Proyecto backend-first · API REST con Django

Flujos con dependencias, permisos explícitos y transiciones de estado auditables.

QuestBoard es una API backend con Python y Django para trabajo colaborativo con dependencias y revisión. A diferencia de un CRUD básico de tareas, controla qué trabajo puede comenzar, quién puede aprobarlo y mantiene los cambios relevantes de forma coherente y auditable.

  • Python
  • Django
  • Django REST Framework
  • PostgreSQL
  • Docker
  • Gunicorn

El proyecto se concentra en reglas backend que los endpoints habituales de creación, actualización y borrado no expresan bien: elegibilidad del flujo, autoridad dentro del proyecto, integridad de dependencias, separación de la revisión e historial de auditoría duradero.

Los cambios de estado utilizan una operación de transición dedicada en lugar de un PATCH sin restricciones. Cada transición legal aplica sus propios permisos y precondiciones, incluido un retorno controlado desde REVIEW a IN_PROGRESS.

  1. BACKLOG
  2. READY
  3. IN_PROGRESS
  4. REVIEW
  5. DONE

Las dependencias forman un grafo validado dentro de cada proyecto. Las operaciones de planificación rechazan aristas inválidas antes de insertarlas y las restricciones PostgreSQL refuerzan las relaciones duplicadas o autorreferenciales. Los prerrequisitos determinan directamente si una quest puede pasar de BACKLOG a READY.

  • Self-dependencies are rejected
  • Dependencies must remain within one project
  • Duplicate edges and cycles are rejected
  • Every prerequisite must be DONE before READY

La autorización se evalúa según la membresía del proyecto, el rol, la asignación y el estado del flujo. La autoridad de OWNER y REVIEWER se separa de la ejecución de CONTRIBUTOR, y una persona asignada no puede aprobar su propio trabajo.

Roles del proyecto

  • OWNER
  • REVIEWER
  • CONTRIBUTOR

Invariantes de negocio protegidas

  • Assignees must belong to the project
  • Assignment is frozen from IN_PROGRESS
  • Self-approval is forbidden
  • DONE is terminal
  • Protected deletion preserves valid relationships
  • Every project retains at least one OWNER

QuestEvent persiste las mutaciones relevantes de creación, asignación, dependencias y estado con actor, fecha y contexto estructurado. quest_id_snapshot conserva el identificador histórico tras el borrado legal de una quest.

Las mutaciones de dominio utilizan transaction.atomic. Las filas Quest se bloquean para cambios de estado concurrentes, mientras que los bloqueos select_for_update a nivel de proyecto serializan las escrituras del grafo y los cambios de membresía cuyas invariantes abarcan varias filas.

  1. transaction.atomic
  2. Fila Quest · select_for_update
  3. Fila Project · grafo e invariantes de OWNER

Un fallo específico de PostgreSQL reveló una forma inválida de SELECT FOR UPDATE a través de la relación nullable con assignee. La solución mantuvo el bloqueo: transition_quest bloquea únicamente la fila Quest y resuelve la relación nullable por separado, conservando el límite transaccional y las invariantes del flujo.

GitHub Actions ejecuta el backend sobre PostgreSQL 17 y valida calidad de código, migraciones, configuración de Django, contrato OpenAPI, tests de dominio/API y construcción de la imagen Docker. El mismo runtime Docker se despliega con Gunicorn en Render y PostgreSQL gestionado.

  • PostgreSQL 17
  • Ruff lint and format
  • Migration drift
  • Django system checks
  • OpenAPI validation
  • Backend/API tests
  • Docker image build