Fizzy API y bridge FastAPI: dos formas de crear tarjetas en el kanban

fra fra · 4 min

kanban.d4r.es está protegido por el outpost de Authentik en Traefik, lo que complica cualquier automatización que intente hablar con Fizzy directamente por HTTP. Este post documenta las dos vías que funcionan en el stack D4R y presenta el bridge FastAPI que resuelve el problema de fondo.

El problema: Authentik intercepta todo

Fizzy expone una API JSON interna y acepta tokens Bearer, pero el middleware authentik@docker de Traefik intercepta cada petición a kanban.d4r.es antes de que llegue al contenedor de Rails. Si la petición no trae una sesión OIDC válida, el proxy devuelve un 302 al flujo OAuth de Authentik, independientemente del token que incluyas.

El resultado práctico: un curl con Authorization: Bearer <token> contra kanban.d4r.es recibe HTML de redirección, no JSON.

Vía 1: rails runner dentro del contenedor

La vía más robusta para automatizaciones internas es ejecutar código Ruby directamente dentro de app-fizzy-1 vía docker exec. No depende de HTTP, ni de tokens, ni de Authentik.

El patrón básico para crear una tarjeta:

docker exec app-fizzy-1 sh -lc 'cd /rails && bin/rails runner "
Current.user = User.find(%q{USER_ID})
board  = Board.find(%q{BOARD_ID})
column = board.columns.find(%q{COLUMN_ID})

card = board.cards.create!(
  title:          %q{Título de la tarjeta},
  creator_id:     %q{USER_ID},
  status:         %q{published},
  column:         column,
  last_active_at: Time.current
)
puts %Q(#{card.number} | #{card.title})
"'

Un detalle importante: el modelo Card tiene belongs_to :creator, default: -> { Current.user }. En el contexto de rails runner no hay usuario de sesión, así que hay que fijar Current.user explícitamente antes de crear la tarjeta, o pasar creator_id: de forma directa. Sin ese paso la validación Creator must exist bloquea la creación.

Estado DONE: closures

Fizzy no usa un campo status=done en la tarjeta. Las tarjetas cerradas tienen un registro en la tabla closures. El modelo expone el método card.close que crea ese registro usando Current.user como responsable del cierre.

Estado MAYBE: sin columna

Las tarjetas en la columna MAYBE? del board son simplemente tarjetas publicadas con column_id = NULL. No existe una columna «MAYBE» en la base de datos; es el estado por defecto de una tarjeta publicada sin columna asignada.

Vía 2: bridge FastAPI en el portal

Para que el resto del stack (n8n, scripts externos, el propio portal) pueda crear tarjetas sin conocer los detalles de rails runner ni tener acceso SSH al servidor, el portal en d4r.es expone dos endpoints propios que actúan como bridge:

EndpointFunción
GET /api/kanban/projectDevuelve boards y columnas disponibles
POST /api/kanban/cardsCrea una tarjeta en el board y columna indicados

Ambos endpoints viven dentro del perímetro autenticado del portal y hablan con Fizzy internamente vía rails runner, sin pasar por el outpost de Authentik.

GET /api/kanban/project

Devuelve la estructura del proyecto Fizzy: boards y sus columnas.

{
  "boards": [
    {
      "id": "03g30vmfynlu0z5sug5339p6x",
      "name": "D4R",
      "account_id": "03g30vkv0lv4glmwklmzjokp1",
      "columns": [
        {
          "id": "03g329cj705u8zkzvpnb25ktn",
          "name": "DOING",
          "position": 1
        }
      ]
    }
  ]
}

POST /api/kanban/cards

Crea una tarjeta. Acepta board_id/column_id explícitos o los nombres como atajos:

{
  "title": "Nueva tarjeta desde n8n",
  "description": "Creada automáticamente",
  "board_name": "D4R",
  "column_name": "DOING"
}

Si no se especifica columna, la tarjeta cae en MAYBE? (sin columna). La respuesta devuelve el ID de Fizzy, el número de tarjeta y la URL directa.

Modelo de datos relevante

Fizzy usa SQLite. Las tablas más útiles para automatizaciones:

TablaUso
boardsEspacios de trabajo (tableros)
columnsColumnas de cada tablero
cardsTarjetas; column_id NULL = MAYBE?
closuresRegistro de tarjetas cerradas (DONE)
card_not_nowsTarjetas en estado NOT NOW

Scripts en el repo

El repo incluye dos scripts bash en scripts/fizzy/ que encapsulan estos patrones:

  • scripts/fizzy/create_card.sh — crea una tarjeta individual con flags --title, --column, --done
  • scripts/fizzy/import_cards.sh — importa tarjetas desde un CSV con columnas title,column,done,description

Ambos usan SSH + docker exec internamente y no dependen del token HTTP de Fizzy ni de sesiones OIDC.

fra fra

Editor en D4R.