openapi: 3.1.0
info:
  title: GAMIA Signups API
  version: 0.1.0
  description: |
    Backend mínimo para registrar interesados en GAMIA (Torre Villavicencio, propuesta de hub de IA en Santiago).
    Tres endpoints: health check, contador público de inscripciones, y captura de signup.
  contact:
    url: https://gamia.cl
servers:
  - url: https://gamia.cl
    description: Producción
externalDocs:
  description: Developer reference with curl + JS + Python examples and full error matrix
  url: https://gamia.cl/api/docs.md
paths:
  /api/health:
    get:
      summary: Health check
      operationId: getHealth
      responses:
        '200':
          description: Servicio operativo
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Health' }
              example: { ok: true }
  /api/count:
    get:
      summary: Conteo público de signups
      operationId: getCount
      responses:
        '200':
          description: Conteo actual
          headers:
            Cache-Control:
              schema: { type: string }
              example: no-cache
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Count' }
              example: { count: 42 }
        '500':
          description: Falla al leer el log
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { error: count failed, code: COUNT_FAILED }
  /api/signup:
    post:
      summary: Registrar un interesado
      description: |
        Captura interés en GAMIA. Acepta JSON o form-urlencoded. Body capeado a 10 KB.
        Sin autenticación. CORS abierto (`Access-Control-Allow-Origin: *`).
        Toda respuesta de error tiene shape estable `{error, code, fields?, allowed?}`.
      operationId: createSignup
      externalDocs:
        description: Full request/response examples and error matrix
        url: https://gamia.cl/api/docs.md#post-apisignup
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/SignupRequest' }
            examples:
              minimal:
                summary: Solo campos requeridos
                value:
                  nombre: "Ada Lovelace"
                  email: "ada@example.com"
                  rol: "investigador"
              full:
                summary: Todos los campos
                value:
                  nombre: "Ada Lovelace"
                  email: "ada@example.com"
                  rol: "investigador"
                  organizacion: "Universidad de Chile"
                  aporte: "Modelado matemático para infraestructura compartida"
          application/x-www-form-urlencoded:
            schema: { $ref: '#/components/schemas/SignupRequest' }
            example: "nombre=Ada&email=ada@example.com&rol=investigador"
      responses:
        '200':
          description: Signup registrado
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Ok' }
              example: { ok: true }
        '400':
          description: Validación fallida o body malformado
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              examples:
                missing:
                  summary: Required fields missing
                  value:
                    error: "campos requeridos faltantes"
                    code: MISSING_FIELDS
                    fields: [email, rol]
                email:
                  summary: Invalid email format
                  value:
                    error: "email inválido"
                    code: INVALID_EMAIL
                    fields: [email]
                rol:
                  summary: Role not in allowed enum
                  value:
                    error: "rol inválido"
                    code: INVALID_ROLE
                    fields: [rol]
                    allowed: [founder, inversionista, investigador, empresa, gobierno, medios, otro]
                bad:
                  summary: Malformed body
                  value:
                    error: "bad request"
                    code: BAD_REQUEST
        '413':
          description: Payload demasiado grande (>10KB)
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example:
                error: "payload demasiado grande"
                code: PAYLOAD_TOO_LARGE
        '500':
          description: Falla al escribir el log
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
              example: { error: write failed, code: WRITE_FAILED }
components:
  schemas:
    Health:
      type: object
      required: [ok]
      properties:
        ok: { type: boolean, const: true }
    Count:
      type: object
      required: [count]
      properties:
        count: { type: integer, minimum: 0 }
    Ok:
      type: object
      required: [ok]
      properties:
        ok: { type: boolean, const: true }
    Error:
      type: object
      required: [error, code]
      properties:
        error:
          type: string
          description: Human-readable error message (Spanish).
        code:
          type: string
          description: Machine-readable error code (English, stable).
          enum:
            - MISSING_FIELDS
            - INVALID_EMAIL
            - INVALID_ROLE
            - PAYLOAD_TOO_LARGE
            - BAD_REQUEST
            - COUNT_FAILED
            - WRITE_FAILED
            - NOT_FOUND
        fields:
          type: array
          description: Names of fields that failed validation (present when applicable).
          items: { type: string }
        allowed:
          type: array
          description: List of accepted values (present when an enum was violated).
          items: { type: string }
    SignupRequest:
      type: object
      required: [nombre, email, rol]
      properties:
        nombre:
          type: string
          minLength: 1
          maxLength: 200
        email:
          type: string
          format: email
          maxLength: 200
        rol:
          type: string
          enum: [founder, inversionista, investigador, empresa, gobierno, medios, otro]
        organizacion:
          type: string
          maxLength: 300
        aporte:
          type: string
          maxLength: 2000
