{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Mera Quotes API",
    "version": "1.0.0",
    "description": "Local implementation contract. No public host or live merchant credentials have been activated. Public browsing, identity, moderation and payment lifecycle use same-origin browser APIs; app supply uses versioned v1 Bearer keys. Payment and automatic billing are independently gated by approved merchant/operator settings; default is disconnected503. Checkout/confirm/authorization/refund/reconcile and leased renewal commands are implemented, with isolated test transports and no live-provider call claimed. Baseline seed corpus:9 historical excerpts (6 English +3 Korean originals),4 authors,0 translations; actual supply counts are returned by public/stats. Content import preserves quote/proverb/literary_excerpt form, attribution context, exact source-file provenance and separate content/translation review methods; automated source review and pending human operational approval are disclosed. KR/US rights scope only. Production credentials, merchant contracts, final content approval and publishing remain separate launch approvals."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:47631",
      "description": "Local isolated development only; production host not configured."
    }
  ],
  "tags": [
    {
      "name": "Public library"
    },
    {
      "name": "Identity"
    },
    {
      "name": "Participation"
    },
    {
      "name": "Moderation"
    },
    {
      "name": "Developer"
    },
    {
      "name": "Billing"
    },
    {
      "name": "Supply API"
    },
    {
      "name": "Quote studio"
    }
  ],
  "security": [],
  "paths": {
    "/api/public/quotes": {
      "get": {
        "operationId": "publicListQuotes",
        "summary": "Search and browse quotes",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Search and browse quotes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebQuotePage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Public browser library of approved, source-reviewed, rights-cleared, nonexpired quotes with public_display_allowed=true and verified translation review when translated. Website access does not grant a commercial dataset or snapshot license. Public rate limiting applies. Content filters never change attribution: literary excerpts retain their poetic/narrative/character context, and proverbs retain traditional attribution.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Case-insensitive literal substring of text, author or source title; SQL wildcards escaped."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Compatible Korean topic filter. Canonical API labels remain valid; legacy aliases 고독→자기성찰, 단순함→절제, 성장→실천, 진실→정직과 품성 normalize to canonical topics. Prefer category_id for stable integrations."
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages."
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["historical", "original"]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 12
            }
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          },
          {
            "name": "category_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "life",
                "self-reflection",
                "relationships",
                "courage",
                "learning",
                "time",
                "action",
                "judgment",
                "happiness",
                "moderation",
                "integrity",
                "generosity"
              ]
            },
            "description": "Filter by canonical stable topic ID; omission or all selects all topics. The existing category filter remains valid. Topic selection is independent of content_type. Unknown topic filters return400 invalid_filter. If category and category_id are both supplied, list predicates are combined; incompatible filters produce an empty result."
          },
          {
            "name": "length",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["all", "short", "medium", "long"]
            },
            "description": "문장 본문 문자 수(공백·문장부호 포함): short 50자 이하, medium 51~100자, long 101자 이상. 생략 또는 all은 전체. 잘못된 값은 400 invalid_filter."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["card"]
            },
            "description": "웹 카드에 필요한 QuoteCard 컬럼만 조회한다. 생략하면 기존 Quote를 반환한다."
          }
        ]
      }
    },
    "/api/public/random": {
      "get": {
        "operationId": "publicRandomQuote",
        "summary": "Pick one eligible random quote",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Pick one eligible random quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebQuoteResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Public browser library of approved, source-reviewed, rights-cleared, nonexpired quotes with public_display_allowed=true and verified translation review when translated. Website access does not grant a commercial dataset or snapshot license. Public rate limiting applies. Content filters never change attribution: literary excerpts retain their poetic/narrative/character context, and proverbs retain traditional attribution.",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages. An unavailable requested language returns404; no language substitution."
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["card"]
            },
            "description": "웹 카드에 필요한 QuoteCard 컬럼만 조회한다. 생략하면 기존 Quote를 반환한다."
          }
        ]
      }
    },
    "/api/public/today": {
      "get": {
        "operationId": "publicTodayQuote",
        "summary": "Get the stable UTC daily selection",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Get the stable UTC daily selection",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebQuoteResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Public browser library of approved, source-reviewed, rights-cleared, nonexpired quotes with public_display_allowed=true and verified translation review when translated. Website access does not grant a commercial dataset or snapshot license. Public rate limiting applies. Content filters never change attribution: literary excerpts retain their poetic/narrative/character context, and proverbs retain traditional attribution.",
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages. An unavailable requested language returns404; no language substitution."
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["card"]
            },
            "description": "웹 카드에 필요한 QuoteCard 컬럼만 조회한다. 생략하면 기존 Quote를 반환한다."
          }
        ]
      }
    },
    "/api/public/quotes/{id}": {
      "get": {
        "operationId": "publicQuote",
        "summary": "Get quote provenance and rights",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Get quote provenance and rights",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Public browser library of approved, source-reviewed, rights-cleared, nonexpired quotes with public_display_allowed=true and verified translation review when translated. Website access does not grant a commercial dataset or snapshot license. Public rate limiting applies.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/public/changes": {
      "get": {
        "operationId": "publicChanges",
        "summary": "Synchronize quote changes and deletion tombstones",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Synchronize quote changes and deletion tombstones",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangePage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Public browser library of approved, rights-cleared, nonexpired quotes. Website access does not grant a commercial dataset or snapshot license. Public rate limiting applies. Apply ordered upserts/deletes then persist next_cursor in the same local transaction; repeat while has_more. A previously published record that is now unavailable for this supply product is returned as delete. Expiry maintenance must run operationally to mint timely new deletion revisions.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,19}$",
              "default": "0"
            },
            "description": "Last fully committed revision as decimal text. Maximum signed64-bit value."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ]
      }
    },
    "/api/v1/quotes": {
      "get": {
        "operationId": "v1ListQuotes",
        "summary": "Search and browse quotes",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Search and browse quotes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuotePage"
                }
              }
            },
            "headers": {
              "X-Quota-Limit": {
                "description": "Organization monthly success quota.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Remaining": {
                "description": "Remaining successful responses across all organization apps and keys.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Period": {
                "description": "UTC YYYY-MM calendar month.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "402": {
            "$ref": "#/components/responses/Error402"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Approved, source-reviewed, rights-cleared, nonexpired content with verified translation review when translated. A valid app-bound API key and realtime product permission are required. Default/free/commercial keys receive app_display_allowed=true AND commercial_allowed=true records. An administrator-designated internal plan instead uses app_display_allowed=true under the same authentication and bounded quotas; internal designation is not self-service. public_display_allowed is independent. One successful response counts once, independent of page size; empty successful pages also count. All organization apps/rotated keys share one atomic quota. No automatic overage charge. Content filters preserve the actual form and attribution context; literary voices never become personal author statements. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Case-insensitive literal substring of text, author or source title; SQL wildcards escaped."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Compatible Korean topic filter. Canonical API labels remain valid; legacy aliases 고독→자기성찰, 단순함→절제, 성장→실천, 진실→정직과 품성 normalize to canonical topics. Prefer category_id for stable integrations."
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages."
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["historical", "original"]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 12
            }
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          },
          {
            "name": "category_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "life",
                "self-reflection",
                "relationships",
                "courage",
                "learning",
                "time",
                "action",
                "judgment",
                "happiness",
                "moderation",
                "integrity",
                "generosity"
              ]
            },
            "description": "Filter by canonical stable topic ID; omission or all selects all topics. The existing category filter remains valid. Topic selection is independent of content_type. Unknown topic filters return400 invalid_filter. If category and category_id are both supplied, list predicates are combined; incompatible filters produce an empty result."
          },
          {
            "name": "length",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["all", "short", "medium", "long"]
            },
            "description": "문장 본문 문자 수(공백·문장부호 포함): short 50자 이하, medium 51~100자, long 101자 이상. 생략 또는 all은 전체. 잘못된 값은 400 invalid_filter."
          }
        ],
        "x-metering": {
          "unit": "successful-content-response",
          "scope": "organization",
          "atomic": true,
          "period": "UTC calendar month",
          "failed_responses_billed": false,
          "automatic_overage": false
        }
      }
    },
    "/api/v1/quotes/random": {
      "get": {
        "operationId": "v1RandomQuote",
        "summary": "Pick one eligible random quote",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Pick one eligible random quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResult"
                }
              }
            },
            "headers": {
              "X-Quota-Limit": {
                "description": "Organization monthly success quota.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Remaining": {
                "description": "Remaining successful responses across all organization apps and keys.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Period": {
                "description": "UTC YYYY-MM calendar month.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "402": {
            "$ref": "#/components/responses/Error402"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Approved, source-reviewed, rights-cleared, nonexpired content with verified translation review when translated. A valid app-bound API key and realtime product permission are required. Default/free/commercial keys receive app_display_allowed=true AND commercial_allowed=true records. An administrator-designated internal plan instead uses app_display_allowed=true under the same authentication and bounded quotas; internal designation is not self-service. public_display_allowed is independent. One successful response counts once, independent of page size; empty successful pages also count. All organization apps/rotated keys share one atomic quota. No automatic overage charge. Content filters preserve the actual form and attribution context; literary voices never become personal author statements. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "x-metering": {
          "unit": "successful-content-response",
          "scope": "organization",
          "atomic": true,
          "period": "UTC calendar month",
          "failed_responses_billed": false,
          "automatic_overage": false
        },
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages. An unavailable requested language returns404; no language substitution."
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          }
        ]
      }
    },
    "/api/v1/quotes/today": {
      "get": {
        "operationId": "v1TodayQuote",
        "summary": "Get the stable UTC daily selection",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Get the stable UTC daily selection",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodayResult"
                }
              }
            },
            "headers": {
              "X-Quota-Limit": {
                "description": "Organization monthly success quota.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Remaining": {
                "description": "Remaining successful responses across all organization apps and keys.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Period": {
                "description": "UTC YYYY-MM calendar month.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "402": {
            "$ref": "#/components/responses/Error402"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Approved, source-reviewed, rights-cleared, nonexpired content with verified translation review when translated. A valid app-bound API key and realtime product permission are required. Default/free/commercial keys receive app_display_allowed=true AND commercial_allowed=true records. An administrator-designated internal plan instead uses app_display_allowed=true under the same authentication and bounded quotas; internal designation is not self-service. public_display_allowed is independent. One successful response counts once, independent of page size; empty successful pages also count. All organization apps/rotated keys share one atomic quota. No automatic overage charge. Content filters preserve the actual form and attribution context; literary voices never become personal author statements. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "x-metering": {
          "unit": "successful-content-response",
          "scope": "organization",
          "atomic": true,
          "period": "UTC calendar month",
          "failed_responses_billed": false,
          "automatic_overage": false
        },
        "parameters": [
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Language of displayed text (for example ko or en), including reviewed translations. Preserve original_language and translation metadata. Omit or use all for mixed languages. An unavailable requested language returns404; no language substitution."
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["quote", "proverb", "literary_excerpt", "all"]
            },
            "description": "Optional exact content form, independent of kind=historical|original. Omit or use all for all forms. List endpoints return an empty successful page when no records match; today/random return404 instead of silently substituting another content type."
          }
        ]
      }
    },
    "/api/v1/quotes/{id}": {
      "get": {
        "operationId": "v1Quote",
        "summary": "Get quote provenance and rights",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Get quote provenance and rights",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResult"
                }
              }
            },
            "headers": {
              "X-Quota-Limit": {
                "description": "Organization monthly success quota.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Remaining": {
                "description": "Remaining successful responses across all organization apps and keys.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Period": {
                "description": "UTC YYYY-MM calendar month.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "402": {
            "$ref": "#/components/responses/Error402"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Approved, source-reviewed, rights-cleared, nonexpired content with verified translation review when translated. A valid app-bound API key and realtime product permission are required. Default/free/commercial keys receive app_display_allowed=true AND commercial_allowed=true records. An administrator-designated internal plan instead uses app_display_allowed=true under the same authentication and bounded quotas; internal designation is not self-service. public_display_allowed is independent. One successful response counts once, independent of page size; empty successful pages also count. All organization apps/rotated keys share one atomic quota. No automatic overage charge. Content filters preserve the actual form and attribution context; literary voices never become personal author statements. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-metering": {
          "unit": "successful-content-response",
          "scope": "organization",
          "atomic": true,
          "period": "UTC calendar month",
          "failed_responses_billed": false,
          "automatic_overage": false
        }
      }
    },
    "/api/v1/changes": {
      "get": {
        "operationId": "v1Changes",
        "summary": "Synchronize quote changes and deletion tombstones",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Synchronize quote changes and deletion tombstones",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangePage"
                }
              }
            },
            "headers": {
              "X-Quota-Limit": {
                "description": "Organization monthly success quota.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Remaining": {
                "description": "Remaining successful responses across all organization apps and keys.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Quota-Period": {
                "description": "UTC YYYY-MM calendar month.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "402": {
            "$ref": "#/components/responses/Error402"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Approved, source-reviewed, rights-cleared, nonexpired content with verified translation review when translated. A valid app-bound API key and realtime product permission are required. Default/free/commercial keys receive app_display_allowed=true AND commercial_allowed=true records. An administrator-designated internal plan instead uses app_display_allowed=true under the same authentication and bounded quotas; internal designation is not self-service. public_display_allowed is independent. One successful response counts once, independent of page size; empty successful pages also count. All organization apps/rotated keys share one atomic quota. No automatic overage charge. Apply ordered upserts/deletes then persist next_cursor in the same local transaction; repeat while has_more. A previously published record now unavailable for the caller supply channel is returned as delete. Expiry maintenance must run operationally to mint timely deletion revisions. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,19}$",
              "default": "0"
            },
            "description": "Last fully committed revision as decimal text. Maximum signed64-bit value."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "x-metering": {
          "unit": "successful-content-response",
          "scope": "organization",
          "atomic": true,
          "period": "UTC calendar month",
          "failed_responses_billed": false,
          "automatic_overage": false
        }
      }
    },
    "/api/public/stats": {
      "get": {
        "operationId": "publicStats",
        "summary": "Get actual content acquisition counts",
        "tags": ["Public library"],
        "security": [],
        "responses": {
          "200": {
            "description": "Get actual content acquisition counts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stats"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Actual eligible approved/rights-cleared/nonexpired counts, pending proposal count, categories, language counts and content_type_counts. Counts describe the current database, not a promised catalog size or human operational release approval. topics returns canonical {id,label,count} entries; category_id is independent of content_type. Candidate/import staging totals are not live public counts."
      }
    },
    "/api/auth/me": {
      "get": {
        "operationId": "authMe",
        "summary": "Read the verified server session user",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "Read the verified server session user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OptionalUserResult"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Returns user:null for a guest. Session is checked against the database; client role claims are not trusted."
      }
    },
    "/api/auth/register": {
      "post": {
        "operationId": "register",
        "summary": "Create service identity and send verification link",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "202": {
            "description": "Create service identity and send verification link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegisterResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "No session or verification token is returned. Duplicate addresses receive the same generic acceptance wording. SMTP is required in production; local-file means a private ignored outbox, not a sent email. Confirmation is required before login.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/verify": {
      "post": {
        "operationId": "verifyEmail",
        "summary": "Consume a single-use email verification token",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "Consume a single-use email verification token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "GET links never consume a token. Verification token is single-use and expires after1 hour. The response does not log in the user.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "operationId": "login",
        "summary": "Validate credentials and create a real session",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "Validate credentials and create a real session",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResult"
                }
              }
            },
            "headers": {
              "Set-Cookie": {
                "description": "mq_session opaque token; HttpOnly; SameSite=Lax; Path=/; seven-day expiry. Secure in production/HTTPS. Never expose this cookie to JavaScript.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Validate credentials and create a real session",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "operationId": "logout",
        "summary": "Revoke current session and clear cookie",
        "tags": ["Identity"],
        "security": [
          {},
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Revoke current session and clear cookie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Revoke the current session if present and clear its cookie. A guest request can clear a stale cookie; exact-origin CSRF protection still applies.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ]
      }
    },
    "/api/auth/forgot": {
      "post": {
        "operationId": "forgotPassword",
        "summary": "Request a private password reset link",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "202": {
            "description": "Request a private password reset link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Generic response avoids account enumeration. Existing accounts receive a30-minute single-use token. Production SMTP unavailable means503, never a fake sent-mail success.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForgotRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/reset": {
      "post": {
        "operationId": "resetPassword",
        "summary": "Reset password and revoke all sessions",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "Reset password and revoke all sessions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Reset password and revoke all sessions",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/account": {
      "delete": {
        "operationId": "closeAccount",
        "summary": "Close only the Mera Quotes service identity",
        "tags": ["Identity"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Close only the Mera Quotes service identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Requires a session created within the last15 minutes and confirmation DELETE. Anonymizes service PII, closes owned organizations, revokes keys/sessions and clears private saved/unapproved records. Licensed approved attribution, financial/audit history and withdrawal ledger remain under policy. Other Mera apps/shared identities are untouched.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteAccountRequest"
              }
            }
          }
        }
      }
    },
    "/api/me/saved": {
      "get": {
        "operationId": "savedQuotes",
        "summary": "List current user saved eligible quotes",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "List current user saved eligible quotes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedPage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "List current user saved eligible quotes",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ]
      },
      "post": {
        "operationId": "saveQuote",
        "summary": "Save one eligible quote",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Save one eligible quote",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Save one eligible quote",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveRequest"
              }
            }
          }
        }
      }
    },
    "/api/me/saved/{id}": {
      "delete": {
        "operationId": "unsaveQuote",
        "summary": "Remove one current-user bookmark",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Remove one current-user bookmark",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavedResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Remove one current-user bookmark",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ]
      }
    },
    "/api/me/submissions": {
      "get": {
        "operationId": "mySubmissions",
        "summary": "본인 전체 제안 활동 20개 페이지 조회",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "본인 전체 내역 페이지",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "본인 전체 제안 활동 20개 페이지 조회",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["summary"]
            },
            "description": "summary는 제안 payload를 text/kind만 반환한다."
          }
        ]
      },
      "post": {
        "operationId": "submitQuote",
        "summary": "Submit an original, attributed quotation, proverb, literary excerpt or correction for review",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Submit an original, historical quote or correction for review",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Verified account required. No submitted content becomes public before an independent administrator approves both content and rights. Exact/near duplicate detection may return409 with matching public quote IDs; private pending proposal identities are not exposed. Publication and commercial/redistribution consent are independent. content_type and attribution_context preserve the difference between a real author statement, traditional proverb and literary voice. The import batch/source/translation review ledger has no public write endpoint. Translations carry independent translation_rights_license/translation_rights_basis; original-source public-domain rights cannot stand in for translation usage rights. Historical unknown attribution is accepted for independent provenance/rights review; author_status never bypasses those checks. Keep quote_author separate from source_work_author. New user_owned_output translations require verified content import (422 trusted_translation_import_required through direct UGC). Existing AI translation rights cannot be relicensed through a correction (422 translation_rights_changed). Topic input accepts category/category_id; legacy aliases are normalized and conflicting explicit ID/label pairs return422.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributionRequest"
              }
            }
          }
        }
      }
    },
    "/api/public/quotes/{id}/report": {
      "post": {
        "operationId": "reportQuote",
        "summary": "Report rights, attribution or translation concerns",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Report rights, attribution or translation concerns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Report rights, attribution or translation concerns",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/queue": {
      "get": {
        "operationId": "moderationQueue",
        "summary": "List latest200 pending proposals and200 open reports",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "List latest200 pending proposals and200 open reports",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModerationQueue"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Administrator membership is re-read inside the SQL transaction. Reports and private evidence are never public library data.",
        "parameters": [
          {
            "name": "submissions_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "reports_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ]
      }
    },
    "/api/admin/history": {
      "get": {
        "operationId": "auditHistory",
        "summary": "List latest200 moderation audit events",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "List latest200 moderation audit events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Administrator-only event metadata. Full before/after snapshots remain in the private append-only audit store.",
        "parameters": [
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ]
      }
    },
    "/api/admin/submissions/{id}/review": {
      "post": {
        "operationId": "reviewSubmission",
        "summary": "Approve or reject another user proposal",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Approve or reject another user proposal",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReviewResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "No self approval/rejection. Content status, rights clearance, revision/change feed and audit are committed atomically. Stale correction revisions fail409. Approval requires provenance and clearance evidence. New/changed translation approval also requires translation_verified=true after an actual source comparison; missing confirmation returns422 translation_clearance_required. Human review does not reclassify AI-assisted translation authorship or replace independent translation usage rights.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReviewRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/quotes/{id}/withdraw": {
      "post": {
        "operationId": "withdrawQuote",
        "summary": "Withdraw content and mint a deletion tombstone",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Withdraw content and mint a deletion tombstone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WithdrawResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Withdraw content and mint a deletion tombstone",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReasonRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/reports/{id}/resolve": {
      "post": {
        "operationId": "resolveReport",
        "summary": "Resolve an open report with a reason",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Resolve an open report with a reason",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Resolve an open report with a reason",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReasonRequest"
              }
            }
          }
        }
      }
    },
    "/api/billing/plans": {
      "get": {
        "operationId": "pricePlans",
        "summary": "Read draft prices and explicit payment connection state",
        "tags": ["Billing"],
        "security": [],
        "responses": {
          "200": {
            "description": "Read draft prices and explicit payment connection state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlansResult"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Draft pricing and dynamic payment/billing connection booleans. Default disconnected; approved runtime configuration may report true. Optional current snapshot version metadata allows version selection without content access.30 requests/minute/IP. Internal plan is administrator-assigned."
      }
    },
    "/api/developer/workspace": {
      "get": {
        "operationId": "developerWorkspace",
        "summary": "개발자 작업 공간·조직 쿼터·요청 로그·키 감사 조회",
        "tags": ["Developer"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Read current-user organizations, apps, safe key metadata and usage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          }
        },
        "description": "접수 로그를 먼저 영속 저장하고 성공과 계량을 같은 트랜잭션에서 확정한다. pending/102는 결과 미확인, interrupted는 중단·미계량이다. quota_counted는 확정 계량 여부이며 과거 기록의 불명확한 계량은 null로 보존한다. 성공은 클라이언트 수신 완료를 보장하지 않는다. 로그를 준비하거나 확정할 수 없으면 요청 처리/계량을 확정하지 않는다. 조직 RLS·30일 보관·키 감사 계약을 유지한다.",
        "parameters": [
          {
            "name": "organizations_page",
            "in": "query",
            "required": false,
            "description": "organizations 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "apps_page",
            "in": "query",
            "required": false,
            "description": "apps 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "keys_page",
            "in": "query",
            "required": false,
            "description": "keys 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "usage_page",
            "in": "query",
            "required": false,
            "description": "usage 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "entitlements_page",
            "in": "query",
            "required": false,
            "description": "entitlements 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "orders_page",
            "in": "query",
            "required": false,
            "description": "orders 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "subscriptions_page",
            "in": "query",
            "required": false,
            "description": "subscriptions 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "sections",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "쉼표로 구분한 organizations,apps,keys,usage,entitlements,orders,subscriptions,quotas,logs,key_audit 중 선택. 생략하면 전체 조회."
          },
          {
            "name": "logs_page",
            "in": "query",
            "required": false,
            "description": "목록 페이지. quotas는 전체 조직 현황을 반환하며 페이지를 나누지 않는다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "key_audit_page",
            "in": "query",
            "required": false,
            "description": "목록 페이지. quotas는 전체 조직 현황을 반환하며 페이지를 나누지 않는다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "quotas_page",
            "in": "query",
            "required": false,
            "description": "목록 페이지. quotas는 전체 조직 현황을 반환하며 페이지를 나누지 않는다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "log_org_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_app_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_key_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_request_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 100,
              "maximum": 599
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "요청 로그 필터. 시간 범위는 양 끝을 포함하며 시간대가 필요하다. 중복/역전/잘못된 형식은400."
          },
          {
            "name": "log_outcome",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["pending", "succeeded", "failed", "interrupted"]
            }
          }
        ]
      }
    },
    "/api/developer/organizations": {
      "post": {
        "operationId": "createOrganization",
        "summary": "Create a Free organization owned by the current user",
        "tags": ["Developer"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Create a Free organization owned by the current user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Maximum5 organizations per account. Caller cannot choose internal/commercial plan or another owner.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationRequest"
              }
            }
          }
        }
      }
    },
    "/api/developer/apps": {
      "post": {
        "operationId": "createApplication",
        "summary": "Register a consuming app under an owned organization",
        "tags": ["Developer"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Register a consuming app under an owned organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApplicationResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Owner required. Maximum20 apps per organization. App identity is distinct from user login and organization subscription.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApplicationRequest"
              }
            }
          }
        }
      }
    },
    "/api/developer/keys": {
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an app-bound key and display it once",
        "tags": ["Developer"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Create an app-bound key and display it once",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Owner and app-organization match required. Maximum20 active keys per organization. Store only SHA256 hash; plaintext exists in this one response. Rotating/adding keys does not reset organization quota.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeyRequest"
              }
            }
          }
        }
      }
    },
    "/api/developer/keys/{id}": {
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an owned organization key",
        "tags": ["Developer"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Revoke an owned organization key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokedResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Revoke an owned organization key",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ]
      }
    },
    "/api/billing/checkout": {
      "post": {
        "operationId": "checkout",
        "summary": "Create an idempotent pending merchant checkout",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Default configuration returns503 with no order/payment/entitlement. After separately approved activation, verified recent owner creates a pending10-minute checkout; snapshot uses one-time payment, realtime uses separately approved automatic billing. Product/price/quota/terms/version are fixed in the order. Replays retain the original intent and state bound to the initiating session. A browser SDK return never directly grants rights.",
        "responses": {
          "201": {
            "description": "Create an idempotent pending merchant checkout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match service origin for state-changing browser requests."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[-A-Za-z0-9_]{8,200}$"
            },
            "description": "Persist one key per purchase intent; retry the same intent with the same key. Mismatched product/version/terms returns409. Refund commands are additionally fixed to the refund request ID."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/billing/cancel": {
      "post": {
        "operationId": "cancelSubscription",
        "summary": "Mark an existing commercial subscription to end at period close",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mark an existing commercial subscription to end at period close",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Stops future renewal intent. Preserves current paid rights until period end. An already-started network charge can still be reconciled; charge_in_flight makes that race explicit. Requires actual owner and recent15-minute login.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationIdRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/billing/refund-request": {
      "post": {
        "operationId": "requestRefund",
        "summary": "Request review of a paid order refund",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "202": {
            "description": "Request review of a paid order refund",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Recent organization owner requests review of a paid/partially refunded order.202 is pending review, not a refund. A separate administrator chooses and approves amount/reason. Pending requests are replay-safe.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefundRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/webhooks/payment": {
      "post": {
        "operationId": "paymentWebhook",
        "summary": "Reject payment events while provider adapter is disconnected",
        "tags": ["Billing"],
        "security": [],
        "responses": {
          "200": {
            "description": "Verified notice processed, replay acknowledged or terminal update ignored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Default disconnected503 issues no rights. Approved merchant configuration may acknowledge200 only after authenticated provider lookup verifies payment key, stored order, fixed amount/currency, merchant and status. General Toss payment notices have no assumed generic HMAC signature. Notice JSON only wakes reconciliation; event IDs/payload hashes make replay safe, terminal refunds/cancellations cannot be undone by delayed success. Exact-origin CSRF exception is limited to this webhook, guarded60 requests/minute/IP. Supported event registration is PAYMENT_STATUS_CHANGED only for the domestic CARD/BILLING scope. CANCEL_STATUS_CHANGED and BILLING_DELETED are not accepted by this endpoint; definitive billing-credential failures are handled by the worker/provider lookup contract.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookRequest"
              }
            }
          }
        }
      }
    },
    "/api/v1/revocations": {
      "get": {
        "operationId": "revocations",
        "summary": "Read unmetered deletion feed for offline cleanup",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Read unmetered deletion feed for offline cleanup",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevocationPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Requires a valid unrevoked app key and active organization/owner, but no active realtime or snapshot subscription. Remains available after product expiry. Returns delete for unavailable content and invalidate with delete_before_revision for corrected eligible content. Delete all local records/assets for delete; delete older revisions for invalidate. Atomically persist next_cursor after cleanup and repeat while has_more. Does not return replacement quote text or consume monthly realtime quota. Abuse guard:120 requests/minute/organization. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,18}$",
              "default": "0"
            },
            "description": "Last fully committed revision as decimal text. Maximum signed64-bit value."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ]
      }
    },
    "/api/v1/exports/manifest": {
      "get": {
        "operationId": "snapshotManifest",
        "summary": "Inspect the current immutable snapshot metadata",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Inspect the current immutable snapshot metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManifestResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "Valid key required. Content is not included. The server may materialize/cache the deterministic version artifact. Does not grant download rights and does not consume realtime quota. Manifest binds checksum to exact download response bytes, rights territory, cursor and withdrawal policy. Abuse guard:10 requests/minute/organization, unmetered for monthly realtime quota. rights_territory_policy=intersection_of_record_territories declares that rights_territory is the intersection of all supplied record scopes. An empty intersection returns409 no_common_territory instead of creating a file with an invented or broader scope. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다."
      }
    },
    "/api/v1/exports/{version}": {
      "get": {
        "operationId": "downloadSnapshot",
        "summary": "Download an explicitly licensed fixed snapshot version",
        "tags": ["Supply API"],
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Download an explicitly licensed fixed snapshot version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            },
            "headers": {
              "X-Checksum-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                },
                "description": "SHA256 of exact UTF-8 response bytes; compare with manifest before parsing or installing."
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                },
                "description": "Attachment filename includes the immutable version."
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "A separate active snapshot entitlement must match this exact version, even for internal organizations. Realtime subscription alone is insufficient. Verifies persisted checksum and current eligibility/revision of every record; withdrawn/expired/corrected content causes410 for the old version. Logs organization/app/version download for impact tracking. Not billed as realtime calls. Does not technically recall files already received; consume revocation feed before use and at least daily. Abuse guard:10 requests/minute/organization, unmetered for monthly realtime quota. Snapshot content uses the reviewed base with app_display_allowed=true and redistribution_allowed=true independently of commercial_allowed or public_display_allowed; a paid API subscription or internal plan does not grant this version entitlement. 요청 접수 로그를 영속 저장한 뒤 처리하며 성공 결과와 계량은 원자적으로 확정한다. 로그 저장 불가 시503으로 중단한다. 프로세스 종료 후 pending/interrupted 또는 확정 결과를 요청 ID로 조회할 수 있다. 성공 로그는 응답 수신 완료를 보장하지 않는다.",
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^v1-[0-9]+-[a-f0-9]{16}$"
            }
          }
        ]
      }
    },
    "/api/billing/confirm": {
      "post": {
        "operationId": "confirmCheckout",
        "summary": "Confirm one-time checkout and verify provider state",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Recent originating owner, exact fixed amount and session/order state required. Durable payment command reserves a provider idempotency key before HTTP. Provider confirm is followed by independent lookup. Expired gateway intents with prior uncertain execution become lookup-only; no new confirm after expiry. Unconfigured merchant503; no real provider call has been executed by this delivery.",
        "responses": {
          "200": {
            "description": "Confirm one-time checkout and verify provider state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentOrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match service origin for state-changing browser requests."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/billing/authorize": {
      "post": {
        "operationId": "authorizeBilling",
        "summary": "Authorize automatic billing and verify first charge",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Recent originating owner and matching customer/state required. Automatic billing approval plus encryption configuration are independently required. Billing key is stored AES-256-GCM with org/version AAD; only safe order returned. Saved command/lease/idempotency protects issuance and first charge; uncertain execution is reconciled before retry. Unconfigured503. No real merchant enrollment/charge has been performed.",
        "responses": {
          "200": {
            "description": "Authorize automatic billing and verify first charge",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentOrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match service origin for state-changing browser requests."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorizeRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/billing/reconcile": {
      "post": {
        "operationId": "reconcileCheckout",
        "summary": "Recover a payment by authenticated provider lookup only",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Recent actual organization owner. With state, verifies the originating checkout; without state, owner recovery remains available after gateway10-minute expiry/session change. This endpoint performs lookup and local reconciliation only, even beyond provider15-day POST idempotency retention; it never issues new approval, billing credential, charge or refund. Unconfigured503.",
        "responses": {
          "200": {
            "description": "Recover a payment by authenticated provider lookup only",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentOrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match service origin for state-changing browser requests."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReconcileRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900
      }
    },
    "/api/billing/orders/{id}": {
      "get": {
        "operationId": "ownedOrder",
        "summary": "Read an owner-safe stored order",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Organization owner required. Read only, no provider call and no recent-login gate. Omits provider references and all checkout/credential/command secrets.",
        "responses": {
          "200": {
            "description": "Read an owner-safe stored order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentOrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/billing/admin/refunds": {
      "get": {
        "operationId": "refundReviewQueue",
        "summary": "List pending refund requests and policy limits",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Administrator role re-read from DB and recent15-minute session required. Up to200 pending requests with remaining/full/partial refund limits and affected snapshot download count. No financial operation occurs.",
        "responses": {
          "200": {
            "description": "List pending refund requests and policy limits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundReviewList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "x-required-role": "database-admin",
        "x-recent-login-seconds": 900,
        "parameters": [
          {
            "name": "refunds_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ]
      }
    },
    "/api/billing/admin/refunds/{id}/approve": {
      "post": {
        "operationId": "approveRefund",
        "summary": "Approve a full or permitted partial refund",
        "tags": ["Billing"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "description": "Requires explicit independent administrator+recent login, fixed request amount/reason and Idempotency-Key. Full remaining refund is an explicit administrator exception; partial realtime refund is capped to unused original period, snapshot partial refund rejected. Durable command and authenticated provider lookup protect cancellation/replay. Completion requires verified cumulative provider refund; terminal state wins over delayed success. Default disconnected503, no real refund claimed.",
        "responses": {
          "200": {
            "description": "Approve a full or permitted partial refund",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentOrderResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "410": {
            "$ref": "#/components/responses/Error410"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match service origin for state-changing browser requests."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[-A-Za-z0-9_]{8,200}$"
            },
            "description": "Persist one key per purchase intent; retry the same intent with the same key. Mismatched product/version/terms returns409. Refund commands are additionally fixed to the refund request ID."
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefundApprovalRequest"
              }
            }
          }
        },
        "x-recent-login-seconds": 900,
        "x-required-role": "database-admin"
      }
    },
    "/api/admin/quotes": {
      "get": {
        "operationId": "adminListQuotes",
        "summary": "Search all quotes including withdrawn and nonpublic records",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Search all quotes including withdrawn and nonpublic records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminQuotePage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "content_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "length",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["all", "short", "medium", "long"]
            },
            "description": "문장 본문 문자 수(공백·문장부호 포함): short 50자 이하, medium 51~100자, long 101자 이상. 생략 또는 all은 전체. 잘못된 값은 400 invalid_filter."
          }
        ]
      }
    },
    "/api/admin/quotes/{id}": {
      "get": {
        "operationId": "adminGetQuote",
        "summary": "Read a quote with private evidence and latest 50 before/after audit entries",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Read a quote with private evidence and latest 50 before/after audit entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminQuoteDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["summary"]
            },
            "description": "summary는 이력의 before/after 본문을 제외한다."
          }
        ]
      },
      "patch": {
        "operationId": "adminEditQuote",
        "summary": "Save an audited correction with atomic revision and idempotency checks",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Save an audited correction with atomic revision and idempotency checks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminQuoteEditResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminQuoteEditRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/resend": {
      "post": {
        "operationId": "resendVerification",
        "summary": "확인 메일 재발송",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "202": {
            "description": "Request a private password reset link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "미확인 활성 계정만 새 단회 링크를 발송한다. 계정 존재 여부를 노출하지 않으며 로컬 메일은 비공개 파일에만 보관한다.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForgotRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/providers": {
      "get": {
        "operationId": "authProviders",
        "summary": "로그인 수단 설정 상태",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "공개 로그인 수단과 설정 상태",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["providers"],
                  "properties": {
                    "providers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": ["id", "label", "enabled"],
                        "properties": {
                          "id": {
                            "type": "string",
                            "enum": ["google", "apple"]
                          },
                          "label": {
                            "type": "string"
                          },
                          "enabled": {
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": false
                      }
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/auth/oauth/google": {
      "post": {
        "operationId": "startGoogleLogin",
        "summary": "Google 인증 시작",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "공급자 인증 주소",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["url"],
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "같은 Origin과 약관 동의를 확인하고 10분 단회 state와 HttpOnly 브라우저 쿠키를 생성한다. intent=link는 최근15분 로그인과 서버 계정을 요구한다. 미설정은503, 외부 복귀 주소는 /account로 제한한다.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthStartRequest"
              }
            }
          }
        }
      }
    },
    "/api/auth/oauth/apple": {
      "post": {
        "operationId": "startAppleLogin",
        "summary": "Apple 인증 시작",
        "tags": ["Identity"],
        "security": [],
        "responses": {
          "200": {
            "description": "공급자 인증 주소",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["url"],
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "description": "같은 Origin과 약관 동의를 확인하고 10분 단회 state와 HttpOnly 브라우저 쿠키를 생성한다. intent=link는 최근15분 로그인과 서버 계정을 요구한다. 미설정은503, 외부 복귀 주소는 /account로 제한한다.",
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthStartRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/acquisitions": {
      "get": {
        "operationId": "adminListAcquisitions",
        "summary": "Search private acquisition candidates and source holds",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Search private acquisition candidates and source holds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcquisitionPage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dataset_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "translation_status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rights_status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "editorial_status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "publication_status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "content_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "sources_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "datasets_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ]
      }
    },
    "/api/admin/acquisitions/{id}": {
      "get": {
        "operationId": "adminGetAcquisition",
        "summary": "Read frozen original, rights evidence, duplicates and edit history",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Read frozen original, rights evidence, duplicates and edit history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcquisitionDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "20개 단위 페이지. 범위 밖에서도 실제 총수를 반환한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["summary"]
            },
            "description": "summary는 이력의 before/after 본문을 제외한다."
          }
        ]
      },
      "patch": {
        "operationId": "adminEditAcquisition",
        "summary": "Save private review corrections without publishing",
        "tags": ["Moderation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Save private review corrections without publishing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcquisitionEditResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "503": {
            "$ref": "#/components/responses/Error503"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcquisitionEditRequest"
              }
            }
          }
        }
      }
    },
    "/api/public/quotes/{id}/reactions": {
      "get": {
        "operationId": "quoteReactions",
        "summary": "문장 반응 조회",
        "tags": ["Participation"],
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "공개 집계와 본인 상태. 익명 liked/saved=false, version=0. 관계 사용자 목록은 제공하지 않음.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteReactions"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/me/likes/{id}": {
      "put": {
        "operationId": "setQuoteLike",
        "summary": "문장 좋아요 상태 변경",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "responses": {
          "200": {
            "description": "공개 집계와 본인 상태. 익명 liked/saved=false, version=0. 관계 사용자 목록은 제공하지 않음.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteReactions"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": ["liked", "version"],
                "properties": {
                  "liked": {
                    "type": "boolean"
                  },
                  "version": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483646
                  }
                }
              }
            }
          }
        },
        "description": "현재 version과 원하는 liked를 전송한다. 오래된 버전은409. 자동 재전송 없이 현재 상태를 재조회한다."
      }
    },
    "/api/public/quotes/{id}/interpretations": {
      "get": {
        "operationId": "publicReadInterpretations",
        "summary": "기본 해석·본인 해석·수정 이력 조회",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "다른 작성자의 해석 페이지. 기본/본인 해석은 별도 유지한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "본인 또는 관리자 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["0"]
            },
            "description": "0이면 이력 본문을 조회하지 않고 총수만 반환한다."
          },
          {
            "name": "only",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["history"]
            },
            "description": "history이면 해석 본문을 제외하고 이력만 조회한다."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["editor"]
            },
            "description": "일반 편집기는 다른 사용자 해석을 별도 공개 피드로 조회한다."
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. data·history·user_publication_enabled=true. 공개 경로는 검토 완료 기본 해석과 approved+published 사용자 해석을 제공하며 작성자/검토자 계정 ID를 제외한다. 본인 경로는 본인 해석, 관리자 경로는 검토 대상과 이력을 포함한다. 목록과 이력은 20개 단위이며 pagination/history_pagination을 포함한다."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/me/quotes/{id}/interpretations": {
      "get": {
        "operationId": "meReadInterpretations",
        "summary": "기본 해석·본인 해석·수정 이력 조회",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "다른 작성자의 해석 페이지. 기본/본인 해석은 별도 유지한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "본인 또는 관리자 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["0"]
            },
            "description": "0이면 이력 본문을 조회하지 않고 총수만 반환한다."
          },
          {
            "name": "only",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["history"]
            },
            "description": "history이면 해석 본문을 제외하고 이력만 조회한다."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["editor"]
            },
            "description": "일반 편집기는 다른 사용자 해석을 별도 공개 피드로 조회한다."
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. data·history·user_publication_enabled=true. 공개 경로는 검토 완료 기본 해석과 approved+published 사용자 해석을 제공하며 작성자/검토자 계정 ID를 제외한다. 본인 경로는 본인 해석, 관리자 경로는 검토 대상과 이력을 포함한다. 목록과 이력은 20개 단위이며 pagination/history_pagination을 포함한다."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "put": {
        "operationId": "meChangeInterpretation",
        "summary": "해석 작성·수정·삭제·검토",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. data·history·user_publication_enabled=true. 공개 경로는 검토 완료 기본 해석과 approved+published 사용자 해석을 제공하며 작성자/검토자 계정 ID를 제외한다. 본인 경로는 본인 해석, 관리자 경로는 검토 대상과 이력을 포함한다."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["version", "action", "body", "ai_assisted"],
                    "properties": {
                      "version": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2147483646
                      },
                      "action": {
                        "const": "write"
                      },
                      "body": {
                        "type": "string",
                        "minLength": 20,
                        "maxLength": 2000
                      },
                      "ai_assisted": {
                        "type": "boolean"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["version", "action"],
                    "properties": {
                      "version": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2147483646
                      },
                      "action": {
                        "enum": ["delete"]
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "description": "서버 계정 재검증. version 충돌409. write는 본문과 AI 여부 필수, 나머지는 금지. 기본 해석 작성은 draft, 사용자 해석 작성은 pending. 사용자 공개 게이트는 닫힘. 삭제는 과거 본문도 제거. 시간당20회 제한. 자동 재전송 금지."
      }
    },
    "/api/admin/quotes/{id}/interpretations": {
      "get": {
        "operationId": "adminReadInterpretations",
        "summary": "기본 해석·본인 해석·수정 이력 조회",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "다른 작성자의 해석 페이지. 기본/본인 해석은 별도 유지한다.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history_page",
            "in": "query",
            "required": false,
            "description": "본인 또는 관리자 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "history",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["0"]
            },
            "description": "0이면 이력 본문을 조회하지 않고 총수만 반환한다."
          },
          {
            "name": "only",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["history"]
            },
            "description": "history이면 해석 본문을 제외하고 이력만 조회한다."
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["editor"]
            },
            "description": "일반 편집기는 다른 사용자 해석을 별도 공개 피드로 조회한다."
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. data·history·user_publication_enabled=true. 공개 경로는 검토 완료 기본 해석과 approved+published 사용자 해석을 제공하며 작성자/검토자 계정 ID를 제외한다. 본인 경로는 본인 해석, 관리자 경로는 검토 대상과 이력을 포함한다. 목록과 이력은 20개 단위이며 pagination/history_pagination을 포함한다."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "put": {
        "operationId": "adminChangeInterpretation",
        "summary": "해석 작성·수정·삭제·검토",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["basic", "user"],
              "default": "user"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "사용자 해석 검토 대상 작성자. 다른 사용자의 본문 편집·삭제는 금지."
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. data·history·user_publication_enabled=true. 공개 경로는 검토 완료 기본 해석과 approved+published 사용자 해석을 제공하며 작성자/검토자 계정 ID를 제외한다. 본인 경로는 본인 해석, 관리자 경로는 검토 대상과 이력을 포함한다."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["version", "action", "body", "ai_assisted"],
                    "properties": {
                      "version": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2147483646
                      },
                      "action": {
                        "const": "write"
                      },
                      "body": {
                        "type": "string",
                        "minLength": 20,
                        "maxLength": 2000
                      },
                      "ai_assisted": {
                        "type": "boolean"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["version", "action"],
                    "properties": {
                      "version": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2147483646
                      },
                      "action": {
                        "enum": ["delete", "approve", "reject"]
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "description": "서버 계정 재검증. version 충돌409. write는 본문과 AI 여부 필수, 나머지는 금지. 기본 해석 작성은 draft, 사용자 해석 작성은 pending. 사용자 공개 게이트는 닫힘. 삭제는 과거 본문도 제거. 시간당20회 제한. 자동 재전송 금지."
      }
    },
    "/api/public/quotes/{id}/interpretations/feed": {
      "get": {
        "operationId": "interpretationFeed",
        "summary": "개별 공개된 해석 안정 정렬·페이지",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["popular", "latest"],
              "default": "popular"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. 기본 해석 별도, 사용자 해석10개. 계정ID/이력 제외. 목록 revision 변경 시409. 공개120/60초.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterpretationFeed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/public/interpretations/{id}/reactions": {
      "get": {
        "operationId": "interpretationReactions",
        "summary": "공개 해석 집계·본인 관계",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterpretationReaction"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/me/interpretations/{id}/like": {
      "put": {
        "operationId": "likeInterpretation",
        "summary": "해석 좋아요·취소",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "현재 서비스와 정확히 같은 Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. 확인된 활성 계정·같은 Origin. 자기 좋아요403, 비공개404, 중복/역순409.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterpretationReaction"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretationLikeInput"
              }
            }
          }
        }
      }
    },
    "/api/me/interpretations/{id}/report": {
      "post": {
        "operationId": "reportInterpretation",
        "summary": "해석 신고 접수",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "현재 서비스와 정확히 같은 Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. 확인된 활성 계정·같은 Origin. {received:true,status}. 동일 내용 중복은 기존 결과, 다른 내용409. 접수는 숨김 아님. 시간당10회."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretationReportInput"
              }
            }
          }
        }
      }
    },
    "/api/admin/interpretations/{id}/moderate": {
      "put": {
        "operationId": "moderateInterpretation",
        "summary": "해석 숨김·복구·개별 공개",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "현재 서비스와 정확히 같은 Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. DB 관리자 재검증·같은 Origin·사유·버전·원자적 감사. {confirmed:true,version,status}. 숨김 복구는 pending/draft, 개별 공개는 사용자 approved만."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretationModerateInput"
              }
            }
          }
        }
      }
    },
    "/api/admin/quotes/{id}/interpretations/moderation": {
      "get": {
        "operationId": "interpretationModeration",
        "summary": "신고 목록·운영 감사 조회",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "reports_page",
            "in": "query",
            "required": false,
            "description": "신고 목록 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "audit_page",
            "in": "query",
            "required": false,
            "description": "운영 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. DB 관리자만 {reports,audit}. 공개/다른 계정에 노출하지 않음. 신고자/행위자 계정ID 제외."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/admin/interpretation-reports/{id}": {
      "put": {
        "operationId": "resolveInterpretationReport",
        "summary": "해석 신고 처리·기각",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "현재 서비스와 정확히 같은 Origin"
          }
        ],
        "responses": {
          "200": {
            "description": "private/no-store. DB 관리자·같은 Origin. open에서만 전이. {confirmed:true,status,version}. 숨김과 독립적."
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "description": "버전/상태/목록 변경 충돌. 자동 재전송 없이 GET 확인."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretationResolveInput"
              }
            }
          }
        }
      }
    },
    "/api/me/profile": {
      "get": {
        "operationId": "getServiceProfile",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 현재 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceProfileResult"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "확인된 활성 계정 필요"
          },
          "500": {
            "description": "안전한 일반 오류. SQL·비밀·개인 본문은 반환하지 않음"
          }
        }
      },
      "put": {
        "operationId": "updateServiceProfile",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 현재 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceProfileResult"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "확인된 활성 계정 필요"
          },
          "409": {
            "description": "버전 충돌. GET 확인 후 사용자 재선택"
          },
          "500": {
            "description": "안전한 일반 오류. SQL·비밀·개인 본문은 반환하지 않음"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServiceProfileRequest"
              }
            }
          }
        }
      }
    },
    "/api/me/library": {
      "get": {
        "operationId": "getPersonalLibrary",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 현재 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalPage"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "확인된 활성 계정 필요"
          },
          "500": {
            "description": "안전한 일반 오류. SQL·비밀·개인 본문은 반환하지 않음"
          }
        },
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["saved", "likes", "interpretation-likes", "interpretations"]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "view",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["card"]
            },
            "description": "카드 표시 컬럼만 조회한다. 기본은 상세 공개 문장이다."
          }
        ],
        "description": "세션 본인 기록만 조회. user/org 쿼리 거부. 숨김/삭제 해석 및 공개 불가 원문 제외. 비공개 내 해석은 본인에게만 공개. 과거 본문/타인 계정ID 없음."
      }
    },
    "/api/me/contributor": {
      "get": {
        "operationId": "readContributorBenefits",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorBenefits"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "versions_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            },
            "description": "20개 단위 페이지"
          },
          {
            "name": "appeals_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            },
            "description": "20개 단위 페이지"
          }
        ]
      }
    },
    "/api/me/contributor/refresh": {
      "post": {
        "operationId": "refreshContributorBenefits",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorBenefits"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributorEmpty"
              }
            }
          }
        }
      }
    },
    "/api/me/contributor/claim": {
      "post": {
        "operationId": "claimContributorLicense",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorIssued"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributorClaimRequest"
              }
            }
          }
        }
      }
    },
    "/api/me/contributor/appeal": {
      "post": {
        "operationId": "appealContributorSuspension",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorAppealReceived"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributorAppealRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/contributors": {
      "get": {
        "operationId": "readContributorAdministration",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorAdmin"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "exports_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            },
            "description": "20개 단위 페이지"
          }
        ]
      }
    },
    "/api/admin/contributors/catalog": {
      "put": {
        "operationId": "mapContributorSnapshot",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorUpdated"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributorCatalogRequest"
              }
            }
          }
        }
      }
    },
    "/api/admin/contributors/{userId}": {
      "put": {
        "operationId": "moderateContributor",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContributorUpdated"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "userId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContributorModerationRequest"
              }
            }
          }
        }
      }
    },
    "/api/me/contributor/downloads/{version}": {
      "get": {
        "operationId": "downloadContributorSnapshot",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            },
            "headers": {
              "X-Content-SHA256": {
                "schema": {
                  "type": "string"
                },
                "description": "응답 bytes의 SHA256"
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "410": {
            "description": "철회/만료/수정된 파일 재다운로드 차단"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/me/contributor/revocations": {
      "get": {
        "operationId": "readContributorRevocations",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevocationPage"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "계정/조직/기여자/관리자 권한 확인 필요"
          },
          "409": {
            "description": "현재 상태/버전 충돌. GET만 확인"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "안전한 일반 오류"
          }
        },
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ]
      }
    },
    "/api/me/reading-settings": {
      "get": {
        "operationId": "getReadingSettings",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 현재 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadingSettingsResult"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "확인된 활성 계정 필요"
          },
          "500": {
            "description": "안전한 일반 오류. SQL·비밀·개인 본문은 반환하지 않음"
          }
        }
      },
      "put": {
        "operationId": "updateReadingSettings",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 현재 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadingSettingsResult"
                }
              }
            }
          },
          "400": {
            "description": "입력 오류"
          },
          "401": {
            "description": "로그인 필요"
          },
          "403": {
            "description": "확인된 활성 계정 필요"
          },
          "409": {
            "description": "버전 충돌. GET 확인 후 사용자 재선택"
          },
          "500": {
            "description": "안전한 일반 오류. SQL·비밀·개인 본문은 반환하지 않음"
          }
        },
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadingSettings"
              }
            }
          }
        }
      }
    },
    "/api/admin/quotes/{id}/interpretations/generate": {
      "post": {
        "operationId": "generateBasicInterpretation",
        "summary": "관리자 AI 기본 해석 미저장 초안 생성",
        "tags": ["Participation"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Must exactly match this service origin for every browser state-changing request. Cookie SameSite is additional protection, not a replacement."
          }
        ],
        "responses": {
          "200": {
            "description": "미저장 AI 보조 편집 초안",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["body", "ai_assisted", "responsibility", "version", "saved"],
                  "properties": {
                    "body": {
                      "type": "string",
                      "minLength": 20,
                      "maxLength": 2000
                    },
                    "ai_assisted": {
                      "const": true
                    },
                    "responsibility": {
                      "const": "메라 문장 편집팀"
                    },
                    "version": {
                      "type": "integer"
                    },
                    "saved": {
                      "const": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "405": {
            "$ref": "#/components/responses/Error405"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "413": {
            "$ref": "#/components/responses/Error413"
          },
          "415": {
            "$ref": "#/components/responses/Error415"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "502": {
            "description": "생성 실패, 기존 저장 해석 유지"
          },
          "503": {
            "description": "로컬 모델 연결 대기"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": ["version"],
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          }
        },
        "description": "로컬 모델 연결 대기503/실패502. 생성 전후 관리자·문장·version 재검증. 자동 저장/공개 없음. 시간당10회/20초 제한."
      }
    },
    "/api/locale": {
      "post": {
        "operationId": "setSiteLocale",
        "summary": "사이트 표시 언어 저장",
        "description": "로그인 없이 같은 Origin 요청으로 한국어·영어 UI 언어만 설정한다. 명언 콘텐츠 언어와 계정 권한은 변경하지 않는다. HttpOnly·SameSite=Lax 쿠키를 1년 저장하고 HTTPS에서는 Secure를 적용한다. 응답은 private/no-store다. 임의 복귀 주소를 받지 않는다.",
        "tags": ["Public library"],
        "security": [],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LocalePreference"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "저장한 표시 언어",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocalePreference"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/Error400"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/admin/quotes/{id}/history": {
      "get": {
        "summary": "관리자 이력 메타데이터 페이지 또는 선택한 한 건의 변경 본문",
        "tags": ["Admin"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "20개 단위 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "record",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,19}$"
            },
            "description": "선택한 이력 번호. 대상과 관리자 권한을 다시 확인한다."
          }
        ],
        "responses": {
          "200": {
            "description": "목록은 본문을 제외한다. record 지정 시 한 건의 before/after만 반환한다.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AdminQuoteHistoryPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "record": {
                          "$ref": "#/components/schemas/AdminQuoteHistory"
                        }
                      },
                      "required": ["record"],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "로그인이 필요합니다."
          },
          "403": {
            "description": "관리자 또는 소유자 권한이 필요합니다."
          },
          "404": {
            "description": "대상을 찾을 수 없습니다."
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "operationId": "read_api_admin_quotes__id__history",
        "security": [
          {
            "SessionCookie": []
          }
        ]
      }
    },
    "/api/admin/acquisitions/{id}/history": {
      "get": {
        "summary": "관리자 이력 메타데이터 페이지 또는 선택한 한 건의 변경 본문",
        "tags": ["Admin"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "20개 단위 이력 페이지",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100000,
              "default": 1
            }
          },
          {
            "name": "record",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,19}$"
            },
            "description": "선택한 이력 번호. 대상과 관리자 권한을 다시 확인한다."
          }
        ],
        "responses": {
          "200": {
            "description": "목록은 본문을 제외한다. record 지정 시 한 건의 before/after만 반환한다.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/AcquisitionHistoryPage"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "record": {
                          "$ref": "#/components/schemas/AcquisitionHistoryRecord"
                        }
                      },
                      "required": ["record"],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "로그인이 필요합니다."
          },
          "403": {
            "description": "관리자 또는 소유자 권한이 필요합니다."
          },
          "404": {
            "description": "대상을 찾을 수 없습니다."
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "operationId": "read_api_admin_acquisitions__id__history",
        "security": [
          {
            "SessionCookie": []
          }
        ]
      }
    },
    "/api/me/submissions/{id}": {
      "get": {
        "summary": "본인 제안 단건 조회",
        "tags": ["Personal"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "현재 페이지와 무관하게 본인 제안 원본을 반환한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmissionResult"
                }
              }
            }
          },
          "401": {
            "description": "로그인이 필요합니다."
          },
          "404": {
            "description": "대상을 찾을 수 없습니다."
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        },
        "operationId": "read_api_me_submissions__id_",
        "security": [
          {
            "SessionCookie": []
          }
        ]
      }
    },
    "/api/me/studio": {
      "get": {
        "operationId": "studio1",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioView"
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        }
      }
    },
    "/api/me/studio/jobs": {
      "post": {
        "operationId": "studio2",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "현재 서비스와 정확히 같은 Origin이어야 합니다."
          }
        ],
        "responses": {
          "202": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioJob"
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudioInput"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "studio3",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "request_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/StudioJob"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["job"]
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        }
      }
    },
    "/api/me/studio/jobs/{id}": {
      "get": {
        "operationId": "studio4",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioJob"
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        }
      }
    },
    "/api/me/studio/jobs/{id}/cancel": {
      "post": {
        "operationId": "studio5",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "현재 서비스와 정확히 같은 Origin이어야 합니다."
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cancel_requested": {
                      "const": true
                    }
                  },
                  "required": ["cancel_requested"]
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudioEmpty"
              }
            }
          }
        }
      }
    },
    "/api/me/studio/works": {
      "post": {
        "operationId": "studio6",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "현재 서비스와 정확히 같은 Origin이어야 합니다."
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioWork"
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudioSave"
              }
            }
          }
        }
      }
    },
    "/api/me/studio/works/{id}": {
      "put": {
        "operationId": "studio7",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "현재 서비스와 정확히 같은 Origin이어야 합니다."
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioWork"
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudioEdit"
              }
            }
          }
        }
      }
    },
    "/api/me/studio/works/{id}/history": {
      "get": {
        "operationId": "studio8",
        "summary": "비공개 문장 창작",
        "tags": ["Quote studio"],
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "서버 확정 상태. private/no-store",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "version": {
                            "type": "integer"
                          },
                          "body": {
                            "type": "string"
                          },
                          "meaning_anchor": {
                            "type": "string"
                          },
                          "action": {
                            "enum": ["save", "edit", "delete"]
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": []
                      }
                    },
                    "page": {
                      "type": "integer"
                    }
                  },
                  "required": ["data", "page"]
                }
              }
            }
          },
          "400": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "401": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "403": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "404": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "405": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "409": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "429": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "500": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          },
          "503": {
            "description": "공통 오류. 변경을 자동 재전송하지 말고 GET으로 확인합니다."
          }
        }
      }
    },
    "/api/v1/sync/manifest": {
      "get": {
        "operationId": "appSyncManifest",
        "tags": ["Developer"],
        "summary": "앱 동기화 정책",
        "description": "별도 앱별 동기화 허가와 서버 보관 앱 키가 필요하다. 실시간 호출량은 차감하지 않고 조직별 별도 제한을 적용한다. 응답 checksum은 HTTP 응답 bytes의 SHA-256이다. removals는 새 본문·이용기간을 제공하지 않는다.",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncManifest"
                }
              }
            },
            "headers": {
              "X-Checksum-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              },
              "Cache-Control": {
                "schema": {
                  "const": "private, no-store"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sync/download": {
      "get": {
        "operationId": "appSyncDownload",
        "tags": ["Developer"],
        "summary": "전체 다운로드·선택적 스냅샷",
        "description": "별도 앱별 동기화 허가와 서버 보관 앱 키가 필요하다. 실시간 호출량은 차감하지 않고 조직별 별도 제한을 적용한다. 응답 checksum은 HTTP 응답 bytes의 SHA-256이다. removals는 새 본문·이용기간을 제공하지 않는다.",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncDownload"
                }
              }
            },
            "headers": {
              "X-Checksum-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              },
              "Cache-Control": {
                "schema": {
                  "const": "private, no-store"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sync/changes": {
      "get": {
        "operationId": "appSyncChanges",
        "tags": ["Developer"],
        "summary": "로컬 복제본 증분 업데이트",
        "description": "별도 앱별 동기화 허가와 서버 보관 앱 키가 필요하다. 실시간 호출량은 차감하지 않고 조직별 별도 제한을 적용한다. 응답 checksum은 HTTP 응답 bytes의 SHA-256이다. removals는 새 본문·이용기간을 제공하지 않는다.",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncChanges"
                }
              }
            },
            "headers": {
              "X-Checksum-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              },
              "Cache-Control": {
                "schema": {
                  "const": "private, no-store"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sync/removals": {
      "get": {
        "operationId": "appSyncRemovals",
        "tags": ["Developer"],
        "summary": "제거 전용 피드",
        "description": "별도 앱별 동기화 허가와 서버 보관 앱 키가 필요하다. 실시간 호출량은 차감하지 않고 조직별 별도 제한을 적용한다. 응답 checksum은 HTTP 응답 bytes의 SHA-256이다. removals는 새 본문·이용기간을 제공하지 않는다.",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncChanges"
                }
              }
            },
            "headers": {
              "X-Checksum-SHA256": {
                "schema": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              },
              "Cache-Control": {
                "schema": {
                  "const": "private, no-store"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/developer/sync-grants": {
      "get": {
        "operationId": "readAppSyncGrant",
        "tags": ["Developer"],
        "summary": "관리자 허가 확인·응답 유실 복구",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "app_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncGrantResult"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setAppSyncGrant",
        "tags": ["Developer"],
        "summary": "관리자 내부 앱 동기화 허가·회수",
        "description": "DB 관리자·최근 로그인·같은 Origin 필수. 최초 expected_version은 null, 이후 현재 버전이 필요하다. 응답 유실·충돌은 GET으로 확인한다.",
        "security": [
          {
            "SessionCookie": []
          }
        ],
        "x-recent-login-seconds": 900,
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppSyncGrantInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "확정 응답",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppSyncGrantResult"
                }
              }
            }
          },
          "400": {
            "description": "잘못된 조회 조건·커서",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "인증 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "앱 허가 또는 관리자 권한 필요",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "지원하지 않는 메서드",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "동기화 초기화 필요 또는 허가 버전 충돌",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "조직 동기화 호출 한도 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "내부 처리 실패",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "상태 조회 실패 또는 데이터 크기 초과",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sync/v2/manifest": {
      "get": {
        "operationId": "getPublicationManifest",
        "summary": "미리 게시한 베이스 또는 직접 증분 선택",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-None-Match",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "앱 인증 필요"
          },
          "403": {
            "description": "앱 동기화 허가 없음"
          },
          "409": {
            "description": "현재 게시 버전으로 다시 조회"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "서버 오류"
          },
          "503": {
            "description": "게시 준비 또는 복구 중"
          },
          "200": {
            "description": "게시 파일 선택. X-Sync-Server-Time 및 X-Sync-Offline-Until 헤더로 오프라인 허용 시간을 제공한다.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicationManifest"
                }
              }
            }
          },
          "304": {
            "description": "ETag 일치. 본문 없이 검증 시간 헤더를 갱신한다."
          }
        }
      }
    },
    "/api/v1/sync/v2/files/{hash}.json.gz": {
      "get": {
        "operationId": "getPublicationFile",
        "summary": "사전 생성한 불변 gzip 파일 다운로드",
        "security": [
          {
            "ApiKeyBearer": []
          }
        ],
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            }
          },
          {
            "name": "release",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Range",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "401": {
            "description": "앱 인증 필요"
          },
          "403": {
            "description": "앱 동기화 허가 없음"
          },
          "409": {
            "description": "현재 게시 버전으로 다시 조회"
          },
          "429": {
            "description": "요청 제한"
          },
          "500": {
            "description": "서버 오류"
          },
          "503": {
            "description": "게시 준비 또는 복구 중"
          },
          "404": {
            "description": "현재 게시에 속하지 않는 파일"
          },
          "200": {
            "description": "Content-Encoding 없는 gzip 파일. compressed/raw 크기와 SHA-256을 각각 확인한다.",
            "content": {
              "application/gzip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "허가·현재 버전을 다시 확인한 단일 바이트 범위. Content-Range와 전체 압축 파일 SHA-256을 제공한다.",
            "content": {
              "application/gzip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "416": {
            "description": "잘못되거나 충족할 수 없는 범위. Content-Range: bytes */전체길이."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "SessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "mq_session",
        "description": "Real DB-validated opaque session; HttpOnly/SameSite=Lax/Secure in production. Unsafe requests additionally need same-origin Origin header. Verified email required for authenticated participation/developer use. Administrator is a separate DB role."
      },
      "ApiKeyBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "mq_live_ + 43 base64url characters",
        "description": "App-bound opaque API key, stored hashed. Login session never substitutes for an API product entitlement. Keep on server; do not embed in browser/native public bundles."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            },
            "required": ["code", "message"]
          },
          "requestId": {
            "type": "string"
          }
        },
        "required": ["error", "requestId"]
      },
      "Message": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "required": ["message"]
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "display_name": {
            "type": "string"
          },
          "verified": {
            "type": "boolean"
          },
          "is_admin": {
            "type": "boolean"
          }
        },
        "required": ["id", "email", "display_name", "verified", "is_admin"]
      },
      "Quote": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "description": "Language of the displayed text, including a reviewed translation when present. Consult original_language and translation metadata for provenance."
          },
          "author": {
            "type": "string",
            "description": "Backward-compatible display attribution, not proof of the actual quotation author. Consult quote_author, source_work_author, author_status and attribution_context. A historical record without a known quote author may display 작자 미상."
          },
          "source_title": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "source_locator": {
            "type": "string"
          },
          "original_text": {
            "type": "string"
          },
          "original_language": {
            "type": "string"
          },
          "translation_author": {
            "type": "string",
            "description": "Actual disclosed translator or AI-assisted translation attribution; empty when no translation. No invented human translator identity."
          },
          "rights_basis": {
            "type": "string",
            "description": "Public rights summary for the original work/source and acquisition scope. The translated text has separate translation_rights_license and translation_rights_basis; private evidence and reviewer identities remain excluded."
          },
          "rights_territory": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "Korean topic API/display value, preserved for compatibility alongside stable category_id. Canonical labels and four legacy aliases are normalized through the shared taxonomy; this field is distinct from content_type."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": ["historical", "original"],
            "description": "Authorship/origin distinction: historical quotation versus contributor original. Independent of content_type and attribution_context."
          },
          "status": {
            "type": "string",
            "enum": ["approved"]
          },
          "rights_status": {
            "type": "string",
            "enum": ["cleared"]
          },
          "rights_license": {
            "type": "string",
            "enum": ["public_domain", "CC0-1.0", "CC-BY-4.0"],
            "description": "Rights license of the original source or contributor-authored original, assessed separately from translation_rights_license. A public-domain original does not make its translation public-domain."
          },
          "rights_expires_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "commercial_allowed": {
            "type": "boolean",
            "description": "Independent paid/external API-resupply permission. Required for default/free/commercial realtime API supply; not inferred from public display, app display or download redistribution permission. Administrator-designated internal app supply does not require API resale permission."
          },
          "redistribution_allowed": {
            "type": "boolean",
            "description": "Independent dataset download redistribution permission. Snapshot supply requires this and app_display_allowed plus an exact-version entitlement. API-resupply or public-display permission is not inferred or required in its place."
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "content_type": {
            "$ref": "#/components/schemas/ContentType"
          },
          "attribution_context": {
            "$ref": "#/components/schemas/AttributionContext"
          },
          "source_edition": {
            "type": "string",
            "description": "Exact source edition and original publication information; empty for legacy records without this metadata. A later translation or editorial edition is distinct from the original publication."
          },
          "source_registry_id": {
            "type": "string",
            "description": "Acquisition source registry identifier. Empty for records without a registry reference. A registry source assessment is not per-record rights clearance."
          },
          "source_file_url": {
            "type": "string",
            "description": "Public HTTPS URL of the exact source file, or empty for legacy/UGC records. Server-local file paths are never supplied."
          },
          "source_file_sha256": {
            "type": "string",
            "pattern": "^(?:|[a-f0-9]{64})$",
            "description": "SHA256 of the full acquired source file bytes after HTTP decoding, including any original BOM/line endings; empty when not recorded. This is separate from the snapshot response checksum."
          },
          "translation_method": {
            "$ref": "#/components/schemas/TranslationMethod"
          },
          "translation_review_status": {
            "$ref": "#/components/schemas/TranslationReviewStatus"
          },
          "translation_review_method": {
            "$ref": "#/components/schemas/TranslationReviewMethod"
          },
          "content_review_status": {
            "$ref": "#/components/schemas/ContentReviewStatus"
          },
          "content_review_method": {
            "$ref": "#/components/schemas/ContentReviewMethod"
          },
          "app_display_allowed": {
            "type": "boolean",
            "description": "Independent clearance for commercial app display. Required by internal app, external API and snapshot supply; external API also requires commercial_allowed, while snapshots instead require redistribution_allowed."
          },
          "public_display_allowed": {
            "type": "boolean",
            "description": "Independent permission for public website display. Public browser routes require this flag; commercial API/snapshot supply does not require it when its separate app-display, resupply and redistribution permissions are satisfied."
          },
          "translation_rights_license": {
            "$ref": "#/components/schemas/TranslationRightsLicense"
          },
          "translation_rights_basis": {
            "type": "string",
            "description": "Public summary of the independent rights/usage basis of this translated text. Empty when not applicable or unrecorded. Original-source public-domain status cannot substitute for this basis. Private contracts, reviewer identities and evidence remain excluded."
          },
          "author_status": {
            "$ref": "#/components/schemas/AuthorStatus"
          },
          "quote_author": {
            "type": "string",
            "description": "Recorded attribution of the quoted statement itself; may be empty when unknown. It is distinct from the source work author and must be interpreted with author_status and attribution_context."
          },
          "source_work_author": {
            "type": "string",
            "description": "Author of the source work, if recorded; may be empty. Do not automatically attribute a poetic speaker, narrator, character or anonymously quoted statement to this person."
          },
          "category_id": {
            "type": "string",
            "enum": [
              "",
              "life",
              "self-reflection",
              "relationships",
              "courage",
              "learning",
              "time",
              "action",
              "judgment",
              "happiness",
              "moderation",
              "integrity",
              "generosity"
            ],
            "description": "Stable canonical topic ID. Empty is permitted for legacy rows not mapped to a canonical topic. category preserves the Korean API/display value; content_type is a separate classification."
          }
        },
        "required": [
          "text",
          "language",
          "author",
          "source_title",
          "source_url",
          "source_locator",
          "original_text",
          "original_language",
          "translation_author",
          "rights_basis",
          "rights_territory",
          "category",
          "id",
          "kind",
          "status",
          "rights_status",
          "rights_license",
          "rights_expires_at",
          "commercial_allowed",
          "redistribution_allowed",
          "revision",
          "created_at",
          "updated_at",
          "content_type",
          "attribution_context",
          "source_edition",
          "source_registry_id",
          "source_file_url",
          "source_file_sha256",
          "translation_method",
          "translation_review_status",
          "translation_review_method",
          "content_review_status",
          "content_review_method",
          "app_display_allowed",
          "public_display_allowed",
          "translation_rights_license",
          "translation_rights_basis",
          "author_status",
          "quote_author",
          "source_work_author",
          "category_id"
        ],
        "additionalProperties": false,
        "description": "Safe content record shared by website, realtime API, change upserts and snapshot records. All channels require approved, rights-cleared, nonexpired content with verified source review and verified translation review when translated. Public browser supply requires public_display_allowed. Default/free/commercial realtime API supply requires app_display_allowed and commercial_allowed; administrator-designated internal app supply requires app_display_allowed under the same authentication and bounded quotas. Snapshot supply independently requires app_display_allowed and redistribution_allowed plus an explicit version entitlement, without requiring API-resupply permission. Permissions never grant one another. Content form and speaker context remain attached to text. Private contributor identifiers, fingerprints, evidence, local source paths, reviewer identities and import ledger payloads are excluded. Automated review never implies human editorial or operational release approval. Original-source and translation usage rights remain distinct in every channel; consumers must not label a user_owned_output translation as public-domain solely because rights_license is public_domain. Quotation attribution and source-work authorship are separate; unknown/unverified/attributed/verified author_status never substitutes for source or rights review, and unknown authorship alone is not a supply veto."
      },
      "QuoteResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Quote"
          }
        },
        "required": ["data"]
      },
      "TodayResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Quote"
          },
          "date": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "type": "string",
            "const": "UTC"
          }
        },
        "required": ["data", "date", "timezone"]
      },
      "QuotePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": ["data", "total", "page", "limit"]
      },
      "QuoteList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          }
        },
        "required": ["data"]
      },
      "UpsertChange": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "operation": {
            "type": "string",
            "const": "upsert"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "$ref": "#/components/schemas/Quote"
          }
        },
        "required": ["revision", "quote_id", "operation", "created_at", "data"],
        "additionalProperties": false
      },
      "DeleteChange": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "operation": {
            "type": "string",
            "const": "delete"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["revision", "quote_id", "operation", "created_at"],
        "additionalProperties": false
      },
      "ChangePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/UpsertChange"
                },
                {
                  "$ref": "#/components/schemas/DeleteChange"
                }
              ]
            }
          },
          "next_cursor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": ["data", "next_cursor", "has_more"]
      },
      "RevocationPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/DeleteChange"
                },
                {
                  "$ref": "#/components/schemas/InvalidateChange"
                }
              ]
            }
          },
          "next_cursor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "has_more": {
            "type": "boolean"
          },
          "billing": {
            "type": "string",
            "const": "unmetered"
          },
          "instruction": {
            "type": "string"
          }
        },
        "required": ["data", "next_cursor", "has_more", "billing", "instruction"]
      },
      "Stats": {
        "type": "object",
        "properties": {
          "approved": {
            "type": "integer",
            "minimum": 0
          },
          "pending": {
            "type": "integer",
            "minimum": 0
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "language_counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Actual approved and rights-cleared counts by language; Korean original and translation provenance remains per record."
          },
          "content_type_counts": {
            "type": "object",
            "properties": {
              "quote": {
                "type": "integer",
                "minimum": 0
              },
              "proverb": {
                "type": "integer",
                "minimum": 0
              },
              "literary_excerpt": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": ["quote", "proverb", "literary_excerpt"],
            "additionalProperties": false,
            "description": "Actual eligible public counts by content form, including zero counts; independent of kind and language. public_display_allowed=false, held, withdrawn, expired or unverified content is excluded."
          },
          "topics": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Topic"
            },
            "description": "All twelve canonical topic IDs and Korean labels in canonical order, including zero counts, using current eligible public records. Unmapped legacy category_id-empty records can remain in the approved total without appearing in this twelve-topic sum. Candidate/staging counts are not publication counts."
          }
        },
        "required": ["approved", "pending", "categories", "content_type_counts", "topics"]
      },
      "RegisterRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "password": {
            "type": "string",
            "minLength": 12,
            "maxLength": 128,
            "writeOnly": true
          },
          "display_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "terms": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["email", "password", "display_name", "terms"],
        "additionalProperties": false
      },
      "RegisterResult": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "verification_required": {
            "type": "boolean",
            "const": true
          },
          "mail_transport": {
            "type": "string",
            "enum": ["local-file", "smtp", "supabase"]
          }
        },
        "required": ["message", "verification_required", "mail_transport"]
      },
      "LoginRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "password": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "writeOnly": true
          }
        },
        "required": ["email", "password"],
        "additionalProperties": false
      },
      "UserResult": {
        "type": "object",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/User"
          }
        },
        "required": ["user"]
      },
      "OptionalUserResult": {
        "type": "object",
        "properties": {
          "user": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/User"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": ["user"]
      },
      "TokenRequest": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$",
            "writeOnly": true
          }
        },
        "required": ["token"],
        "additionalProperties": false
      },
      "ForgotRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          }
        },
        "required": ["email"],
        "additionalProperties": false
      },
      "ResetRequest": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$",
            "writeOnly": true
          },
          "password": {
            "type": "string",
            "minLength": 12,
            "maxLength": 128,
            "writeOnly": true
          }
        },
        "required": ["token", "password"],
        "additionalProperties": false
      },
      "DeleteAccountRequest": {
        "type": "object",
        "properties": {
          "confirmation": {
            "type": "string",
            "const": "DELETE"
          }
        },
        "required": ["confirmation"],
        "additionalProperties": false
      },
      "SaveRequest": {
        "type": "object",
        "properties": {
          "quote_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": ["quote_id"],
        "additionalProperties": false
      },
      "SavedResult": {
        "type": "object",
        "properties": {
          "saved": {
            "type": "boolean"
          }
        },
        "required": ["saved"]
      },
      "ReasonRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          }
        },
        "required": ["reason"],
        "additionalProperties": false
      },
      "ReportRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "enum": ["rights", "attribution", "translation", "other"]
          },
          "detail": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          }
        },
        "required": ["reason", "detail"],
        "additionalProperties": false
      },
      "ReportResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"]
          }
        },
        "required": ["id", "status"]
      },
      "Report": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"]
          },
          "resolution": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "resolved_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["id", "user_id", "quote_id", "reason", "detail", "status", "created_at"]
      },
      "ReviewRequest": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": ["approve", "reject"]
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          },
          "rights_cleared": {
            "type": "boolean",
            "default": false
          },
          "rights_evidence": {
            "type": "string",
            "maxLength": 4000,
            "default": ""
          },
          "rights_expires_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "translation_verified": {
            "type": "boolean",
            "description": "Optional explicit confirmation that this administrator compared a new or changed translation against the original. Approval requires true when that translation is new/changed; otherwise422 translation_clearance_required. An unchanged already-verified translation can retain its prior review metadata without a new confirmation. A fresh human comparison records human_editorial_review as the review method only; an AI-assisted translation remains ai_assisted."
          }
        },
        "required": ["action", "reason"],
        "additionalProperties": false,
        "description": "Approval requires rights_cleared=true and at least 10 characters of private evidence; future expiry only. A submitter cannot review their own submission. New or changed translations require translation_verified=true after actual original/translation comparison. Merely approving rights or an unrelated correction is not human translation review. Existing imported AI-assisted authorship/method and independent translation rights are preserved; human_editorial_review describes only an actual newly confirmed human review."
      },
      "WithdrawResult": {
        "type": "object",
        "properties": {
          "withdrawn": {
            "type": "boolean",
            "const": true
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          }
        },
        "required": ["withdrawn", "revision"]
      },
      "Audit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "actor_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "action": {
            "type": "string"
          },
          "target_type": {
            "type": "string"
          },
          "target_id": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "actor_id", "action", "target_type", "target_id", "reason", "created_at"]
      },
      "Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "owner_id": {
            "type": "string",
            "format": "uuid"
          },
          "plan": {
            "type": "string",
            "enum": ["free", "internal", "starter", "growth", "business", "commercial"]
          },
          "status": {
            "type": "string",
            "enum": ["active", "closed", "suspended"]
          },
          "period_start": {
            "type": "string",
            "format": "date-time"
          },
          "period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "name", "owner_id", "plan", "status", "cancel_at_period_end"]
      },
      "Application": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "org_id", "name", "created_at"]
      },
      "KeyRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "Non-secret display prefix only."
          },
          "revoked_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "app_name": {
            "type": "string"
          }
        },
        "required": ["id", "org_id", "app_id", "name", "prefix", "created_at"],
        "additionalProperties": false
      },
      "KeyResult": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^mq_live_[A-Za-z0-9_-]{43}$",
            "description": "Returned exactly once after real local issuance; never available in workspace lists. Keep only in a server-side secret store."
          },
          "record": {
            "$ref": "#/components/schemas/KeyRecord"
          },
          "notice": {
            "type": "string"
          }
        },
        "required": ["key", "record", "notice"],
        "additionalProperties": false
      },
      "Usage": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "period": {
            "type": "string",
            "pattern": "^[0-9]{4}-[0-9]{2}$"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "org_name": {
            "type": "string"
          },
          "app_name": {
            "type": "string"
          }
        },
        "required": ["org_id", "app_id", "period", "count"]
      },
      "Entitlement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string",
            "enum": ["realtime", "snapshot"]
          },
          "status": {
            "type": "string",
            "enum": ["active", "expired", "revoked"]
          },
          "valid_from": {
            "type": "string",
            "format": "date-time"
          },
          "valid_until": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "order_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "snapshot_version": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "original_valid_until": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["id", "org_id", "product", "status", "valid_from"]
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "const": "KRW"
          },
          "terms_version": {
            "type": "string"
          },
          "snapshot_version": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "product_snapshot": {
            "$ref": "#/components/schemas/PricePlan"
          },
          "refunded_amount": {
            "type": "integer",
            "minimum": 0
          },
          "period_start": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "subscription_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "expires_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "org_id",
          "product",
          "status",
          "amount",
          "currency",
          "terms_version",
          "product_snapshot",
          "refunded_amount",
          "period_start",
          "period_end",
          "subscription_id"
        ],
        "additionalProperties": false,
        "description": "Owner/member-safe order projection. Excludes provider payment references, checkout state hashes, creator/account secrets and command payloads. expires_at is provided by owner order/checkout responses; workspace may omit it."
      },
      "PricePlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "monthly_requests": {
            "type": "integer",
            "minimum": 0
          },
          "requests_per_minute": {
            "type": "integer",
            "minimum": 0
          },
          "price_krw": {
            "type": "integer",
            "minimum": 0
          },
          "price_label": {
            "type": "string"
          },
          "product": {
            "type": "string",
            "enum": ["realtime", "snapshot"]
          },
          "description": {
            "type": "string"
          },
          "commercial": {
            "type": "boolean"
          },
          "snapshot": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "monthly_requests",
          "requests_per_minute",
          "price_krw",
          "price_label",
          "product",
          "description",
          "commercial",
          "snapshot"
        ]
      },
      "PlansResult": {
        "type": "object",
        "properties": {
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PricePlan"
            }
          },
          "internal_plan": {
            "$ref": "#/components/schemas/PricePlan"
          },
          "payment_connected": {
            "type": "boolean",
            "default": false
          },
          "prices_are_draft": {
            "type": "boolean",
            "const": true
          },
          "terms_version": {
            "type": "string"
          },
          "notice": {
            "type": "string"
          },
          "billing_connected": {
            "type": "boolean",
            "default": false
          },
          "payment_mode": {
            "type": "string",
            "enum": ["disconnected", "merchant"],
            "default": "disconnected"
          },
          "client_key": {
            "type": "string",
            "description": "Public Toss browser client key, present only after approved activation; never the secret API key."
          },
          "snapshot_versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SnapshotVersionSummary"
            }
          },
          "pricing_policy": {
            "$ref": "#/components/schemas/PricingPolicy"
          }
        },
        "required": [
          "plans",
          "internal_plan",
          "payment_connected",
          "prices_are_draft",
          "terms_version",
          "notice",
          "billing_connected",
          "payment_mode",
          "pricing_policy"
        ],
        "description": "Draft pricing and runtime merchant connection state. Optional snapshot_versions contains metadata only, no quote text. Empty when no eligible snapshot exists. MQ-08 안내 revision은 약관/주문 버전과 별개이며 기존 금액·한도 유지, 세금 미확정·혜택 준비 상태를 명시한다."
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "organizations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Organization"
            }
          },
          "apps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceApplication"
            }
          },
          "keys": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KeyRecord"
            }
          },
          "usage": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Usage"
            }
          },
          "entitlements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Entitlement"
            }
          },
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceOrder"
            }
          },
          "payment_connected": {
            "type": "boolean",
            "default": false
          },
          "terms_version": {
            "type": "string"
          },
          "billing_connected": {
            "type": "boolean",
            "default": false
          },
          "payment_mode": {
            "type": "string",
            "enum": ["disconnected", "merchant"],
            "default": "disconnected"
          },
          "client_key": {
            "type": "string",
            "description": "Public Toss browser client key, present only after approved activation; never the secret API key."
          },
          "subscriptions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceSubscription"
            }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "organizations": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "apps": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "keys": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "usage": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "entitlements": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "orders": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "subscriptions": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "logs": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "key_audit": {
                "$ref": "#/components/schemas/PageInfo"
              },
              "quotas": {
                "type": "object",
                "properties": {
                  "page": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "page_size": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "total": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": ["page", "page_size", "total"],
                "additionalProperties": false,
                "description": "조직 쿼터 현황은 페이지 없이 전체 활성 구성 조직을 반환한다. page_size는 반환된 조직 수(빈 경우20)다."
              }
            },
            "additionalProperties": false
          },
          "logs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeveloperRequestLog"
            }
          },
          "key_audit": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeveloperKeyAudit"
            }
          },
          "quotas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrganizationQuota"
            }
          },
          "app_choices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceApplication"
            }
          }
        },
        "required": [
          "organizations",
          "apps",
          "keys",
          "usage",
          "entitlements",
          "orders",
          "payment_connected",
          "terms_version",
          "billing_connected",
          "payment_mode",
          "subscriptions",
          "logs",
          "key_audit",
          "quotas",
          "app_choices"
        ]
      },
      "OrganizationRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": ["name"],
        "additionalProperties": false
      },
      "ApplicationRequest": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": ["org_id", "name"],
        "additionalProperties": false
      },
      "KeyRequest": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": ["org_id", "app_id", "name"],
        "additionalProperties": false
      },
      "RevokedResult": {
        "type": "object",
        "properties": {
          "revoked": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["revoked"]
      },
      "CheckoutRequest": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string",
            "enum": [
              "starter",
              "growth",
              "business",
              "snapshot",
              "realtime_commercial",
              "snapshot_commercial"
            ]
          },
          "snapshot_version": {
            "type": "string",
            "maxLength": 100
          },
          "terms": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["org_id", "product", "terms"],
        "additionalProperties": false,
        "description": "Verified organization owner with login within15 minutes and current product/terms acceptance. Requires Idempotency-Key. Snapshot version must equal the latest purchasable manifest. Default disconnected503 creates no order or paid rights; approved merchant activation can create a real pending checkout."
      },
      "OrganizationIdRequest": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": ["org_id"],
        "additionalProperties": false
      },
      "CancelResult": {
        "type": "object",
        "properties": {
          "cancel_at_period_end": {
            "type": "boolean",
            "const": true
          },
          "period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "notice": {
            "type": "string"
          },
          "charge_in_flight": {
            "type": "boolean"
          }
        },
        "required": ["cancel_at_period_end", "period_end", "notice", "charge_in_flight"],
        "description": "Stops future renewal intent. Preserves current paid rights until period end. An already-started network charge can still be reconciled; charge_in_flight makes that race explicit."
      },
      "RefundRequest": {
        "type": "object",
        "properties": {
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          }
        },
        "required": ["order_id", "reason"],
        "additionalProperties": false
      },
      "RefundResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "const": "pending"
          },
          "notice": {
            "type": "string"
          }
        },
        "required": ["id", "status", "notice"]
      },
      "SnapshotManifest": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "string",
            "const": "1"
          },
          "version": {
            "type": "string",
            "pattern": "^v1-[0-9]+-[a-f0-9]{16}$"
          },
          "record_count": {
            "type": "integer",
            "minimum": 1
          },
          "checksum": {
            "type": "object",
            "properties": {
              "algorithm": {
                "type": "string",
                "const": "SHA-256"
              },
              "value": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              },
              "encoding": {
                "type": "string",
                "const": "hex"
              },
              "target": {
                "type": "string",
                "const": "download response bytes"
              }
            },
            "required": ["algorithm", "value", "encoding", "target"]
          },
          "content_type": {
            "type": "string"
          },
          "bytes": {
            "type": "integer",
            "minimum": 1
          },
          "revision_cursor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "rights_territory": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["KR", "US"]
            },
            "minItems": 1,
            "uniqueItems": true,
            "description": "Sorted common territory codes present in every supplied record. Intersection of record-level territories, not a union or a hardcoded KR/US grant. No common territory prevents snapshot creation with409 no_common_territory."
          },
          "rights_scope": {
            "type": "string",
            "description": "Recorded dataset rights scope. Snapshot eligibility uses independent app-display and download-redistribution clearance; manifest access never grants a download entitlement or an external API-resupply license."
          },
          "rights_notice": {
            "type": "string"
          },
          "withdrawals": {
            "type": "object",
            "properties": {
              "endpoint": {
                "type": "string",
                "const": "/api/v1/revocations"
              },
              "minimum_sync": {
                "type": "string"
              },
              "cursor": {
                "type": "string",
                "pattern": "^[0-9]+$",
                "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
              },
              "required_action": {
                "type": "string"
              },
              "remote_recall_possible": {
                "type": "boolean",
                "const": false
              }
            },
            "required": [
              "endpoint",
              "minimum_sync",
              "cursor",
              "required_action",
              "remote_recall_possible"
            ]
          },
          "update_policy": {
            "type": "string"
          },
          "rights_territory_policy": {
            "type": "string",
            "const": "intersection_of_record_territories",
            "description": "The snapshot-wide region scope is the intersection, never the union, of every supplied record rights_territory."
          },
          "sync": {
            "$ref": "#/components/schemas/AppSyncBasis"
          }
        },
        "required": [
          "schema_version",
          "version",
          "record_count",
          "checksum",
          "content_type",
          "bytes",
          "revision_cursor",
          "rights_territory",
          "rights_scope",
          "rights_notice",
          "withdrawals",
          "update_policy",
          "rights_territory_policy"
        ],
        "description": " 신규 파일의 sync는 한국어/KR 동기화 시작 기준이다. 기존 파일에 없으면 sync/download로 초기화한다. 앱별 동기화 허가를 부여하지 않는다."
      },
      "ManifestResult": {
        "type": "object",
        "properties": {
          "manifest": {
            "$ref": "#/components/schemas/SnapshotManifest"
          },
          "payment_connected": {
            "type": "boolean",
            "default": false
          },
          "download_requires_separate_entitlement": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["manifest", "payment_connected", "download_requires_separate_entitlement"]
      },
      "Snapshot": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "string",
            "const": "1"
          },
          "rights_territory": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["KR", "US"]
            },
            "minItems": 1,
            "uniqueItems": true,
            "description": "Sorted common territory codes present in every supplied record. Intersection of record-level territories, not a union or a hardcoded KR/US grant. No common territory prevents snapshot creation with409 no_common_territory."
          },
          "revocation_cursor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "quotes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          },
          "sync": {
            "$ref": "#/components/schemas/AppSyncBasis"
          }
        },
        "required": ["schema_version", "rights_territory", "revocation_cursor", "quotes"],
        "additionalProperties": false,
        "description": "Immutable versioned content file. Quote metadata retains actual form, attribution, source-file provenance, translation/review methods and four independent permission flags. Eligibility requires reviewed/cleared/nonexpired content with app-display and download-redistribution clearance, not API-resupply clearance. Snapshot-wide rights_territory is the nonempty intersection of all included record territories; retain the narrower file scope together with each original/translation rights record. 신규 파일의 sync는 한국어/KR 동기화 시작 기준이다. 기존 파일에 없으면 sync/download로 초기화한다. 앱별 동기화 허가를 부여하지 않는다."
      },
      "ContributionRequest": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["historical", "original"]
          },
          "text": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          },
          "language": {
            "type": "string",
            "enum": ["ko", "en"]
          },
          "author": {
            "type": "string",
            "maxLength": 120,
            "description": "Optional backward-compatible display attribution, defaults to empty. Historical records may omit it or provide empty when quote authorship is unknown; the server displays 작자 미상 as the Korean unknown-author label. Contributor originals still require the actual verified own-author display name.",
            "default": ""
          },
          "source_title": {
            "type": "string",
            "maxLength": 300,
            "default": ""
          },
          "source_url": {
            "type": "string",
            "maxLength": 2000,
            "default": "",
            "description": "Public HTTPS primary source. No credentials, localhost or private hosts. Required for historical quotations."
          },
          "source_locator": {
            "type": "string",
            "maxLength": 300,
            "default": ""
          },
          "original_text": {
            "type": "string",
            "maxLength": 4000,
            "default": ""
          },
          "original_language": {
            "type": "string",
            "minLength": 2,
            "maxLength": 20,
            "default": "en"
          },
          "translation_author": {
            "type": "string",
            "maxLength": 120,
            "default": ""
          },
          "rights_basis": {
            "type": "string",
            "minLength": 10,
            "maxLength": 2000
          },
          "rights_license": {
            "type": "string",
            "enum": ["public_domain", "CC0-1.0", "CC-BY-4.0"]
          },
          "rights_territory": {
            "type": "string",
            "const": "KR,US"
          },
          "category": {
            "type": "string",
            "maxLength": 60,
            "default": "",
            "description": "Optional Korean topic value; defaults to empty. Provide category or category_id. Canonical labels and legacy aliases 고독/단순함/성장/진실 normalize to 자기성찰/절제/실천/정직과 품성. If both fields are provided their topics must agree, otherwise422. Omitted category defaults to empty; unknown/missing topics and ID/label conflicts return422 invalid_category."
          },
          "ai_assisted": {
            "type": "boolean"
          },
          "consent": {
            "type": "boolean",
            "const": true
          },
          "publication_consent": {
            "type": "boolean",
            "const": true
          },
          "commercial_consent": {
            "type": "boolean"
          },
          "redistribution_consent": {
            "type": "boolean"
          },
          "rights_evidence": {
            "type": "string",
            "maxLength": 4000,
            "default": ""
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "expected_revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "content_type": {
            "$ref": "#/components/schemas/ContentType",
            "default": "quote",
            "description": "Optional for compatibility; defaults to quote. Server validates attribution combinations independently of historical/original kind."
          },
          "attribution_context": {
            "$ref": "#/components/schemas/AttributionContext",
            "default": "author_statement",
            "description": "Optional for compatibility; defaults to author_statement. Proverbs require traditional context; literary speakers and characters must not be relabeled as actual author statements."
          },
          "translation_rights_license": {
            "$ref": "#/components/schemas/TranslationRightsLicense",
            "default": "",
            "description": "Optional for compatibility; defaults to empty. A new or changed translated text requires its own nonempty rights license, independently of the source license. Unchanged imported translation metadata is preserved by the server. New user_owned_output translations must use the verified import path; direct new UGC submissions return422 trusted_translation_import_required. The usage basis of an existing AI-assisted translation cannot be replaced with another license through a general correction."
          },
          "translation_rights_basis": {
            "type": "string",
            "default": "",
            "description": "Optional for compatibility; defaults to empty. New or changed translations require an independent usage/rights basis. Do not copy the public-domain source label into the translation rights. Existing imported metadata is retained when the translation is unchanged. Newly submitted or approved translated records require at least10 characters of independent basis; the default-empty value is for untranslated input or preservation of an existing correction target.",
            "maxLength": 4000
          },
          "author_status": {
            "$ref": "#/components/schemas/AuthorStatus",
            "default": "unverified",
            "description": "Optional attribution status; defaults to unverified. It does not self-approve source, rights or publication and unknown authorship alone does not block an otherwise eligible historical record."
          },
          "quote_author": {
            "type": "string",
            "description": "Optional statement/quotation attribution, distinct from source_work_author. When omitted, the historical compatibility input uses author; an explicitly empty value preserves unknown attribution. Do not invent a person when the quote author is unknown.",
            "maxLength": 120
          },
          "source_work_author": {
            "type": "string",
            "default": "",
            "description": "Optional source-work author, distinct from quotation/character/speaker attribution. Defaults to empty.",
            "maxLength": 120
          },
          "category_id": {
            "type": "string",
            "enum": [
              "",
              "life",
              "self-reflection",
              "relationships",
              "courage",
              "learning",
              "time",
              "action",
              "judgment",
              "happiness",
              "moderation",
              "integrity",
              "generosity"
            ],
            "description": "Optional stable topic ID. Provide category or category_id; an empty supplied value is treated as absent. Explicit IDs must be canonical and must agree with a supplied category label; otherwise422 invalid_category. Independent of content_type.",
            "maxLength": 60
          }
        },
        "required": [
          "kind",
          "text",
          "language",
          "rights_basis",
          "rights_license",
          "rights_territory",
          "ai_assisted",
          "consent",
          "publication_consent",
          "commercial_consent",
          "redistribution_consent"
        ],
        "additionalProperties": false,
        "description": "Own originals require author=current verified display name and CC0/CC BY license. Historical quotes require original text, title, HTTPS primary source and locator. Translation credit and rights required when languages differ. All AI-assisted submissions are rejected422 in the initial policy. Separate publication/commercial/redistribution consent is recorded; posting consent alone never grants commercial supply. quote_id creates a correction; expected_revision protects against stale corrections. content_type and attribution_context are independent optional fields with quote/author_statement defaults; server validates their combination. Public import review metadata cannot be self-assigned through this strict UGC request. Reviewed AI-assisted imported translations are a separate acquisition path and do not relax the rejection of AI-authored UGC. Literary excerpts require poetic_speaker, narrator, character or unknown context; proverbs require kind=historical and traditional context. Invalid attribution combinations return422. translation_rights_license and translation_rights_basis are optional default-empty fields but new/changed translations require independent nonempty rights data. An unchanged imported AI-assisted translation retains its recorded method, translator attribution, review metadata and independent translation rights instead of being rewritten as human/public-domain work. quote content accepts author_statement or unknown attribution_context. author_status defaults to unverified, source_work_author defaults to empty, and omitted quote_author falls back to the historical compatibility author input; no source-work author is automatically substituted as the speaker. Unknown historical quote authorship can use an empty display author and remains eligible for independent source/rights review. New UGC user_owned_output translations return422 trusted_translation_import_required. Attempting to change an existing AI-assisted translation usage license/basis during correction returns422 translation_rights_changed. author_status=verified or attributed with an empty quote_author returns422 author_metadata_conflict; unknown/unverified alone does not block provenance review. category and category_id are optional compatibility inputs, but a valid topic must be supplied through at least one; the server normalizes canonical labels/IDs and the four legacy aliases. Conflicting explicit ID/label pairs return422. Topic does not select quote/proverb/literary_excerpt content type."
      },
      "Submission": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "payload": {
            "$ref": "#/components/schemas/ContributionRequest"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "approved", "rejected"]
          },
          "review_reason": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "reviewed_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "quote_id",
          "payload",
          "status",
          "review_reason",
          "created_at",
          "reviewed_at"
        ],
        "description": "Own submission response. A create/review/admin response may additionally contain private moderation fields, available only to the authorized owner or administrator."
      },
      "SubmissionResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Submission"
          }
        },
        "required": ["data"]
      },
      "SubmissionList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/Submission"
                },
                {
                  "$ref": "#/components/schemas/SubmissionSummary"
                }
              ]
            }
          },
          "page": {
            "type": "integer",
            "minimum": 0
          },
          "page_size": {
            "type": "integer",
            "minimum": 0
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["data", "page", "page_size", "total"]
      },
      "ReviewResult": {
        "type": "object",
        "properties": {
          "submission": {
            "$ref": "#/components/schemas/Submission"
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          }
        },
        "required": ["submission", "quote_id"]
      },
      "ModerationQueue": {
        "type": "object",
        "properties": {
          "submissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModerationSubmission"
            }
          },
          "reports": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ModerationReport"
            }
          },
          "submissions_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          },
          "reports_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": ["submissions", "reports"]
      },
      "AuditList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditSummary"
            }
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["data"]
      },
      "OrganizationResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Organization"
          }
        },
        "required": ["data"]
      },
      "ApplicationResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Application"
          }
        },
        "required": ["data"]
      },
      "InvalidateChange": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "operation": {
            "type": "string",
            "const": "invalidate"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "delete_before_revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          }
        },
        "required": ["revision", "quote_id", "operation", "created_at", "delete_before_revision"],
        "additionalProperties": false,
        "description": "Delete cached records/derived assets with this quote_id whose revision is lower than delete_before_revision. This feed does not deliver replacement content."
      },
      "PaymentConnection": {
        "type": "object",
        "properties": {
          "payment_connected": {
            "type": "boolean",
            "default": false
          },
          "billing_connected": {
            "type": "boolean",
            "default": false
          },
          "payment_mode": {
            "type": "string",
            "enum": ["disconnected", "merchant"],
            "default": "disconnected"
          },
          "client_key": {
            "type": "string",
            "description": "Public Toss browser client key, present only after approved activation; never the secret API key."
          }
        },
        "required": ["payment_connected", "billing_connected", "payment_mode"],
        "description": "Runtime connection state. Defaults false. Merchant/operator approval and dedicated credentials required; billing additionally needs automatic-payment approval and a32-byte encryption key. Production rejects provider test keys."
      },
      "SnapshotVersionSummary": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "pattern": "^v1-[0-9]+-[a-f0-9]{16}$"
          },
          "record_count": {
            "type": "integer",
            "minimum": 1
          },
          "checksum": {
            "type": "object",
            "properties": {
              "algorithm": {
                "type": "string",
                "const": "SHA-256"
              },
              "value": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              },
              "encoding": {
                "type": "string",
                "const": "hex"
              },
              "target": {
                "type": "string",
                "const": "download response bytes"
              }
            },
            "required": ["algorithm", "value", "encoding", "target"]
          },
          "rights_territory": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["KR", "US"]
            }
          }
        },
        "required": ["version", "record_count", "checksum", "rights_territory"]
      },
      "Subscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string"
          },
          "product_snapshot": {
            "$ref": "#/components/schemas/PricePlan"
          },
          "terms_version": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "const": "KRW"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "active", "past_due", "canceled", "failed"]
          },
          "current_period_start": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "current_period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "next_billing_at": {
            "type": "string",
            "format": "date-time"
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "canceled_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "org_id",
          "product",
          "product_snapshot",
          "terms_version",
          "amount",
          "currency",
          "status",
          "current_period_start",
          "current_period_end",
          "next_billing_at",
          "cancel_at_period_end",
          "canceled_at",
          "created_at"
        ],
        "additionalProperties": false,
        "description": "Safe subscription view; no customer credential, billing key, provider secret or command lease/payload."
      },
      "Checkout": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "const": "toss"
          },
          "flow": {
            "type": "string",
            "enum": ["payment", "billing"]
          },
          "client_key": {
            "type": "string"
          },
          "customer_key": {
            "type": "string"
          },
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "order_name": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "const": "KRW"
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Session/order-bound unpredictable checkout return state. Do not log or persist outside the short checkout flow."
          },
          "success_url": {
            "type": "string",
            "format": "uri"
          },
          "fail_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "provider",
          "flow",
          "client_key",
          "customer_key",
          "order_id",
          "order_name",
          "amount",
          "currency",
          "state",
          "success_url",
          "fail_url"
        ],
        "additionalProperties": false
      },
      "CheckoutResult": {
        "type": "object",
        "properties": {
          "order": {
            "$ref": "#/components/schemas/Order"
          },
          "checkout": {
            "$ref": "#/components/schemas/Checkout"
          }
        },
        "required": ["order", "checkout"]
      },
      "PaymentOrderResult": {
        "type": "object",
        "properties": {
          "order": {
            "$ref": "#/components/schemas/Order"
          },
          "status": {
            "type": "string"
          },
          "review_required": {
            "type": "boolean"
          },
          "active": {
            "type": "boolean",
            "description": "이 주문에 연결된 현재 유효한 이용권 여부."
          }
        },
        "required": ["order"],
        "additionalProperties": false,
        "description": "Safe stored order after server-to-provider verification. A replay/read may omit status. Never treat an SDK return or this shape without confirmed order state as paid entitlement."
      },
      "ConfirmRequest": {
        "type": "object",
        "properties": {
          "paymentKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "writeOnly": true
          },
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "integer",
            "minimum": 1
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "writeOnly": true
          }
        },
        "required": ["paymentKey", "orderId", "amount", "state"],
        "additionalProperties": false
      },
      "AuthorizeRequest": {
        "type": "object",
        "properties": {
          "authKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "writeOnly": true
          },
          "customerKey": {
            "type": "string",
            "minLength": 10,
            "maxLength": 50
          },
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "writeOnly": true
          }
        },
        "required": ["authKey", "customerKey", "orderId", "state"],
        "additionalProperties": false
      },
      "ReconcileRequest": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "format": "uuid"
          },
          "state": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "writeOnly": true
          }
        },
        "required": ["orderId"],
        "additionalProperties": false,
        "description": "Lookup-only recovery. State is optional for an authenticated owner with recent login; it never authorizes a new confirm, billing-key issue, charge or refund."
      },
      "RefundReview": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "const": "pending"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "org_name": {
            "type": "string"
          },
          "product": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "const": "KRW"
          },
          "refunded_amount": {
            "type": "integer",
            "minimum": 0
          },
          "period_start": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "snapshot_version": {
            "type": ["string", "null"]
          },
          "download_count": {
            "type": "integer",
            "minimum": 0
          },
          "remaining_amount": {
            "type": "integer",
            "minimum": 0
          },
          "maximum_refund_amount": {
            "type": "integer",
            "minimum": 0
          },
          "maximum_partial_refund_amount": {
            "type": "integer",
            "minimum": 0
          },
          "full_refund_allowed": {
            "type": "boolean",
            "const": true
          },
          "snapshot_partial_refund": {
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "id",
          "order_id",
          "status",
          "reason",
          "created_at",
          "org_id",
          "org_name",
          "product",
          "amount",
          "currency",
          "refunded_amount",
          "period_start",
          "period_end",
          "snapshot_version",
          "download_count",
          "remaining_amount",
          "maximum_refund_amount",
          "maximum_partial_refund_amount",
          "full_refund_allowed",
          "snapshot_partial_refund"
        ],
        "additionalProperties": false
      },
      "RefundReviewList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RefundReview"
            }
          },
          "payment_connected": {
            "type": "boolean"
          },
          "pagination": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": ["data", "payment_connected"]
      },
      "RefundApprovalRequest": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "minimum": 1
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 200
          }
        },
        "required": ["amount", "reason"],
        "additionalProperties": false,
        "description": "Independent administrator approval. Full remaining amount is allowed as an explicit exception and revokes this order rights. Partial realtime refund is capped to unused period; snapshot partial refunds are forbidden."
      },
      "WebhookRequest": {
        "type": "object",
        "properties": {
          "eventType": {
            "type": "string",
            "enum": ["PAYMENT_STATUS_CHANGED"]
          },
          "createdAt": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "data": {
            "type": "object",
            "properties": {
              "paymentKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "writeOnly": true
              },
              "orderId": {
                "type": "string",
                "format": "uuid"
              },
              "status": {
                "type": "string",
                "maxLength": 80
              },
              "lastTransactionKey": {
                "type": ["string", "null"],
                "maxLength": 200
              }
            },
            "required": ["paymentKey", "orderId"]
          }
        },
        "required": ["eventType", "createdAt", "data"],
        "description": "Supported domestic CARD/BILLING flow subscribes only to Toss PAYMENT_STATUS_CHANGED. Other event types are rejected. Notice status is untrusted; authenticated lookup verifies merchant/order/amount/currency/status. Extra provider fields are ignored."
      },
      "WebhookResult": {
        "type": "object",
        "properties": {
          "duplicate": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          },
          "ignored": {
            "type": "boolean"
          },
          "review_required": {
            "type": "boolean"
          }
        },
        "required": ["duplicate", "status"]
      },
      "ContentType": {
        "type": "string",
        "enum": ["quote", "proverb", "literary_excerpt"],
        "description": "Content form, independent of historical/original kind. quote is a statement or aphorism with author_statement or unknown context; proverb is traditional; literary_excerpt preserves the literary speaker or narrative context. Unknown attribution alone does not invalidate a verified source."
      },
      "AttributionContext": {
        "type": "string",
        "enum": [
          "author_statement",
          "traditional",
          "poetic_speaker",
          "narrator",
          "character",
          "unknown"
        ],
        "description": "Actual attribution context. Never present a poetic speaker, narrator or character as a documented personal statement by the work author. Proverbs use traditional; quotes allow author_statement or unknown. Source-work author and quotation attribution remain separate."
      },
      "TranslationMethod": {
        "type": "string",
        "enum": ["none", "human", "ai_assisted"],
        "description": "How this displayed text was translated. none means no translation. AI-assisted translation is disclosed and is separate from the policy rejecting AI-authored UGC quotations."
      },
      "TranslationReviewStatus": {
        "type": "string",
        "enum": ["not_applicable", "pending", "verified"],
        "description": "Independent translation review status; untranslated text uses not_applicable. Pending translations are held outside public and commercial supply."
      },
      "TranslationReviewMethod": {
        "type": "string",
        "enum": ["", "automated_bilingual_review", "human_editorial_review"],
        "description": "Empty for no translation review. Automated bilingual review never implies human editorial review or human operational approval. A newly confirmed human comparison may set human_editorial_review while translation_method remains ai_assisted; the two fields describe different work."
      },
      "ContentReviewStatus": {
        "type": "string",
        "enum": ["verified", "pending"],
        "description": "Source/content verification status, separate from moderation approval, rights clearance, translation review and human operational release approval."
      },
      "ContentReviewMethod": {
        "type": "string",
        "enum": ["", "automated_source_review", "human_editorial_review", "legacy_source_review"],
        "description": "Actual source verification method. Automated or legacy review must never be labeled as human editorial review; an empty method is not evidence of human review."
      },
      "TranslationRightsLicense": {
        "type": "string",
        "enum": ["", "public_domain", "CC0-1.0", "CC-BY-4.0", "user_owned_output"],
        "description": "Independent rights basis for the translated text, not the original source. Empty for untranslated or legacy records without metadata. user_owned_output records the documented usage basis of user-requested AI output; it is not a public-domain declaration, a copyright-status determination or an invented CC0/CC BY grant. Downstream use remains limited by recorded channel permissions and rights scope."
      },
      "AuthorStatus": {
        "type": "string",
        "enum": ["unknown", "unverified", "attributed", "verified"],
        "description": "Attribution confidence/status, independent of source authenticity, rights clearance, content/translation review and publication status. Unknown authorship alone does not block supply when other eligibility conditions are satisfied; unverified does not mean the source or rights have been verified."
      },
      "TopicId": {
        "type": "string",
        "enum": [
          "life",
          "self-reflection",
          "relationships",
          "courage",
          "learning",
          "time",
          "action",
          "judgment",
          "happiness",
          "moderation",
          "integrity",
          "generosity"
        ],
        "description": "Stable topic identifier from the canonical twelve-topic taxonomy. Topic is independent of content_type=quote|proverb|literary_excerpt; Korean labels are display/API compatibility values, not identifiers."
      },
      "Topic": {
        "type": "object",
        "properties": {
          "id": {
            "$ref": "#/components/schemas/TopicId"
          },
          "label": {
            "type": "string",
            "enum": [
              "삶",
              "자기성찰",
              "관계",
              "용기",
              "배움",
              "시간",
              "실천",
              "판단",
              "행복",
              "절제",
              "정직과 품성",
              "감사와 나눔"
            ],
            "description": "Canonical Korean API/display value for this topic identifier."
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Current eligible public record count for this topic, not an acquisition target or unpublished candidate count."
          }
        },
        "required": ["id", "label", "count"],
        "additionalProperties": false
      },
      "AdminQuote": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "description": "Language of the displayed text, including a reviewed translation when present. Consult original_language and translation metadata for provenance."
          },
          "author": {
            "type": "string",
            "description": "Backward-compatible display attribution, not proof of the actual quotation author. Consult quote_author, source_work_author, author_status and attribution_context. A historical record without a known quote author may display 작자 미상."
          },
          "source_title": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "source_locator": {
            "type": "string"
          },
          "original_text": {
            "type": "string"
          },
          "original_language": {
            "type": "string"
          },
          "translation_author": {
            "type": "string",
            "description": "Actual disclosed translator or AI-assisted translation attribution; empty when no translation. No invented human translator identity."
          },
          "rights_basis": {
            "type": "string",
            "description": "Public rights summary for the original work/source and acquisition scope. The translated text has separate translation_rights_license and translation_rights_basis; private evidence and reviewer identities remain excluded."
          },
          "rights_territory": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "Korean topic API/display value, preserved for compatibility alongside stable category_id. Canonical labels and four legacy aliases are normalized through the shared taxonomy; this field is distinct from content_type."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": ["historical", "original"],
            "description": "Authorship/origin distinction: historical quotation versus contributor original. Independent of content_type and attribution_context."
          },
          "status": {
            "type": "string",
            "enum": ["approved", "withdrawn"]
          },
          "rights_status": {
            "type": "string",
            "enum": ["pending", "cleared", "expired", "withdrawn"]
          },
          "rights_license": {
            "type": "string",
            "enum": ["public_domain", "CC0-1.0", "CC-BY-4.0"],
            "description": "Rights license of the original source or contributor-authored original, assessed separately from translation_rights_license. A public-domain original does not make its translation public-domain."
          },
          "rights_expires_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "commercial_allowed": {
            "type": "boolean",
            "description": "Independent paid/external API-resupply permission. Required for default/free/commercial realtime API supply; not inferred from public display, app display or download redistribution permission. Administrator-designated internal app supply does not require API resale permission."
          },
          "redistribution_allowed": {
            "type": "boolean",
            "description": "Independent dataset download redistribution permission. Snapshot supply requires this and app_display_allowed plus an exact-version entitlement. API-resupply or public-display permission is not inferred or required in its place."
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "content_type": {
            "$ref": "#/components/schemas/ContentType"
          },
          "attribution_context": {
            "$ref": "#/components/schemas/AttributionContext"
          },
          "source_edition": {
            "type": "string",
            "description": "Exact source edition and original publication information; empty for legacy records without this metadata. A later translation or editorial edition is distinct from the original publication."
          },
          "source_registry_id": {
            "type": "string",
            "description": "Acquisition source registry identifier. Empty for records without a registry reference. A registry source assessment is not per-record rights clearance."
          },
          "source_file_url": {
            "type": "string",
            "description": "Public HTTPS URL of the exact source file, or empty for legacy/UGC records. Server-local file paths are never supplied."
          },
          "source_file_sha256": {
            "type": "string",
            "pattern": "^(?:|[a-f0-9]{64})$",
            "description": "SHA256 of the full acquired source file bytes after HTTP decoding, including any original BOM/line endings; empty when not recorded. This is separate from the snapshot response checksum."
          },
          "translation_method": {
            "$ref": "#/components/schemas/TranslationMethod"
          },
          "translation_review_status": {
            "$ref": "#/components/schemas/TranslationReviewStatus"
          },
          "translation_review_method": {
            "$ref": "#/components/schemas/TranslationReviewMethod"
          },
          "content_review_status": {
            "$ref": "#/components/schemas/ContentReviewStatus"
          },
          "content_review_method": {
            "$ref": "#/components/schemas/ContentReviewMethod"
          },
          "app_display_allowed": {
            "type": "boolean",
            "description": "Independent clearance for commercial app display. Required by internal app, external API and snapshot supply; external API also requires commercial_allowed, while snapshots instead require redistribution_allowed."
          },
          "public_display_allowed": {
            "type": "boolean",
            "description": "Independent permission for public website display. Public browser routes require this flag; commercial API/snapshot supply does not require it when its separate app-display, resupply and redistribution permissions are satisfied."
          },
          "translation_rights_license": {
            "$ref": "#/components/schemas/TranslationRightsLicense"
          },
          "translation_rights_basis": {
            "type": "string",
            "description": "Public summary of the independent rights/usage basis of this translated text. Empty when not applicable or unrecorded. Original-source public-domain status cannot substitute for this basis. Private contracts, reviewer identities and evidence remain excluded."
          },
          "author_status": {
            "$ref": "#/components/schemas/AuthorStatus"
          },
          "quote_author": {
            "type": "string",
            "description": "Recorded attribution of the quoted statement itself; may be empty when unknown. It is distinct from the source work author and must be interpreted with author_status and attribution_context."
          },
          "source_work_author": {
            "type": "string",
            "description": "Author of the source work, if recorded; may be empty. Do not automatically attribute a poetic speaker, narrator, character or anonymously quoted statement to this person."
          },
          "category_id": {
            "type": "string",
            "enum": [
              "",
              "life",
              "self-reflection",
              "relationships",
              "courage",
              "learning",
              "time",
              "action",
              "judgment",
              "happiness",
              "moderation",
              "integrity",
              "generosity"
            ],
            "description": "Stable canonical topic ID. Empty is permitted for legacy rows not mapped to a canonical topic. category preserves the Korean API/display value; content_type is a separate classification."
          },
          "manual_edit_revision": {
            "type": ["string", "null"],
            "pattern": "^[0-9]+$"
          },
          "rights_evidence": {
            "type": "string"
          },
          "availability": {
            "type": "object",
            "properties": {
              "public": {
                "type": "boolean"
              },
              "app": {
                "type": "boolean"
              },
              "commercial": {
                "type": "boolean"
              },
              "download": {
                "type": "boolean"
              }
            },
            "required": ["public", "app", "commercial", "download"],
            "additionalProperties": false
          }
        },
        "required": [
          "text",
          "language",
          "author",
          "source_title",
          "source_url",
          "source_locator",
          "original_text",
          "original_language",
          "translation_author",
          "rights_basis",
          "rights_territory",
          "category",
          "id",
          "kind",
          "status",
          "rights_status",
          "rights_license",
          "rights_expires_at",
          "commercial_allowed",
          "redistribution_allowed",
          "revision",
          "created_at",
          "updated_at",
          "content_type",
          "attribution_context",
          "source_edition",
          "source_registry_id",
          "source_file_url",
          "source_file_sha256",
          "translation_method",
          "translation_review_status",
          "translation_review_method",
          "content_review_status",
          "content_review_method",
          "app_display_allowed",
          "public_display_allowed",
          "translation_rights_license",
          "translation_rights_basis",
          "author_status",
          "quote_author",
          "source_work_author",
          "category_id",
          "manual_edit_revision",
          "availability"
        ],
        "description": "Administrator-only current quote; private source/rights evidence and actual per-channel availability are included. No permissions are granted by reading this object."
      },
      "AdminQuoteHistory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "actor_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "action": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "before_data": {
            "type": ["object", "null"],
            "additionalProperties": true
          },
          "after_data": {
            "type": ["object", "null"],
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "actor_id",
          "action",
          "reason",
          "created_at",
          "before_data",
          "after_data"
        ],
        "additionalProperties": false
      },
      "AdminQuoteDetail": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AdminQuote"
          },
          "history": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/AdminQuoteHistory"
                },
                {
                  "$ref": "#/components/schemas/AdminQuoteHistorySummary"
                }
              ]
            }
          },
          "history_limit": {
            "type": "integer",
            "const": 20
          },
          "history_total": {
            "type": "integer",
            "minimum": 0
          },
          "history_page": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": ["data", "history", "history_limit", "history_total"],
        "additionalProperties": false
      },
      "AdminQuotePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminQuoteSummary"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": ["data", "total", "page", "limit"],
        "additionalProperties": false
      },
      "AdminQuoteEditRequest": {
        "type": "object",
        "properties": {
          "expected_revision": {
            "type": "string",
            "pattern": "^[0-9]{1,19}$"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          },
          "changes": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "original_text": {
                "type": "string"
              },
              "author": {
                "type": "string",
                "description": "Backward-compatible display attribution, not proof of the actual quotation author. Consult quote_author, source_work_author, author_status and attribution_context. A historical record without a known quote author may display 작자 미상."
              },
              "author_status": {
                "$ref": "#/components/schemas/AuthorStatus"
              },
              "quote_author": {
                "type": "string",
                "description": "Recorded attribution of the quoted statement itself; may be empty when unknown. It is distinct from the source work author and must be interpreted with author_status and attribution_context."
              },
              "source_work_author": {
                "type": "string",
                "description": "Author of the source work, if recorded; may be empty. Do not automatically attribute a poetic speaker, narrator, character or anonymously quoted statement to this person."
              },
              "category_id": {
                "type": "string",
                "enum": [
                  "",
                  "life",
                  "self-reflection",
                  "relationships",
                  "courage",
                  "learning",
                  "time",
                  "action",
                  "judgment",
                  "happiness",
                  "moderation",
                  "integrity",
                  "generosity"
                ],
                "description": "Stable canonical topic ID. Empty is permitted for legacy rows not mapped to a canonical topic. category preserves the Korean API/display value; content_type is a separate classification."
              },
              "content_type": {
                "$ref": "#/components/schemas/ContentType"
              },
              "attribution_context": {
                "$ref": "#/components/schemas/AttributionContext"
              },
              "source_title": {
                "type": "string"
              },
              "source_edition": {
                "type": "string",
                "description": "Exact source edition and original publication information; empty for legacy records without this metadata. A later translation or editorial edition is distinct from the original publication."
              },
              "source_url": {
                "type": "string"
              },
              "source_file_url": {
                "type": "string",
                "description": "Public HTTPS URL of the exact source file, or empty for legacy/UGC records. Server-local file paths are never supplied."
              },
              "source_locator": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": ["approved", "withdrawn"]
              },
              "public_display_allowed": {
                "type": "boolean",
                "description": "Independent permission for public website display. Public browser routes require this flag; commercial API/snapshot supply does not require it when its separate app-display, resupply and redistribution permissions are satisfied."
              }
            },
            "minProperties": 1,
            "additionalProperties": false
          },
          "source_verified": {
            "type": "boolean",
            "default": false
          },
          "translation_verified": {
            "type": "boolean",
            "default": false
          }
        },
        "required": ["expected_revision", "request_id", "reason", "changes"],
        "additionalProperties": false,
        "description": "Only listed fields may change. Source/original/attribution changes require source_verified. Translated text changes require translation_verified. AI authorship and license/entitlement flags remain unchanged. Same request ID plus identical body is replayed; a new payload using that ID conflicts."
      },
      "AdminQuoteEditResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AdminQuote"
          },
          "unchanged": {
            "type": "boolean"
          },
          "replayed": {
            "type": "boolean"
          }
        },
        "required": ["data", "unchanged", "replayed"],
        "additionalProperties": false
      },
      "OAuthStartRequest": {
        "type": "object",
        "required": ["terms"],
        "additionalProperties": false,
        "properties": {
          "terms": {
            "const": true
          },
          "return_to": {
            "type": "string",
            "maxLength": 2048
          },
          "intent": {
            "type": "string",
            "enum": ["login", "link"],
            "default": "login"
          }
        }
      },
      "AcquisitionCandidate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "dataset_id": {
            "type": "string"
          },
          "external_id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "original_text": {
            "type": "string"
          },
          "original_language": {
            "type": "string"
          },
          "korean_translation": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "source_title": {
            "type": "string"
          },
          "source_url": {
            "type": "string"
          },
          "source_sha256": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "revision": {
            "type": "string"
          },
          "manual_edit_revision": {
            "type": "string"
          },
          "translation_status": {
            "type": "string",
            "enum": ["not_required", "pending", "review_pending", "verified"]
          },
          "rights_status": {
            "type": "string",
            "enum": ["pending", "documented", "conditional", "cleared", "excluded"]
          },
          "editorial_status": {
            "type": "string",
            "enum": ["pending", "held", "verified"]
          },
          "publication_status": {
            "type": "string",
            "enum": ["private", "approved", "excluded"]
          },
          "content_type": {
            "type": "string",
            "enum": ["quote", "proverb", "literary_excerpt", "other"]
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "duplicate_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "dataset_id",
          "external_id",
          "text",
          "language",
          "original_text",
          "original_language",
          "korean_translation",
          "author",
          "source_title",
          "source_url",
          "source_sha256",
          "reason",
          "revision",
          "manual_edit_revision",
          "translation_status",
          "rights_status",
          "editorial_status",
          "publication_status",
          "content_type",
          "quote_id",
          "duplicate_count"
        ],
        "additionalProperties": true,
        "description": "Administrator-only staging record. Independent statuses never grant public/API/download permission. Full original input and history are private."
      },
      "AcquisitionPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcquisitionSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "counts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "datasets": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          },
          "datasets_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": ["data", "total", "page", "limit", "counts", "sources", "datasets"]
      },
      "AcquisitionDetail": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "incoming": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "history_total": {
            "type": "integer",
            "minimum": 0
          },
          "history_page": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": ["data", "history", "incoming"]
      },
      "AcquisitionEditRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["expected_revision", "request_id", "reason", "changes"],
        "properties": {
          "expected_revision": {
            "type": "string",
            "pattern": "^\\d{1,18}$"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 3000
          },
          "changes": {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "text": {
                "type": "string"
              },
              "original_text": {
                "type": "string"
              },
              "korean_translation": {
                "type": "string"
              },
              "author": {
                "type": "string"
              },
              "source_title": {
                "type": "string"
              },
              "source_url": {
                "type": "string"
              },
              "translation_status": {
                "type": "string",
                "enum": ["not_required", "pending", "review_pending", "verified"]
              },
              "rights_status": {
                "type": "string",
                "enum": ["pending", "documented", "conditional", "cleared", "excluded"]
              },
              "editorial_status": {
                "type": "string",
                "enum": ["pending", "held", "verified"]
              },
              "publication_status": {
                "type": "string",
                "enum": ["private", "excluded"]
              },
              "content_type": {
                "type": "string",
                "enum": ["quote", "proverb", "literary_excerpt", "other"]
              }
            }
          }
        }
      },
      "AcquisitionEditResult": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object"
          },
          "replayed": {
            "type": "boolean"
          }
        },
        "required": ["data", "replayed"]
      },
      "QuoteReactions": {
        "type": "object",
        "required": ["count", "liked", "saved", "version"],
        "additionalProperties": false,
        "properties": {
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "liked": {
            "type": "boolean"
          },
          "saved": {
            "type": "boolean"
          },
          "version": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "InterpretationLikeInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "liked": {
            "type": "boolean"
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483646
          }
        },
        "required": ["liked", "version"]
      },
      "InterpretationReportInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "enum": ["rights", "abuse", "misleading", "other"]
          },
          "detail": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          }
        },
        "required": ["reason", "detail"]
      },
      "InterpretationModerateInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "action": {
            "type": "string",
            "enum": ["hide", "restore", "publish"]
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483646
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          }
        },
        "required": ["action", "version", "reason"]
      },
      "InterpretationResolveInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": ["resolved", "dismissed"]
          },
          "version": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2147483646
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          }
        },
        "required": ["status", "version", "reason"]
      },
      "InterpretationReaction": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "liked": {
            "type": "boolean"
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          }
        },
        "required": ["count", "liked", "version"]
      },
      "PublicInterpretation": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": ["basic", "user"]
          },
          "body": {
            "type": "string"
          },
          "ai_assisted": {
            "type": "boolean"
          },
          "responsibility": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "approved"
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "author": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "liked": {
            "type": "boolean"
          },
          "reaction_version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483647
          },
          "own": {
            "type": "boolean"
          },
          "report_status": {
            "type": ["string", "null"],
            "enum": ["open", "resolved", "dismissed", null]
          },
          "review_method": {
            "type": "string",
            "enum": ["none", "human", "automated"],
            "description": "검토 방법. automated는 사람 검토가 아닌 Codex 자동 평가이며 실행 원장과 원문 revision에 연결된다."
          }
        },
        "required": [
          "id",
          "quote_id",
          "kind",
          "body",
          "ai_assisted",
          "responsibility",
          "status",
          "version",
          "updated_at",
          "author",
          "count",
          "liked",
          "reaction_version",
          "own",
          "report_status"
        ]
      },
      "InterpretationFeed": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "basic": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PublicInterpretation"
              },
              {
                "type": "null"
              }
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicInterpretation"
            }
          },
          "next_cursor": {
            "type": ["string", "null"]
          },
          "sort": {
            "type": "string",
            "enum": ["popular", "latest"]
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$"
          }
        },
        "required": ["basic", "data", "next_cursor", "sort", "revision"]
      },
      "ServiceProfile": {
        "type": "object",
        "additionalProperties": false,
        "required": ["display_name", "version"],
        "properties": {
          "display_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "version": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "ServiceProfileResult": {
        "type": "object",
        "additionalProperties": false,
        "required": ["profile"],
        "properties": {
          "profile": {
            "$ref": "#/components/schemas/ServiceProfile"
          }
        }
      },
      "ServiceProfileRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["display_name", "version"],
        "properties": {
          "display_name": {
            "type": "string",
            "maxLength": 240,
            "description": "NFC・공백 정리 후 1~60 코드포인트. 제어/형식 문자 금지, 중복 허용. 서비스 전용."
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483646
          }
        }
      },
      "PersonalInterpretation": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "kind",
          "author",
          "body",
          "status",
          "published",
          "ai_assisted",
          "responsibility",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": ["basic", "user"]
          },
          "author": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "published": {
            "type": "boolean"
          },
          "ai_assisted": {
            "type": "boolean"
          },
          "responsibility": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "review_method": {
            "type": "string",
            "enum": ["none", "human", "automated"],
            "description": "검토 방법. automated는 사람 검토가 아닌 Codex 자동 평가이며 실행 원장과 원문 revision에 연결된다."
          }
        }
      },
      "PersonalPage": {
        "type": "object",
        "additionalProperties": false,
        "required": ["data", "kind", "page", "total", "page_size"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["quote"],
              "properties": {
                "quote": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Quote"
                    },
                    {
                      "$ref": "#/components/schemas/QuoteCard"
                    }
                  ]
                },
                "interpretation": {
                  "$ref": "#/components/schemas/PersonalInterpretation"
                }
              }
            }
          },
          "kind": {
            "type": "string",
            "enum": ["saved", "likes", "interpretation-likes", "interpretations"]
          },
          "page": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "page_size": {
            "type": "integer",
            "const": 20
          }
        }
      },
      "PricingPolicy": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "const": "draft_retained"
          },
          "reader_price_krw": {
            "type": "integer",
            "const": 0
          },
          "tax_status": {
            "type": "string",
            "const": "unconfirmed"
          },
          "tax_notice": {
            "type": "string"
          },
          "resource_limits": {
            "type": "object",
            "properties": {
              "organizations_per_account": {
                "type": "integer",
                "minimum": 1
              },
              "apps_per_organization": {
                "type": "integer",
                "minimum": 1
              },
              "active_keys_per_organization": {
                "type": "integer",
                "minimum": 1
              }
            },
            "required": [
              "organizations_per_account",
              "apps_per_organization",
              "active_keys_per_organization"
            ],
            "additionalProperties": false
          },
          "contributor_status": {
            "type": "string",
            "enum": ["planned", "available"]
          },
          "support_notice": {
            "type": "string"
          }
        },
        "required": [
          "revision",
          "status",
          "reader_price_krw",
          "tax_status",
          "tax_notice",
          "resource_limits",
          "contributor_status",
          "support_notice"
        ],
        "additionalProperties": false
      },
      "ContributorBenefits": {
        "type": "object",
        "properties": {
          "threshold": {
            "type": "integer",
            "const": 30
          },
          "eligible_count": {
            "type": "integer"
          },
          "terms_version": {
            "type": "string"
          },
          "award": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "major": {
                    "oneOf": [
                      {
                        "type": "integer"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": ["active", "suspended"]
                  },
                  "version": {
                    "type": "integer"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "qualified_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": ["major", "status", "version", "reason", "qualified_at"],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "submissions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "status": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "eligibility": {
                  "type": "string"
                }
              },
              "required": ["id", "status", "created_at", "eligibility"],
              "additionalProperties": false
            }
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "licenses": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "snapshot_version": {
                  "type": "string"
                },
                "org_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "terms_version": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": ["snapshot_version", "org_id", "terms_version", "created_at"],
              "additionalProperties": false
            }
          },
          "appeals": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "detail": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "resolution": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": ["id", "detail", "status", "resolution", "created_at"],
              "additionalProperties": false
            }
          },
          "versions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "snapshot_version": {
                  "type": "string"
                },
                "release": {
                  "type": "string"
                },
                "major": {
                  "type": "integer"
                },
                "available": {
                  "type": "boolean"
                },
                "eligible": {
                  "type": "boolean"
                }
              },
              "required": ["snapshot_version", "release", "major", "available", "eligible"],
              "additionalProperties": false
            }
          },
          "organizations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                }
              },
              "required": ["id", "name"],
              "additionalProperties": false
            }
          },
          "versions_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          },
          "appeals_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": [
          "threshold",
          "eligible_count",
          "terms_version",
          "award",
          "submissions",
          "total",
          "page",
          "page_size",
          "licenses",
          "appeals",
          "versions",
          "organizations"
        ],
        "additionalProperties": false
      },
      "ContributorAdmin": {
        "type": "object",
        "properties": {
          "state": {
            "type": "object",
            "properties": {
              "current_snapshot": {
                "oneOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "version": {
                "type": "integer"
              }
            },
            "required": ["current_snapshot", "version"],
            "additionalProperties": false
          },
          "exports": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "version": {
                  "type": "string"
                },
                "record_count": {
                  "type": "string"
                },
                "release": {
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "published": {
                  "oneOf": [
                    {
                      "type": "boolean"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": ["version", "record_count", "release", "published"],
              "additionalProperties": false
            }
          },
          "awards": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "display_name": {
                  "type": "string"
                },
                "major": {
                  "oneOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "status": {
                  "type": "string"
                },
                "version": {
                  "type": "integer"
                },
                "reason": {
                  "type": "string"
                },
                "qualified_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "eligible_count": {
                  "type": "integer"
                },
                "appeal": {
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "user_id",
                "display_name",
                "major",
                "status",
                "version",
                "reason",
                "qualified_at",
                "eligible_count",
                "appeal"
              ],
              "additionalProperties": false
            }
          },
          "page": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "exports_pagination": {
            "$ref": "#/components/schemas/PageInfo"
          }
        },
        "required": ["state", "exports", "awards", "page", "total"],
        "additionalProperties": false
      },
      "ContributorClaimRequest": {
        "type": "object",
        "properties": {
          "snapshot_version": {
            "type": "string"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "terms_version": {
            "type": "string",
            "const": "2026-10-24-contributor-v1"
          },
          "terms": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["snapshot_version", "org_id", "terms_version", "terms"],
        "additionalProperties": false
      },
      "ContributorAppealRequest": {
        "type": "object",
        "properties": {
          "detail": {
            "type": "string",
            "minLength": 5,
            "maxLength": 2000
          },
          "version": {
            "type": "integer"
          }
        },
        "required": ["detail", "version"],
        "additionalProperties": false
      },
      "ContributorCatalogRequest": {
        "type": "object",
        "properties": {
          "snapshot_version": {
            "type": "string"
          },
          "release": {
            "type": "string",
            "pattern": "^[1-9][0-9]*\\.[0-9]+\\.[0-9]+$"
          },
          "published": {
            "type": "boolean"
          },
          "current": {
            "type": "boolean"
          },
          "version": {
            "type": "integer"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          }
        },
        "required": ["snapshot_version", "release", "published", "current", "version", "reason"],
        "additionalProperties": false
      },
      "ContributorModerationRequest": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": ["suspend", "restore", "dismiss_appeal"]
          },
          "version": {
            "type": "integer"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          }
        },
        "required": ["action", "version", "reason"],
        "additionalProperties": false
      },
      "ContributorIssued": {
        "type": "object",
        "properties": {
          "issued": {
            "type": "boolean",
            "const": true
          },
          "snapshot_version": {
            "type": "string"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": ["issued", "snapshot_version", "org_id"],
        "additionalProperties": false
      },
      "ContributorUpdated": {
        "type": "object",
        "properties": {
          "updated": {
            "type": "boolean",
            "const": true
          }
        },
        "required": ["updated"],
        "additionalProperties": false
      },
      "ContributorAppealReceived": {
        "type": "object",
        "properties": {
          "received": {
            "type": "boolean",
            "const": true
          },
          "status": {
            "type": "string",
            "const": "open"
          }
        },
        "required": ["received", "status"],
        "additionalProperties": false
      },
      "ContributorEmpty": {
        "type": "object",
        "properties": {},
        "required": [],
        "additionalProperties": false
      },
      "ReadingSettings": {
        "type": "object",
        "additionalProperties": false,
        "required": ["palette", "theme", "font", "version"],
        "properties": {
          "palette": {
            "enum": ["ink-teal", "slate-blue", "paper-sage"]
          },
          "theme": {
            "enum": ["system", "light", "dark"]
          },
          "font": {
            "enum": ["ridibatang", "gowun-batang", "nanum-myeongjo", "pretendard"]
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2147483646
          }
        }
      },
      "ReadingSettingsResult": {
        "type": "object",
        "required": ["settings"],
        "properties": {
          "settings": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ReadingSettings"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "LocalePreference": {
        "type": "object",
        "additionalProperties": false,
        "required": ["locale"],
        "properties": {
          "locale": {
            "type": "string",
            "enum": ["ko", "en"]
          }
        }
      },
      "PageInfo": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["page", "page_size", "total"],
        "additionalProperties": false
      },
      "WorkspaceOrder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "amount": {
            "type": "integer",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "const": "KRW"
          },
          "terms_version": {
            "type": "string"
          },
          "snapshot_version": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "refunded_amount": {
            "type": "integer",
            "minimum": 0
          },
          "period_start": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "subscription_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "owner_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id",
          "org_id",
          "product",
          "status",
          "amount",
          "currency",
          "terms_version",
          "refunded_amount",
          "period_start",
          "period_end",
          "subscription_id"
        ],
        "additionalProperties": false
      },
      "WorkspaceSubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "product": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "active", "past_due", "canceled", "failed"]
          },
          "current_period_start": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "current_period_end": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "next_billing_at": {
            "type": "string",
            "format": "date-time"
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "canceled_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "org_id",
          "product",
          "status",
          "current_period_start",
          "current_period_end",
          "next_billing_at",
          "cancel_at_period_end",
          "canceled_at"
        ],
        "additionalProperties": false
      },
      "QuoteCard": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "description": "Language of the displayed text, including a reviewed translation when present. Consult original_language and translation metadata for provenance."
          },
          "author": {
            "type": "string",
            "description": "Backward-compatible display attribution, not proof of the actual quotation author. Consult quote_author, source_work_author, author_status and attribution_context. A historical record without a known quote author may display 작자 미상."
          },
          "author_status": {
            "$ref": "#/components/schemas/AuthorStatus"
          },
          "quote_author": {
            "type": "string",
            "description": "Recorded attribution of the quoted statement itself; may be empty when unknown. It is distinct from the source work author and must be interpreted with author_status and attribution_context."
          },
          "source_work_author": {
            "type": "string",
            "description": "Author of the source work, if recorded; may be empty. Do not automatically attribute a poetic speaker, narrator, character or anonymously quoted statement to this person."
          },
          "kind": {
            "type": "string",
            "enum": ["historical", "original"],
            "description": "Authorship/origin distinction: historical quotation versus contributor original. Independent of content_type and attribution_context."
          },
          "content_type": {
            "$ref": "#/components/schemas/ContentType"
          },
          "attribution_context": {
            "$ref": "#/components/schemas/AttributionContext"
          },
          "category": {
            "type": "string",
            "description": "Korean topic API/display value, preserved for compatibility alongside stable category_id. Canonical labels and four legacy aliases are normalized through the shared taxonomy; this field is distinct from content_type."
          },
          "category_id": {
            "type": "string",
            "enum": [
              "",
              "life",
              "self-reflection",
              "relationships",
              "courage",
              "learning",
              "time",
              "action",
              "judgment",
              "happiness",
              "moderation",
              "integrity",
              "generosity"
            ],
            "description": "Stable canonical topic ID. Empty is permitted for legacy rows not mapped to a canonical topic. category preserves the Korean API/display value; content_type is a separate classification."
          },
          "source_title": {
            "type": "string"
          },
          "original_language": {
            "type": "string"
          },
          "translation_method": {
            "$ref": "#/components/schemas/TranslationMethod"
          },
          "translation_review_status": {
            "$ref": "#/components/schemas/TranslationReviewStatus"
          },
          "translation_review_method": {
            "$ref": "#/components/schemas/TranslationReviewMethod"
          },
          "content_review_status": {
            "$ref": "#/components/schemas/ContentReviewStatus"
          },
          "content_review_method": {
            "$ref": "#/components/schemas/ContentReviewMethod"
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "text",
          "language",
          "author",
          "source_title",
          "original_language",
          "category",
          "id",
          "kind",
          "revision",
          "created_at",
          "updated_at",
          "content_type",
          "attribution_context",
          "translation_method",
          "translation_review_status",
          "translation_review_method",
          "content_review_status",
          "content_review_method",
          "author_status",
          "quote_author",
          "source_work_author",
          "category_id"
        ],
        "additionalProperties": false
      },
      "AdminQuoteSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string",
            "description": "Language of the displayed text, including a reviewed translation when present. Consult original_language and translation metadata for provenance."
          },
          "author": {
            "type": "string",
            "description": "Backward-compatible display attribution, not proof of the actual quotation author. Consult quote_author, source_work_author, author_status and attribution_context. A historical record without a known quote author may display 작자 미상."
          },
          "author_status": {
            "$ref": "#/components/schemas/AuthorStatus"
          },
          "quote_author": {
            "type": "string",
            "description": "Recorded attribution of the quoted statement itself; may be empty when unknown. It is distinct from the source work author and must be interpreted with author_status and attribution_context."
          },
          "source_work_author": {
            "type": "string",
            "description": "Author of the source work, if recorded; may be empty. Do not automatically attribute a poetic speaker, narrator, character or anonymously quoted statement to this person."
          },
          "kind": {
            "type": "string",
            "enum": ["historical", "original"],
            "description": "Authorship/origin distinction: historical quotation versus contributor original. Independent of content_type and attribution_context."
          },
          "content_type": {
            "$ref": "#/components/schemas/ContentType"
          },
          "attribution_context": {
            "$ref": "#/components/schemas/AttributionContext"
          },
          "category": {
            "type": "string",
            "description": "Korean topic API/display value, preserved for compatibility alongside stable category_id. Canonical labels and four legacy aliases are normalized through the shared taxonomy; this field is distinct from content_type."
          },
          "category_id": {
            "type": "string",
            "enum": [
              "",
              "life",
              "self-reflection",
              "relationships",
              "courage",
              "learning",
              "time",
              "action",
              "judgment",
              "happiness",
              "moderation",
              "integrity",
              "generosity"
            ],
            "description": "Stable canonical topic ID. Empty is permitted for legacy rows not mapped to a canonical topic. category preserves the Korean API/display value; content_type is a separate classification."
          },
          "source_title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["approved", "withdrawn"]
          },
          "public_display_allowed": {
            "type": "boolean",
            "description": "Independent permission for public website display. Public browser routes require this flag; commercial API/snapshot supply does not require it when its separate app-display, resupply and redistribution permissions are satisfied."
          },
          "rights_status": {
            "type": "string",
            "enum": ["pending", "cleared", "expired", "withdrawn"]
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "manual_edit_revision": {
            "type": ["string", "null"],
            "pattern": "^[0-9]+$"
          },
          "availability": {
            "type": "object",
            "properties": {
              "public": {
                "type": "boolean"
              },
              "app": {
                "type": "boolean"
              },
              "commercial": {
                "type": "boolean"
              },
              "download": {
                "type": "boolean"
              }
            },
            "required": ["public", "app", "commercial", "download"],
            "additionalProperties": false
          }
        },
        "required": [
          "text",
          "language",
          "author",
          "source_title",
          "category",
          "id",
          "kind",
          "status",
          "rights_status",
          "revision",
          "updated_at",
          "content_type",
          "attribution_context",
          "public_display_allowed",
          "author_status",
          "quote_author",
          "source_work_author",
          "category_id",
          "manual_edit_revision",
          "availability"
        ],
        "additionalProperties": false
      },
      "AuditSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "actor_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "action": {
            "type": "string"
          },
          "target_type": {
            "type": "string"
          },
          "target_id": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "actor_id",
          "action",
          "target_type",
          "target_id",
          "reason",
          "created_at"
        ],
        "additionalProperties": false
      },
      "AdminQuoteHistorySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Opaque monotonic PostgreSQL bigint revision encoded as decimal text. Never parse as a JavaScript number."
          },
          "actor_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "action": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "actor_id", "action", "reason", "created_at"],
        "additionalProperties": false
      },
      "SavedPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["data", "page", "page_size", "total"],
        "additionalProperties": false
      },
      "SubmissionSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "payload": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "kind": {
                "type": "string"
              }
            },
            "required": ["text", "kind"],
            "additionalProperties": false
          },
          "status": {
            "type": "string",
            "enum": ["pending", "approved", "rejected"]
          },
          "review_reason": {
            "type": ["string", "null"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "reviewed_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "quote_id",
          "payload",
          "status",
          "review_reason",
          "created_at",
          "reviewed_at"
        ],
        "description": "Own submission response. A create/review/admin response may additionally contain private moderation fields, available only to the authorized owner or administrator."
      },
      "AdminQuoteHistoryPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminQuoteHistorySummary"
            }
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["data", "page", "page_size", "total"],
        "additionalProperties": false
      },
      "AcquisitionHistorySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "reason", "created_at"],
        "additionalProperties": false
      },
      "AcquisitionHistoryRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "before_data": {
            "type": ["object", "null"]
          },
          "after_data": {
            "type": ["object", "null"]
          }
        },
        "required": ["id", "reason", "created_at", "before_data", "after_data"],
        "additionalProperties": false
      },
      "AcquisitionHistoryPage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcquisitionHistorySummary"
            }
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "page_size": {
            "type": "integer",
            "const": 20
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["data", "page", "page_size", "total"],
        "additionalProperties": false
      },
      "AcquisitionSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "dataset_id": {
            "type": "string"
          },
          "external_id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "content_type": {
            "type": "string",
            "enum": ["quote", "proverb", "literary_excerpt", "other"]
          },
          "source_title": {
            "type": "string"
          },
          "translation_status": {
            "type": "string",
            "enum": ["not_required", "pending", "review_pending", "verified"]
          },
          "rights_status": {
            "type": "string",
            "enum": ["pending", "documented", "conditional", "cleared", "excluded"]
          },
          "editorial_status": {
            "type": "string",
            "enum": ["pending", "held", "verified"]
          },
          "publication_status": {
            "type": "string",
            "enum": ["private", "approved", "excluded"]
          },
          "reason": {
            "type": "string"
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "revision": {
            "type": "string"
          },
          "manual_edit_revision": {
            "type": "string"
          },
          "duplicate_count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "dataset_id",
          "external_id",
          "text",
          "language",
          "author",
          "source_title",
          "reason",
          "revision",
          "manual_edit_revision",
          "translation_status",
          "rights_status",
          "editorial_status",
          "publication_status",
          "content_type",
          "quote_id",
          "duplicate_count"
        ],
        "additionalProperties": false
      },
      "WebQuotePage": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/Quote"
                },
                {
                  "$ref": "#/components/schemas/QuoteCard"
                }
              ]
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": ["data", "total", "page", "limit"]
      },
      "WebQuoteResult": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Quote"
              },
              {
                "$ref": "#/components/schemas/QuoteCard"
              }
            ]
          }
        },
        "required": ["data"]
      },
      "WorkspaceApplication": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          }
        },
        "required": ["id", "org_id", "name"],
        "additionalProperties": false
      },
      "ModerationSubmission": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "payload": {
            "$ref": "#/components/schemas/ContributionRequest"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "approved", "rejected"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "user_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": ["id", "quote_id", "payload", "status", "created_at"],
        "additionalProperties": false
      },
      "ModerationReport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "quote_id", "reason", "detail", "status", "created_at"],
        "additionalProperties": false
      },
      "StudioInput": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "create"
              },
              "request_key": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "prompt": {
                "type": "string",
                "minLength": 1,
                "maxLength": 600
              },
              "tone": {
                "type": "string",
                "enum": ["담백하게", "따뜻하게", "또렷하게"]
              },
              "length": {
                "type": "string",
                "enum": ["짧게", "보통"]
              }
            },
            "required": ["kind", "request_key", "prompt", "tone", "length"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "refine"
              },
              "request_key": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "source_job": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              },
              "candidate": {
                "type": "integer",
                "minimum": 0,
                "maximum": 2
              },
              "meaning_anchor": {
                "type": "string",
                "minLength": 1,
                "maxLength": 180
              },
              "instruction": {
                "type": "string",
                "minLength": 1,
                "maxLength": 300
              }
            },
            "required": [
              "kind",
              "request_key",
              "source_job",
              "candidate",
              "meaning_anchor",
              "instruction"
            ],
            "additionalProperties": false
          }
        ]
      },
      "StudioSave": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "candidate": {
            "type": "integer",
            "minimum": 0,
            "maximum": 2
          }
        },
        "required": ["job_id", "candidate"],
        "additionalProperties": false
      },
      "StudioEdit": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "const": "edit"
              },
              "version": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              },
              "body": {
                "type": "string",
                "minLength": 1,
                "maxLength": 160
              },
              "meaning_anchor": {
                "type": "string",
                "minLength": 1,
                "maxLength": 180
              }
            },
            "required": ["action", "version", "body", "meaning_anchor"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "const": "delete"
              },
              "version": {
                "type": "integer",
                "exclusiveMinimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": ["action", "version"],
            "additionalProperties": false
          }
        ]
      },
      "StudioCandidate": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "approach": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "meaning_anchor": {
            "type": "string",
            "minLength": 1,
            "maxLength": 180
          }
        },
        "required": ["body", "approach", "meaning_anchor"],
        "additionalProperties": false
      },
      "StudioJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "enum": ["create", "refine"]
          },
          "status": {
            "enum": ["queued", "running", "succeeded", "failed", "cancelled", "uncertain"]
          },
          "result": {
            "anyOf": [
              {
                "type": "array",
                "items": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/StudioCandidate"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "error_code": {
            "type": ["string", "null"]
          },
          "cancel_requested": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "cost_micro": {
            "type": "integer"
          },
          "input_tokens": {
            "type": "integer"
          },
          "output_tokens": {
            "type": "integer"
          },
          "calls": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "kind",
          "status",
          "result",
          "error_code",
          "cancel_requested",
          "created_at",
          "cost_micro",
          "input_tokens",
          "output_tokens",
          "calls"
        ]
      },
      "StudioWork": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "candidate": {
            "type": "integer"
          },
          "body": {
            "type": "string"
          },
          "meaning_anchor": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "deleted": {
            "type": "boolean"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "job_id",
          "candidate",
          "body",
          "meaning_anchor",
          "version",
          "deleted",
          "updated_at"
        ]
      },
      "StudioView": {
        "type": "object",
        "properties": {
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudioJob"
            }
          },
          "works": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StudioWork"
            }
          },
          "total": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "enabled": {
            "type": "boolean"
          },
          "usage": {
            "type": "object",
            "properties": {
              "used": {
                "type": "integer"
              },
              "reserved": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "cost_micro": {
                "type": "integer"
              },
              "reset_at": {
                "type": "string",
                "format": "date-time"
              }
            },
            "required": ["used", "reserved", "limit", "cost_micro", "reset_at"]
          }
        },
        "required": ["jobs", "works", "total", "page", "enabled", "usage"]
      },
      "StudioEmpty": {
        "type": "object",
        "additionalProperties": false
      },
      "OrganizationQuota": {
        "type": "object",
        "properties": {
          "org_id": {
            "type": "string"
          },
          "org_name": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "resets_at": {
            "type": "string"
          },
          "minute_resets_at": {
            "type": "string"
          },
          "plan": {
            "type": ["string", "null"]
          },
          "status": {
            "type": "string",
            "enum": ["active", "unavailable"]
          },
          "reason": {
            "type": ["string", "null"]
          },
          "used": {
            "type": "integer",
            "minimum": 0
          },
          "minute_used": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "remaining": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "minute_limit": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "minute_remaining": {
            "type": ["integer", "null"],
            "minimum": 0
          }
        },
        "required": [
          "org_id",
          "org_name",
          "period",
          "resets_at",
          "minute_resets_at",
          "plan",
          "status",
          "reason",
          "used",
          "minute_used",
          "limit",
          "remaining",
          "minute_limit",
          "minute_remaining"
        ]
      },
      "DeveloperRequestLog": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "org_name": {
            "type": "string"
          },
          "app_name": {
            "type": "string"
          },
          "key_name": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "endpoint": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": 100,
            "maximum": 599
          },
          "error_code": {
            "type": ["string", "null"]
          },
          "duration_ms": {
            "type": "integer",
            "minimum": 0
          },
          "outcome": {
            "type": "string",
            "enum": ["pending", "succeeded", "failed", "interrupted"]
          },
          "quota_counted": {
            "type": ["boolean", "null"]
          },
          "quota_period": {
            "type": ["string", "null"]
          },
          "completed_at": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "request_id",
          "org_name",
          "app_name",
          "key_name",
          "method",
          "endpoint",
          "created_at",
          "status",
          "error_code",
          "duration_ms",
          "outcome",
          "quota_counted",
          "quota_period",
          "completed_at"
        ]
      },
      "DeveloperKeyAudit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "org_name": {
            "type": "string"
          },
          "app_name": {
            "type": "string"
          },
          "key_name": {
            "type": "string"
          },
          "key_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string"
          },
          "actor_id": {
            "type": ["string", "null"]
          },
          "action": {
            "type": "string",
            "enum": ["issued", "revoked"]
          }
        },
        "required": [
          "id",
          "org_name",
          "app_name",
          "key_name",
          "key_id",
          "created_at",
          "actor_id",
          "action"
        ]
      },
      "AppSyncBasis": {
        "type": "object",
        "properties": {
          "schema_version": {
            "const": "1"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "cursor": {
            "type": "string",
            "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
          },
          "language": {
            "const": "ko"
          },
          "territory": {
            "const": "KR"
          }
        },
        "required": ["schema_version", "scope", "cursor", "language", "territory"],
        "additionalProperties": false
      },
      "AppSyncVerification": {
        "type": "object",
        "properties": {
          "server_time": {
            "type": "string",
            "format": "date-time"
          },
          "offline_valid_until": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["server_time", "offline_valid_until"],
        "additionalProperties": false
      },
      "AppSyncDownload": {
        "type": "object",
        "properties": {
          "schema_version": {
            "const": "1"
          },
          "sync": {
            "$ref": "#/components/schemas/AppSyncBasis"
          },
          "verification": {
            "$ref": "#/components/schemas/AppSyncVerification"
          },
          "quotes": {
            "type": "array",
            "maxItems": 10000,
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          }
        },
        "required": ["schema_version", "sync", "verification", "quotes"],
        "additionalProperties": false
      },
      "AppSyncChange": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "operation": {
                "const": "upsert"
              },
              "quote_id": {
                "type": "string",
                "format": "uuid"
              },
              "revision": {
                "type": "string",
                "pattern": "^[0-9]+$"
              },
              "data": {
                "$ref": "#/components/schemas/Quote"
              }
            },
            "required": ["operation", "quote_id", "revision", "data"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "operation": {
                "const": "delete"
              },
              "quote_id": {
                "type": "string",
                "format": "uuid"
              },
              "revision": {
                "type": "string",
                "pattern": "^[0-9]+$"
              }
            },
            "required": ["operation", "quote_id", "revision"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "operation": {
                "const": "invalidate"
              },
              "quote_id": {
                "type": "string",
                "format": "uuid"
              },
              "revision": {
                "type": "string",
                "pattern": "^[0-9]+$"
              },
              "delete_before_revision": {
                "type": "string",
                "pattern": "^[0-9]+$"
              }
            },
            "required": ["operation", "quote_id", "revision", "delete_before_revision"],
            "additionalProperties": false
          }
        ]
      },
      "AppSyncChanges": {
        "type": "object",
        "properties": {
          "schema_version": {
            "const": "1"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "from_cursor": {
            "type": "string",
            "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
          },
          "next_cursor": {
            "type": "string",
            "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
          },
          "has_more": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AppSyncChange"
            }
          },
          "verification": {
            "$ref": "#/components/schemas/AppSyncVerification"
          },
          "active_ids": {
            "type": "array",
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "required": [
          "schema_version",
          "scope",
          "from_cursor",
          "next_cursor",
          "has_more",
          "data",
          "verification"
        ],
        "additionalProperties": false
      },
      "AppSyncManifest": {
        "type": "object",
        "properties": {
          "schema_version": {
            "const": "1"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "cursor": {
            "type": "string",
            "pattern": "^ko-KR-v1:[a-f0-9-]{36}:(0|[1-9][0-9]{0,18})$"
          },
          "language": {
            "const": "ko"
          },
          "territory": {
            "const": "KR"
          },
          "policy": {
            "type": "object",
            "properties": {
              "check_interval_seconds": {
                "type": "integer",
                "const": 21600
              },
              "offline_max_seconds": {
                "type": "integer",
                "const": 86400
              },
              "default_page_size": {
                "type": "integer",
                "const": 200
              },
              "max_page_size": {
                "type": "integer",
                "const": 500
              },
              "max_records": {
                "type": "integer",
                "const": 10000
              },
              "max_response_bytes": {
                "type": "integer",
                "const": 16777216
              },
              "requests_per_minute": {
                "type": "integer",
                "const": 120
              },
              "downloads_per_minute": {
                "type": "integer",
                "const": 5
              }
            },
            "required": [
              "check_interval_seconds",
              "offline_max_seconds",
              "default_page_size",
              "max_page_size",
              "max_records",
              "max_response_bytes",
              "requests_per_minute",
              "downloads_per_minute"
            ],
            "additionalProperties": false
          },
          "record_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000
          },
          "server_time": {
            "type": "string",
            "format": "date-time"
          },
          "endpoints": {
            "type": "object",
            "properties": {
              "download": {
                "const": "/api/v1/sync/download"
              },
              "changes": {
                "const": "/api/v1/sync/changes"
              },
              "removals": {
                "const": "/api/v1/sync/removals"
              }
            },
            "required": ["download", "changes", "removals"],
            "additionalProperties": false
          }
        },
        "required": [
          "schema_version",
          "scope",
          "cursor",
          "language",
          "territory",
          "policy",
          "record_count",
          "server_time",
          "endpoints"
        ],
        "additionalProperties": false
      },
      "AppSyncGrant": {
        "type": "object",
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "valid_until": {
            "type": "string",
            "format": "date-time"
          },
          "revoked_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "version": {
            "type": "string",
            "pattern": "^[0-9]+$"
          }
        },
        "required": ["app_id", "org_id", "valid_until", "revoked_at", "version"],
        "additionalProperties": false
      },
      "AppSyncGrantResult": {
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AppSyncGrant"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": ["data"],
        "additionalProperties": false
      },
      "AppSyncGrantInput": {
        "type": "object",
        "properties": {
          "app_id": {
            "type": "string",
            "format": "uuid"
          },
          "valid_until": {
            "type": "string",
            "format": "date-time"
          },
          "revoked": {
            "type": "boolean"
          },
          "expected_version": {
            "type": ["string", "null"],
            "pattern": "^[1-9][0-9]{0,18}$"
          },
          "reason": {
            "type": "string",
            "minLength": 5,
            "maxLength": 500
          }
        },
        "required": ["app_id", "valid_until", "revoked", "expected_version", "reason"],
        "additionalProperties": false
      },
      "PublicationFile": {
        "type": "object",
        "required": ["sha256", "bytes", "json_sha256", "json_bytes", "encoding"],
        "properties": {
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "bytes": {
            "type": "integer"
          },
          "json_sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "json_bytes": {
            "type": "integer"
          },
          "encoding": {
            "const": "gzip"
          }
        }
      },
      "PublicationManifest": {
        "type": "object",
        "required": [
          "schema_version",
          "scope",
          "release_id",
          "content_hash",
          "record_count",
          "sync",
          "plan",
          "from_release",
          "file"
        ],
        "properties": {
          "schema_version": {
            "const": "2"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "release_id": {
            "type": "string"
          },
          "content_hash": {
            "type": "string"
          },
          "record_count": {
            "type": "integer"
          },
          "sync": {
            "type": "object"
          },
          "plan": {
            "enum": ["none", "base", "patch"]
          },
          "from_release": {
            "type": ["string", "null"]
          },
          "file": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PublicationFile"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PublishedBase": {
        "type": "object",
        "required": ["schema_version", "scope", "content_hash", "sync", "release_id", "quotes"],
        "properties": {
          "schema_version": {
            "const": "2"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "content_hash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "sync": {
            "$ref": "#/components/schemas/AppSyncBasis"
          },
          "release_id": {
            "type": "string"
          },
          "quotes": {
            "type": "array",
            "maxItems": 10000,
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          }
        }
      },
      "PublishedPatch": {
        "type": "object",
        "required": [
          "schema_version",
          "scope",
          "content_hash",
          "sync",
          "from_release",
          "to_release",
          "record_count",
          "upserts",
          "deletes"
        ],
        "properties": {
          "schema_version": {
            "const": "2"
          },
          "scope": {
            "const": "ko-KR-v1"
          },
          "content_hash": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "sync": {
            "$ref": "#/components/schemas/AppSyncBasis"
          },
          "from_release": {
            "type": "string"
          },
          "to_release": {
            "type": "string"
          },
          "record_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000
          },
          "upserts": {
            "type": "array",
            "maxItems": 10000,
            "items": {
              "$ref": "#/components/schemas/Quote"
            }
          },
          "deletes": {
            "type": "array",
            "maxItems": 10000,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      }
    },
    "responses": {
      "Error400": {
        "description": "Malformed JSON, invalid field/filter/cursor/ID or request validation failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error401": {
        "description": "Missing, invalid, expired or revoked session/API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error402": {
        "description": "Realtime product entitlement is absent or expired.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error403": {
        "description": "CSRF origin rejected, email unverified, tenant/owner/admin/rights permission denied.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error404": {
        "description": "Resource unavailable, unapproved, withdrawn or not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error405": {
        "description": "HTTP method not supported.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error409": {
        "description": "Duplicate, stale revision, state conflict, self-service limit or unavailable subscription. Snapshot creation also fails with no_common_territory when supplied records have no common rights territory.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error410": {
        "description": "Pinned snapshot contains withdrawn, changed or expired content; do not redistribute this version.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error413": {
        "description": "Request body exceeds the accepted size.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error415": {
        "description": "Expected application/json request body.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error422": {
        "description": "Content attribution/consent/rights or moderation policy failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error429": {
        "description": "Hard rate or monthly quota limit; no automatic overage charge.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "description": "Advisory seconds before retry. Monthly quota exhaustion still requires a new quota period or approved plan change.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "Error500": {
        "description": "Unexpected server error. Request identifier can be used for support.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error503": {
        "description": "Database/mail/provider unavailable, integrity check failed, or payment adapter explicitly disconnected.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "x-pricing": {
    "status": "draft",
    "payment_connected": false,
    "terms_version": "2026-10-28-license-clarification",
    "currency": "KRW",
    "plans": [
      {
        "id": "free",
        "price_krw": 0,
        "monthly_requests": 300,
        "requests_per_minute": 30
      },
      {
        "id": "starter",
        "price_krw": 9900,
        "monthly_requests": 10000,
        "requests_per_minute": 60
      },
      {
        "id": "growth",
        "price_krw": 29000,
        "monthly_requests": 100000,
        "requests_per_minute": 300
      },
      {
        "id": "business",
        "price_krw": 99000,
        "monthly_requests": 1000000,
        "requests_per_minute": 600
      },
      {
        "id": "snapshot",
        "price_krw": 99000,
        "monthly_requests": 0,
        "requests_per_minute": 0
      }
    ],
    "internal": {
      "administrator_only": true,
      "monthly_requests": 100000,
      "requests_per_minute": 600
    },
    "quota_scope": "organization",
    "period": "UTC calendar month",
    "billable": "successful realtime content response only",
    "automatic_overage": false,
    "snapshot_is_separate": true,
    "connection_state_semantics": "payment_connected=false is the shipped default, not a constant runtime guarantee. plans/workspace expose configured runtime state.",
    "runtime_connection_configurable": true,
    "billing_separate_approval": true
  },
  "x-content-policy": {
    "initial_records": 9,
    "initial_authors": 4,
    "korean_translations": 0,
    "territories": ["KR", "US"],
    "supply_requires": [
      "status=approved",
      "rights_status=cleared",
      "content_review_status=verified",
      "rights not expired",
      "translation verified when language differs from original_language",
      "commercial_allowed=true",
      "app_display_allowed=true"
    ],
    "private_fields_excluded": [
      "contributor_id",
      "normalized_text",
      "rights_evidence",
      "original_fingerprint",
      "source_file_path",
      "reviewer",
      "import_ledger_payload"
    ],
    "korean_originals": 3,
    "review_method": "automated_source_verification",
    "human_operational_approval": "pending",
    "baseline_counts_are_not_live_totals": true,
    "content_types": ["quote", "proverb", "literary_excerpt"],
    "attribution_contexts": [
      "author_statement",
      "traditional",
      "poetic_speaker",
      "narrator",
      "character",
      "unknown"
    ],
    "review_states_separate": [
      "moderation",
      "rights",
      "content_review",
      "translation_review",
      "human_operational_release"
    ],
    "commercial_permissions_separate": [
      "public_display_allowed",
      "app_display_allowed",
      "commercial_allowed",
      "redistribution_allowed"
    ],
    "import_contract": "docs/content-import-contract.md; local CLI validation/apply only, no public import HTTP endpoint",
    "translation_policy": "Original-source and translation rights are separate and publicly preserved as translation_rights_license/translation_rights_basis. user_owned_output is a documented usage basis for user-requested AI output, not a public-domain or CC license grant. ai_assisted remains disclosed after human review; automated_bilingual_review is not human_editorial_review. New/changed UGC translations require independent rights and explicit administrator comparison; pending reviews are held.",
    "public_supply_requires": [
      "status=approved",
      "rights_status=cleared",
      "content_review_status=verified",
      "rights not expired",
      "translation verified when language differs from original_language",
      "public_display_allowed=true"
    ],
    "internal_app_supply_requires": [
      "status=approved",
      "rights_status=cleared",
      "content_review_status=verified",
      "rights not expired",
      "translation verified when language differs from original_language",
      "app_display_allowed=true",
      "administrator-designated internal plan",
      "same authentication and bounded quotas"
    ],
    "snapshot_supply_requires": [
      "status=approved",
      "rights_status=cleared",
      "content_review_status=verified",
      "rights not expired",
      "translation verified when language differs from original_language",
      "app_display_allowed=true",
      "redistribution_allowed=true",
      "explicit active entitlement for the exact version"
    ],
    "permissions_do_not_imply_one_another": true,
    "author_attribution_policy": "author is a compatibility display name; quote_author and source_work_author are distinct. author_status=unknown|unverified|attributed|verified is independent of provenance, rights and review. Unknown authorship alone never blocks otherwise eligible supply; no invented attribution is permitted.",
    "topics": [
      {
        "id": "life",
        "label": "삶"
      },
      {
        "id": "self-reflection",
        "label": "자기성찰"
      },
      {
        "id": "relationships",
        "label": "관계"
      },
      {
        "id": "courage",
        "label": "용기"
      },
      {
        "id": "learning",
        "label": "배움"
      },
      {
        "id": "time",
        "label": "시간"
      },
      {
        "id": "action",
        "label": "실천"
      },
      {
        "id": "judgment",
        "label": "판단"
      },
      {
        "id": "happiness",
        "label": "행복"
      },
      {
        "id": "moderation",
        "label": "절제"
      },
      {
        "id": "integrity",
        "label": "정직과 품성"
      },
      {
        "id": "generosity",
        "label": "감사와 나눔"
      }
    ],
    "legacy_topic_aliases": {
      "고독": "self-reflection",
      "단순함": "moderation",
      "성장": "action",
      "진실": "integrity"
    },
    "topic_content_type_independent": true,
    "snapshot_territory_policy": "intersection_of_record_territories; empty intersection returns409 no_common_territory",
    "territories_semantics": "Supported territory codes only; each record may have a narrower scope, and a snapshot uses the intersection.",
    "legacy_commercial_hold": {
      "migration": "009_legacy_commercial_hold.sql",
      "records": 3,
      "source": "Gongu Korean literary excerpts",
      "public_local_reading": true,
      "app_display_allowed": false,
      "commercial_allowed": false,
      "redistribution_allowed": false,
      "reason": "Source registry commercial acquisition/resupply clearance remains pending; original public-domain status does not clear the acquisition route."
    }
  },
  "x-authentication": {
    "authority": "Supabase Auth",
    "providers": ["email", "google", "apple"],
    "social_external_test": "상용 연결 이후",
    "cookies": ["mq_sb_access", "mq_sb_refresh", "mq_session"],
    "server_user_verification": "GET /auth/v1/user",
    "password_stored_by_service": false,
    "automatic_email_merge": false
  }
}
