paperless
Wiki interna

Paperless

Plataforma multi-tenant de digitalización y OCR de documentos.

Cada cliente (organización) opera aislado dentro de la misma base, el equipo interno de Paperless administra a todos, y el trabajo se organiza en Órdenes de Servicio (OS) con pasos y evidencia.

Stack: API y worker en Go (api/), SPA en React/TypeScript/Tailwind (web/), Postgres con RLS para el aislamiento por tenant, Keycloak para identidad/OIDC y S3 para los archivos. Corre en AWS (mx-central-1) por Docker Compose.

Secciones

  • Guía de uso — entrar (con MFA), dar de alta clientes y su admin, invitar equipo, subir documentos y operar una OS de principio a fin.
  • Documentación técnica — arquitectura, seguridad/multi-tenant, auth/MFA y deploy.
  • Integración & API — autenticación OIDC, tenant efectivo y endpoints.
Guía de uso

Guía de uso

Todo lo que necesitas para operar Paperless día a día, seas del equipo Paperless o administrador de un cliente.

Quién usa Paperless

Hay dos grandes grupos de usuarios: el equipo Paperless (staff, que administra a todos los clientes) y las organizaciones cliente (que ven solo su propia información). Tu rol define qué módulos ves y qué puedes hacer.

Equipo Paperless (staff)

RolQuién es
adminAdministración Paperless — acceso total; administra clientes, equipos y configuración.
coordinadorCoordinación de operaciones — gestiona órdenes, rutas y bodega.
atencion_clienteAtención a clientes — da de alta clientes y administra sus equipos.
operador_bodegaOperación de bodega — recepción, fotos y relocalización de cajas.
capturista_bdControl de inventario — captura y auditoría de inventario.
supervisorSupervisión — seguimiento y control de calidad.
auditor_externoAuditor externo — acceso de auditoría/lectura.

Organizaciones cliente

RolQuién es
cliente_adminAdministrador del cliente — administra su organización y su equipo, ve toda la información de su empresa.
cliente_usuarioUsuario — consulta y trabaja con los documentos y órdenes de su empresa.
partner_adminSocio coworking — administra su espacio y sus sub-clientes.

Entrar y configurar MFA

Paperless usa Paperless ID (Keycloak) para el acceso. Entra en app.78-12-50-254.sslip.io.

Primer acceso del equipo Paperless (staff)

El personal de Paperless entra siempre con segundo factor. La primera vez:

  1. Entra con tu correo y la contraseña temporal que te dieron.
  2. El sistema te pide fijar una contraseña nueva.
  3. Luego te pide configurar TOTP: escanea el código QR con una app autenticadora (Google Authenticator, Microsoft Authenticator, 1Password, etc.) y escribe el código de 6 dígitos para confirmar.
  4. Desde ahí, cada login pide tu contraseña y el código de 6 dígitos que muestra tu app.
Guarda el acceso a tu app autenticadora. Si cambias de teléfono sin migrarla, un administrador tendrá que reiniciar tu TOTP para que vuelvas a configurarlo.

Primer acceso de un cliente

Los usuarios de un cliente (cliente_admin, cliente_usuario) solo fijan su contraseña en el primer login; no se les pide MFA.

Cambiar de organización (staff)

El equipo Paperless puede trabajar en nombre de una organización cliente. Usa el selector “Actuar como organización” en la parte superior: al elegir un cliente, todo lo que hagas (crear órdenes, invitar equipo, ver documentos) aplica a esa organización.

Mientras actúas como una organización, los cambios quedan registrados a tu nombre pero dentro de la empresa seleccionada. Cambia de regreso a Paperless cuando termines.

Dar de alta un cliente y su administrador

Solo el equipo Paperless (roles admin, coordinador, atencion_cliente) puede crear organizaciones cliente.

Cliente nuevo

  1. Ve a Clientes → “Nueva organización”.
  2. Captura el nombre de la empresa y los datos de su primer administrador (nombre y correo). Se crea la organización y su cliente_admin en un solo paso.
  3. El administrador del cliente recibe acceso y fija su contraseña en el primer login.

Darle un administrador a un cliente existente

  1. Usa “Actuar como organización” y elige el cliente.
  2. Ve a Equipo → Invitar e invita a la persona con el rol Administrador (cliente_admin).

Administrar tu equipo

Los administradores (cliente_admin / partner_admin, y el staff actuando como la organización) administran a los miembros desde Equipo.

  • Invitar: Equipo → Invitar; captura nombre, correo y rol.
  • Cambiar el rol de un miembro (por ejemplo, de Usuario a Administrador).
  • Desactivar a quien ya no debe tener acceso — deja de poder entrar sin borrar su historial.

Subir y encontrar documentos

Subir

  1. Entra a Documentos (si eres staff, primero “Actuar como organización” del cliente correcto).
  2. Arrastra o selecciona los archivos. Quedan asociados a la organización activa.
  3. El OCR se procesa en segundo plano; cuando termina, el texto es buscable.

