openapi: 3.1.0
info:
  title: TURE Access API
  version: 0.1.0
  description: API inicial para dispositivos de control de acceso Hikvision.
servers:
  - url: https://api.ture.mx
security:
  - bearerAuth: []
paths:
  /v1/health:
    get:
      security: []
      responses:
        "200": { description: Servicio disponible }
  /v1/devices:
    get:
      responses:
        "200": { description: Dispositivos registrados }
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/DeviceInput" }
      responses:
        "201": { description: Dispositivo registrado }
  /v1/devices/{deviceId}/test:
    parameters:
      - $ref: "#/components/parameters/DeviceId"
    post:
      responses:
        "200": { description: Capacidades ISAPI obtenidas }
        "422": { description: Transporte incompatible }
  /v1/devices/{deviceId}/sync-events:
    parameters:
      - $ref: "#/components/parameters/DeviceId"
    post:
      responses:
        "202": { description: Sincronización encolada }
  /v1/people:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [employee_no, name]
              properties:
                employee_no: { type: string, maxLength: 64 }
                name: { type: string, maxLength: 160 }
                valid_from: { type: string, format: date-time }
                valid_until: { type: [string, "null"], format: date-time }
                metadata: { type: object }
      responses:
        "201": { description: Persona creada }
  /v1/people/{personId}/provision:
    parameters:
      - name: personId
        in: path
        required: true
        schema: { type: integer, minimum: 1 }
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [device_id]
              properties:
                device_id: { type: integer, minimum: 1 }
      responses:
        "202": { description: Provisionamiento encolado }
  /v1/credentials/qr:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [person_id, valid_until]
              properties:
                person_id: { type: integer, minimum: 1 }
                valid_until: { type: string, format: date-time }
      responses:
        "201": { description: Credencial y payload QR creados }
  /v1/gateway/heartbeat:
    post:
      security: [{ gatewayAuth: [] }]
      summary: Registra o renueva la presencia del gateway
      responses:
        "200": { description: Heartbeat aceptado }
  /v1/gateway/devices/register:
    post:
      security: [{ gatewayAuth: [] }]
      summary: Vincula un dispositivo ISUP conectado
      responses:
        "201": { description: Dispositivo vinculado }
  /v1/gateway/events:
    post:
      security: [{ gatewayAuth: [] }]
      summary: Recibe hasta 500 eventos idempotentes
      responses:
        "202": { description: Lote aceptado }
  /v1/gateway/jobs/claim:
    post:
      security: [{ gatewayAuth: [] }]
      summary: Arrienda comandos pendientes para dispositivos ISUP
      responses:
        "200": { description: Lista de comandos asignados }
  /v1/gateway/jobs/{jobId}/{result}:
    parameters:
      - name: jobId
        in: path
        required: true
        schema: { type: integer, minimum: 1 }
      - name: result
        in: path
        required: true
        schema: { type: string, enum: [complete, fail] }
    post:
      security: [{ gatewayAuth: [] }]
      summary: Confirma o rechaza un comando asignado
      responses:
        "200": { description: Resultado registrado }
        "409": { description: El job no pertenece a este gateway }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
    gatewayAuth:
      type: http
      scheme: bearer
      description: Token exclusivo del gateway ISUP
  parameters:
    DeviceId:
      name: deviceId
      in: path
      required: true
      schema: { type: integer, minimum: 1 }
  schemas:
    DeviceInput:
      type: object
      required: [name, transport, username, password]
      properties:
        name: { type: string, maxLength: 120 }
        vendor: { type: string, const: hikvision }
        model: { type: string, maxLength: 80 }
        serial_number: { type: string, maxLength: 120 }
        transport: { type: string, enum: [isapi, isup] }
        base_url: { type: [string, "null"], format: uri }
        username: { type: string }
        password: { type: string }
