Implementation Plan

Implementación

Plan de Implementación en fases:


Fase 1 — Keycloak (sin código, solo configuración)

1.1  Realm roles
     iris_admin · bioinformatician · employee
     org_member · patient · anon

1.2  Groups
     /iris-internal/
       bioinformatician          (all_orgs=false)
       bioinformatician-admin    (all_orgs=true)
       employee
     /orgs/{org_id}/
       admin
       clinician
       requester
       viewer
     /patients/                  (sin sub_role, solo role=patient)

1.3  Protocol Mappers (en el realm, heredados por todos los clients)
     group-membership   → claim "groups"
     user-attribute     → claim "org_id"    (del grupo)
     user-attribute     → claim "sub_role"  (del grupo)
     user-attribute     → claim "all_orgs"  (del grupo, boolean)
     realm-roles        → claim "role"      (el rol de Postgres)

1.4  Clients
     iris-api              resource server, bearer-only
     iris-genomics-cli     device_flow + client_credentials (service accounts ON)
     backapp-genomics      authorization_code + PKCE
     backapp-erm           authorization_code + PKCE
     crm                   authorization_code + PKCE

Fase 2 — Postgres + PostgREST

2.1  Roles de Postgres
     CREATE ROLE authenticator        (login, password, noinherit)
     CREATE ROLE anon
     CREATE ROLE iris_admin
     CREATE ROLE bioinformatician
     CREATE ROLE employee
     CREATE ROLE org_member
     CREATE ROLE patient
     GRANT anon, iris_admin, bioinformatician,
           employee, org_member, patient
     TO authenticator

2.2  postgrest.conf
     jwt-secret = "<keycloak-realm-public-key>"
     jwt-aud    = "iris-api"
     db-anon-role = "anon"

2.3  RLS policies base
     Una tabla de prueba con policies que lean
     current_setting('request.jwt.claims')
     para validar que el JWT de Keycloak llega bien

Fase 3 — iris.api (FastAPI)

3.1  Dependencias de validación
     python-jose o authlib
     JWKS endpoint de Keycloak (autodiscovery via /.well-known)

3.2  dependencies.py
     get_current_user()   — valida JWT, extrae claims
     require_role()       — decorator por rol
     require_org()        — valida org_id del token vs recurso

3.3  routers/auth.py
     GET  /auth/userinfo  — proxy a Keycloak userinfo
     POST /auth/token     — proxy a Keycloak token endpoint
                            (para que los clients no necesiten saber
                             la URL de Keycloak directamente)

3.4  routers/users.py
     CRUD de usuarios vía Keycloak Admin API
     asignación de grupos (= asignación de org y sub_role)

3.5  routers/genomics.py
     endpoints que usan iris.genomics como librería
     protegidos con require_role(bioinformatician)

Fase 4 — iris.genomics

4.1  use_cases/filter_variants.py
     función pura: VcfReader + VariantFilter → Iterator[VariantAnnotation]

4.2  use_cases/annotate_vcf.py
     función pura: variantes + [Annotator] → Iterator[VariantAnnotation]

4.3  commands/vcf.py
     CLI wrapper de filter_variants y annotate_vcf
     con Typer

4.4  cli.py
     entrypoint con auth: lee token de ~/.iris/credentials
     (guardado por device_flow o client_credentials)

Fase 5 — BACKAPPs y CRM

5.1  genomx — explorer + auth middleware Bottle
5.2  erm      — employees + orgs
5.3  crm              — org_portal + patients

¿Arrancamos con la Fase 1 — la configuración de Keycloak? Puedo guiarte paso a paso: primero los realm roles, luego la jerarquía de grupos con sus atributos, y finalmente los protocol mappers que son la parte más delicada porque de ellos depende que el JWT salga con los claims correctos para PostgREST.