Buscar y abrir

  • Usa el Buscador para encontrar documentos por nombre o por su contenido (gracias al OCR).
  • Abre un documento para verlo; usa Descargar para obtener el archivo original.
Cada quien ve solo los documentos de su propia organización. El aislamiento es a nivel de base de datos: nadie puede ver los documentos de otro cliente.

Órdenes de Servicio de principio a fin

El trabajo operativo se organiza en Órdenes de Servicio (OS). Cada servicio tiene su propia secuencia de pasos, y cada paso guarda su evidencia.

  1. Crear la OS: en Servicios, crea una nueva orden eligiendo el tipo de servicio y el cliente.
  2. Paso 1 — Validar: valida la solicitud y la autorización. Aquí puedes subir el archivo de formato (.pdf / .png / .jpg) con el botón de formato; queda adjunto a la orden como evidencia.
  3. Pasos siguientes: avanza por el flujo del servicio. Cada paso puede pedir evidencia (notas, fotos, condiciones) que queda registrada.
  4. Timeline: en la orden ves la línea de tiempo con cada paso y su evidencia. El formato aparece como “📎 Abrir formato” para descargarlo.

Acciones sobre una orden

  • Reabrir un paso si hay que corregir algo ya registrado.
  • Registrar una excepción cuando algo no sale según lo esperado, y luego resolverla.
  • Autorizar, cancelar o cobrar la orden según el flujo y tu rol.

Preguntas frecuentes

Me dice “mfa required” aunque ya configuré el MFA

Cierra la sesión y vuelve a entrar en una ventana limpia (o incógnito), escribiendo contraseña y el código de 6 dígitos. Si persiste, avisa al equipo técnico: es un problema de configuración del lado del servidor, no tuyo.

Olvidé mi contraseña

Las contraseñas las administra Paperless ID. Pide a un administrador que te genere una contraseña temporal; la cambiarás al entrar.

No veo un módulo que otra persona sí ve

Los módulos dependen de tu rol. Si necesitas acceso a algo, pídele a tu administrador que revise tu rol.

Soy staff y no puedo “actuar como” un cliente

Actuar como organización requiere tener el segundo factor (MFA) activo y un rol de staff con permiso. Verifica que entraste con tu código de 6 dígitos.

Documentación técnica

Documentación técnica

Arquitectura, seguridad, autenticación y deploy.

Arquitectura

Cómo encajan las piezas SPA React (web/) API Go (serve) auth, handlers, s.can() Keycloak (OIDC) identidad, MFA, amr Postgres (RLS) org_id por tenant S3 (archivos) Worker Go OCR asíncrono
Arquitectura · SPA → API → Postgres / Keycloak / S3 / worker.

La SPA habla solo con la API; la API valida la sesión OIDC de Keycloak, aplica permisos server-side (s.can()) y accede a los datos del tenant siempre a través de db.Scoped sobre Postgres con RLS. Los archivos viven en S3; el worker procesa el OCR de forma asíncrona.

Comandos de la app (api/cmd/api): serve (HTTP), worker (OCR), migrate (esquema + roles), idp-setup (configura MFA/amr en Keycloak), bootstrap-admin (siembra el primer admin). seed es solo local.

Seguridad y multi-tenant

El aislamiento por tenant va antes que las features. Reglas no negociables:

  • Toda tabla con datos de tenant lleva org_id + RLS ENABLE + FORCE + una política tenant sobre current_org(). TestEveryTenantTableHasRLS falla si no.
  • Los datos de tenant se acceden solo por db.Scoped (s.tx(r, ...)): el tenant viene de la sesión, nunca del body o query.
  • Las FK ignoran RLS: antes de enlazar un id foráneo (box, documento, orden, usuario) hay que verificar que existe dentro del tenant.
  • Las lecturas cross-tenant de staff van solo por db.StaffDirectory, que nunca expone documentos.
  • Cada acción que cambia estado escribe audit(r, tx, ...) en la misma transacción.
  • Permisos server-side con s.can("<perm>"); la UI solo los refleja.
  • Validar toda entrada en el borde (longitudes, enums, UUID con validUUID); decode rechaza campos desconocidos.
  • Proveedores externos tras un adapter con fake marcado. Los secretos solo por env, nunca commiteados.

Autenticación y MFA

Keycloak 26.1 (realm paperless) maneja identidad por OIDC. Dos clientes: paperless-web (login, confidential, standard flow) y paperless-admin (service account que usa la API para administrar usuarios).

  • Login: la SPA redirige a Keycloak; la API lee el ID token en el callback (auth.go) y abre la sesión.
  • MFA de staff: REQUIRE_STAFF_MFA=true. Todo usuario del grupo staff debe configurar TOTP en su primer login.
  • El claim amr: la API lee amr del ID token; si trae otp/mfa/hwk/swk, la sesión cuenta con segundo factor.
  • Para que amr llegue al token hacen falta DOS cosas, ambas configuradas por idp-setup (idempotente): (1) las authenticator reference configs pwd/otp en el flow paperless-browser, y (2) el protocol mapper oidc-amr-mapper en el cliente paperless-web.
