{"openapi":"3.1.0","info":{"title":"gampify API","version":"0.1.0","description":"API REST para generar y gestionar paquetes de validación GAMP 5. Diseñada para que agentes LLM (opencode, Claude, ChatGPT) se integren en minutos: crear proyectos, generar docs, gestionar evidencia, preparar el handoff al QA humano para la firma (la firma NO la hace el agente — es humana por diseño regulatorio: 21 CFR Part 11 §11.200(a) + GAMP 5 v2 §6.2.3 (Quality Unit — independence)).","contact":{"name":"gampify","url":"https://gampify.org"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://gampify.org","description":"Producción (canonical)"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"opaque | gampify_<48hex>","description":"Dos tipos de Bearer token son aceptados:\n  • session token (humano, navegador) — opaco hex de 64, TTL 7 días\n  • API key (máquina, agente LLM) — formato `gampify_` + 48 hex chars\nAmbos heredan los permisos RBAC del usuario que los emitió. La firma de documentos requiere TOTP (2FA) **además** del token — ninguna API key puede firmar por sí sola."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string"}}},"AnswersInput":{"type":"object","description":"Respuestas del wizard que describen el sistema a validar. Estructura libre (los campos exactos varían por industria); todas las secciones top-level son opcionales y se completan en cualquier orden. Para referencia, ver /api/starters/:key (devuelve el shape completo por industria).","properties":{"proyecto":{"type":"object","description":"Datos del proyecto/sistema a validar.","additionalProperties":true,"example":{"empresa":"Laboratorios X","sistema":"LIMS interno","descripcion":"Sistema de gestión de muestras de laboratorio.","version_sistema":"1.0","categoria_gamp":"Cat 4+5","pais":"Argentina","regulador":"ANMAT"}},"equipo":{"type":"object","description":"Roles del equipo (implementador + QA como mínimo).","additionalProperties":true},"regulatorio":{"type":"object","description":"Marco regulatorio aplicable (ANMAT, FDA, EMA, etc.).","additionalProperties":true},"tecnico":{"type":"object","description":"Stack técnico (lenguaje, framework, DB, hosting).","additionalProperties":true},"proveedores":{"type":"object","description":"Proveedores clave (Cloud, DB, librerías críticas).","additionalProperties":true},"procesos":{"type":"object","description":"Procesos de negocio que el sistema soporta.","additionalProperties":true},"riesgos":{"type":"object","description":"Análisis de riesgos (FMEA, HACCP, o lista libre).","additionalProperties":true},"docs_existentes":{"type":"object","description":"Documentación previa (URS, SOP, manuales).","additionalProperties":true},"comercial":{"type":"object","description":"Datos comerciales (clientes objetivo, mercado).","additionalProperties":true}}},"Project":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","active","archived","completed"]},"wizard_answers":{"$ref":"#/components/schemas/AnswersInput"},"created_at":{"type":"string","format":"date-time"}},"required":["id","name","status"]},"Doc":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"project_id":{"type":"string","format":"uuid"},"template_type":{"type":"string","example":"URS","description":"Tipo de documento (URS, FS, DS, IQ, OQ, PQ, …)."},"version":{"type":"integer"},"status":{"type":"string","enum":["draft","in_review","approved","signed","superseded"]},"signed_at":{"type":"string","format":"date-time","nullable":true},"signed_by":{"type":"string","nullable":true}},"required":["id","project_id","template_type","version","status"]},"Evidence":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"doc_id":{"type":"string","format":"uuid"},"step_number":{"type":"integer"},"result":{"type":"string","enum":["pass","fail","na"]},"note":{"type":"string","nullable":true},"screenshot_url":{"type":"string","nullable":true},"recorded_by":{"type":"string"},"recorded_at":{"type":"string","format":"date-time"}},"required":["id","doc_id","step_number","result","recorded_by"]},"AuditLink":{"type":"object","properties":{"token":{"type":"string","description":"Token opaco (URL completa: /audit/<token>)"},"expires_at":{"type":"string","format":"date-time"},"url":{"type":"string","example":"https://gampify.org/audit/<token>"}}}}},"paths":{"/api/health":{"get":{"summary":"Health check del Worker.","tags":["public"],"responses":{"200":{"description":"Status del worker.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"db":{"type":"boolean"},"ai":{"type":"boolean"},"templates":{"type":"integer"},"ts":{"type":"string","format":"date-time"}}}}}}}}},"/api/auth/register":{"post":{"summary":"Registrar un usuario nuevo.","tags":["auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email","password","role"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8},"role":{"type":"string","enum":["implementer","qa","management","viewer"]}}}}}},"responses":{"200":{"description":"Usuario registrado. Devuelve session token."},"409":{"description":"Email ya registrado."},"429":{"description":"Rate limit (5 min)."}}}},"/api/auth/login":{"post":{"summary":"Login → session token (TTL 7 días).","tags":["auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"Devuelve { token, user }.","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"user":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Credenciales inválidas."}}}},"/api/auth/api-keys":{"post":{"summary":"Crear una API key de máquina (formato gampify_<48hex>).","tags":["auth"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Etiqueta humana (ej. \"agente-prod\")"}}}}}},"responses":{"200":{"description":"Devuelve { key, id, prefix, name, created_at }. El campo `key` se muestra UNA sola vez — guardalo."},"401":{"description":"No autenticado."}}},"get":{"summary":"Listar API keys del usuario (sin raw ni hash).","tags":["auth"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Lista de keys (metadata solamente)."}}}},"/api/starters":{"get":{"summary":"Lista de starters por industria (resumen).","tags":["public"],"responses":{"200":{"description":"Mapa {industria: {industria, descripcion}}."}}}},"/api/starters/{key}":{"get":{"summary":"Starter completo por industria (estructura del wizard answers).","tags":["public"],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","enum":["lab-farma","dispositivos-medicos","biotech"]}}],"responses":{"200":{"description":"Starter shape (AnswersInput de referencia)."},"404":{"description":"Starter no encontrado."}}}},"/api/preview":{"post":{"summary":"Preview del paquete de docs sin crear el proyecto.","tags":["projects"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["answers"],"properties":{"answers":{"$ref":"#/components/schemas/AnswersInput"}}}}}},"responses":{"200":{"description":"Estimación (gaps, compliance score, docs propuestos)."}}}},"/api/projects":{"post":{"summary":"Crear un proyecto (genera 39 docs GAMP 5).","tags":["projects"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","answers"],"properties":{"name":{"type":"string"},"answers":{"$ref":"#/components/schemas/AnswersInput"}}}}}},"responses":{"200":{"description":"Proyecto creado.","content":{"application/json":{"schema":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/Project"}}}}}}}},"get":{"summary":"Lista de proyectos accesibles por el usuario.","tags":["projects"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Array de Project (resumen)."}}}},"/api/projects/{id}":{"get":{"summary":"Detalle del proyecto (incluye wizard_answers, status, summary).","tags":["projects"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project completo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"403":{"description":"Sin acceso (RBAC: implementer solo ve lo propio, QA solo asignado)."},"404":{"description":"Proyecto no encontrado."}}}},"/api/projects/{id}/docs/{type}":{"get":{"summary":"Obtener la versión actual de un doc.","tags":["docs"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"type","in":"path","required":true,"schema":{"type":"string","example":"URS"}}],"responses":{"200":{"description":"Doc + contenido markdown."},"404":{"description":"Doc no encontrado."}}},"put":{"summary":"Editar un doc (crea nueva versión, audit trail automático).","tags":["docs"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"type","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content_md","change_reason"],"properties":{"content_md":{"type":"string"},"change_reason":{"type":"string","description":"Por qué se edita (queda en audit trail)."}}}}}},"responses":{"200":{"description":"Nueva versión creada."}}}},"/api/projects/{id}/docs/{type}/sign":{"post":{"summary":"Firmar un doc (HUMAN-ONLY — requiere TOTP activo).","tags":["docs"],"description":"⚠️ Esta firma es HUMANA por diseño regulatorio. Aunque uses una API key válida, el backend exige TOTP (2FA) en cada llamada. Una API key de un usuario QA sin TOTP configurado recibe 403. Esto cumple 21 CFR Part 11 §11.200(a) (identificación electrónica: persona, no credencial) y GAMP 5 §6.2.3 (Quality Unit — independence). Para preparar el handoff: usar /api/projects/:id/audit-link.","security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"type","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["signing_totp","signing_meaning"],"properties":{"signing_totp":{"type":"string","minLength":6,"maxLength":6,"description":"Código TOTP actual del QA."},"signing_meaning":{"type":"string","enum":["approved","reviewed","released","authored","approved-with-observations","rejected"],"description":"Significado legal del sign (21 CFR Part 11 §11.50 manifestation)."}}}}}},"responses":{"200":{"description":"Doc firmado (Ed25519 + TSA + R2 WORM)."},"403":{"description":"TOTP inválido o 2FA no activo (aunque tengas API key válida)."}}}},"/api/projects/{id}/audit-link":{"post":{"summary":"Generar audit-link (URL read-only del paquete, expira 30d).","tags":["audit"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Devuelve { token, expires_at, url }.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLink"}}}}}}},"/api/projects/{id}/self-test":{"post":{"summary":"Correr self-test del sistema (URL probe + repo check).","tags":["projects"],"security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"public_url":{"type":"string","format":"uri"},"repo_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Checks ejecutados (pass/fail/na + nota)."}}}}},"tags":[{"name":"public","description":"Sin auth."},{"name":"auth","description":"Registro, login, API keys."},{"name":"projects","description":"CRUD de proyectos de validación."},{"name":"docs","description":"Documentos GAMP 5 (URS, FS, DS, IQ, OQ, PQ, …)."},{"name":"audit","description":"Audit-trail y handoff a QA."}]}