Sin el oidc-amr-mapper, amr sale vacío y todo login de staff se rechaza como “mfa required” aunque el TOTP esté bien. Fue la causa raíz del bug de login en el box (oct 2026); idp-setup ahora crea el mapper automáticamente.

Modelo de onboarding

  • organizations: is_internal (bool) + kind enum (client/partner/internal) sincronizado por el trigger org_kind_sync.
  • memberships: UNIQUE (identity_uid, org_id); identity_uid = sub de Keycloak; active default true.
  • Alta de cliente: POST /api/admin/orgs crea la org cliente + su primer cliente_admin.
  • Invitar equipo: POST /api/team contra la org actual; staff usa el header X-Act-As-Org.
  • Primer admin: el comando bootstrap-admin siembra la org interna Paperless + el primer staff admin.

Flujo de Órdenes de Servicio (modelo)

  • Cada servicio define una secuencia de pasos; el Paso 1 siempre es validar (lane atencion).
  • La evidencia de cada paso se guarda como JSON en os_events.evidence.
  • El Paso 1 acepta subir un archivo de formato opcional: formato_doc_id apunta a un documento ya existente (se valida contra documents, no borrado).

Deploy en AWS

Corre en AWS (mx-central-1): box EC2 (ubuntu@78.12.50.254, llave deploy/aws/paperless.pem), RDS Postgres, S3, todo por Docker Compose.

Deploy (hoy manual) — el runner self-hosted de GitHub Actions aún no está instalado:

  1. rsync del working tree al box (excluir .env, .pem, ._*).
  2. En ~/paperless/deploy/aws: sudo docker compose build app && docker compose run --rm migrate && docker compose up -d.

Wiki (docs): sitio estático en deploy/aws/docs/ servido por Caddy (DOCS_HOST); deploy = rsync de docs/ + docker compose up -d caddy.

Primera puesta en marcha: deploy/aws/box-setup.sh hace swap, .env, realm + clientes de Keycloak por kcadm, grupo staff, migrate, idp-setup y up.

Cutover DNS (pendiente): apuntar paperless.com.mx (2 A records → 78.12.50.254), editar los hosts en .env, reiniciar caddy + app y actualizar el redirect URI en Keycloak.

Operación

URLs vivas:

Contraseñas: nunca pasan por la app; Keycloak es dueño de las credenciales. Se fija una temporal con kcadm en el box:

kcadm.sh set-password -r paperless --username <email> --new-password '<temp>' --temporary

Cuentas sembradas (2026-10-21):

UsuarioRolOrganizaciónMFA
developer1@paperless.com.mxadmin (staff)Paperless (interna)TOTP obligatorio
demo-cliente@paperless.com.mxcliente_adminCliente DemoNo

Pendientes

  • Instalar el runner self-hosted de GitHub Actions para self-deploy (hoy el deploy es manual).
  • Cutover de DNS a paperless.com.mx cuando haya acceso al DNS.
  • Resto del backlog de WhatsApp (oct 20) — mayormente sin empezar.
Integración

Integración & API

Cómo se habla con la API de Paperless.

Autenticación

  • La API se consume desde la SPA con la sesión OIDC de Keycloak (cookie de sesión), no con tokens armados a mano. El flujo de login es el estándar de paperless-web.
  • Server-to-server: el service account paperless-admin (client credentials) — hoy lo usa la propia API contra el Admin REST de Keycloak.

El tenant efectivo (actuar como organización)

El tenant siempre sale de la sesión, nunca del body. El staff puede actuar sobre una org cliente de dos formas (ambas requieren MFA y son solo para staff):

  • POST /api/session/org {"org_id": "..."} — fija la org activa en la sesión (el selector “Actuar como organización”).
  • Header X-Act-As-Org: <org_id> — fija la org por request. Un cliente que lo mande recibe 403.

Endpoints principales

Método y rutaQué hace
GET /api/me, GET /api/me/orgsIdentidad y organizaciones del usuario
POST /api/session/orgActuar como una organización (staff)
POST /api/admin/orgsCrea org cliente + su primer cliente_admin
GET / POST / PATCH /api/teamLista, invita y edita miembros de la org actual
GET / POST /api/documentsLista y sube documentos (multipart, campo files)
POST /api/documents/{id}/downloadDevuelve una URL firmada de descarga
GET / POST /api/osLista y crea Órdenes de Servicio
POST /api/os/{id}/steps/{key}Avanza un paso de la OS con su evidencia

Subir archivos por cliente

  1. Entra como el cliente_admin de esa org, o (staff) usa “Actuar como organización”.
  2. Sube por Documentos, o directo a POST /api/documents (multipart, campo files).
  3. En el Paso 1 de una OS, el archivo de formato viaja como formato_doc_id (el id de un documento ya subido) en POST /api/os/{id}/steps/{key}.

Pendiente

  • Webhooks / API pública con tokens propios: aún no definido.