Sistema ERP/CRM modular con backend Django + DRF y frontend Quasar. Incluye RBAC, auditoría contractual, HR, ORG, IAM y sincronización.
login_module/: backend Django/DRF (código enlogin_module/src/)frontend/: consola web (Vue 3 + Quasar)modulos/: módulos de dominio en la raíz del repo (ej:modulos.estacion_servicios)compose.yaml: entorno Docker (backend + Postgres)system_wis/: entorno virtual Python (dev)
- Índice: docs/README.md
- Operación (negocio): docs/operacion/README.md
- Auth cookie opcional via
AUTH_TOKEN_TRANSPORT+ CSRF en modo cookie. - 2FA admin con challenge one-time (anti-replay por IP/UA).
- Auditoria con firma HMAC por keyring (
AUDIT_HMAC_KEYS) ysignature_key_id. - Observabilidad basica:
request_id, Sentry opcional y endpoint/api/metrics/. - Paginacion en listados ORG/HR/RBAC (
limit/offset+count/limit/offset/results). - Nota QA: los overrides de throttling deben estar en
.env(el backend usaenv_fileen Docker Compose).
- Configura variables
Copy-Item .env.example .envcp .env.example .env- Levanta servicios
docker compose up -d --buildSi solo quieres backend + db (sin frontend):
docker compose up -d db backendEsto levanta por defecto:
- Frontend (Quasar): http://localhost:3000
- Backend (Django/DRF): http://localhost:8000
- DB (Postgres): localhost:5432
Nota: el contenedor backend corre migraciones automáticamente al iniciar (ver compose.yaml).
El stack PROD sirve el frontend compilado con Nginx en :80 y hace proxy de /api/ hacia el backend.
- Configura variables PROD
cp .env.prod.example .env- Levanta el stack PROD
docker compose -f compose.prod.yaml up -d --buildEndpoints:
- Web (SPA): http://localhost/
- API (proxy): http://localhost/api/
Herramientas opcionales (Adminer):
docker compose -f compose.prod.yaml --profile tools up -d adminerSi cambias dependencias Python (requirements/*.txt), reconstruye la imagen del backend:
docker compose build backend
docker compose up -d backenddocker compose down -v
docker compose up -dPara verificar el estado fresh:
curl http://localhost:8000/api/auth/bootstrap/status/En una instalación fresca normalmente quieres:
- Sembrar RBAC
docker compose exec backend python src/manage.py seed_rbac_v01- Crear usuario admin (si no existe)
docker compose exec backend python src/manage.py createsuperuser- Crear empresa/sucursal y grants iniciales (requiere que el usuario exista)
docker compose exec backend python src/manage.py bootstrap_company \
--company-name "Necktral" \
--branch-name "Principal" \
--admin-username "admin"source system_wis/bin/activate
pip install -r requirements/dev.txt
cd login_module
python src/manage.py migrate --noinput
python src/manage.py runservercd frontend
npm install
npm run devSi prefieres no instalar Node localmente, el compose.yaml incluye un servicio frontend.
docker compose up -d frontendLogs útiles:
docker compose logs -f backenddocker compose logs -f frontend
El repo incluye un runner determinista para CI/local (lint + typecheck + tests + verificación de integridad de auditoría) con reportes en qa/reports/.
-
Runner recomendado (DB limpia, reproducible):
make qa-ci-fresh
-
En CI (GitHub Actions):
make qa-ci-ci
-
Runner “normal” (usa la DB/volúmenes actuales; Gate 3 puede fallar si hay datos viejos inconsistentes):
make qa-ci
Artefactos generados:
qa/reports/static_scan.txtqa/reports/ruff.txtqa/reports/mypy.txtqa/reports/pytest.xmlqa/reports/coverage.xmlqa/reports/coverage.txtqa/reports/audit_integrity.json
-
Tests:
source system_wis/bin/activate cd login_module pytest
-
Tests (dentro de Docker):
docker compose exec backend pytest -q -
Lint (ruff):
source system_wis/bin/activate cd login_module ruff check .
- Lint:
cd frontend npm run lint - Tests (Vitest):
cd frontend npm run test
- Los eventos de auditoría se emiten con
module=AUTHyschema_version=1. - Trazabilidad: hashes encadenados + firma HMAC con keyring (
AUDIT_HMAC_KEYS) ysignature_key_id.
Base path: /api/fuel/
GET /api/fuel/health/— Healthcheck del módulo (público)POST /api/fuel/shifts/open/— Abrir turno (permiso:fuel.shift.open)POST /api/fuel/shifts/{shift_id}/close/— Cerrar turno (permiso:fuel.shift.close)POST /api/fuel/dispenses/— Registrar despacho (permiso:fuel.dispense.create)POST /api/fuel/sales/— Crear venta (permiso:fuel.sale.create)POST /api/fuel/sales/{sale_id}/cancel/— Cancelar venta (permiso:fuel.sale.void)
Ver CHANGELOG.md.
Bitácora de desarrollo (registro detallado y cronológico): ver BITACORA.md.
Para que un Product Manager (o un LLM) pueda ponerse al día sin leer todo el repo, se genera un snapshot en Markdown con:
- rama/commit actual,
- lista de ramas remotas (top 50),
- últimos commits,
- diff de PR cuando aplica.
- Workflow:
PM Snapshot - Artefacto:
pm-snapshot(archivopm_snapshot.md)
bash scripts/pm_snapshot.sh
cat pm_snapshot.md-
Todos los listados soportan
limit/offsety respondencount/limit/offset/results. -
GET /api/org/company/profile/— Ver perfil de la empresa (requiere permiso: org.company.read) -
PUT /api/org/company/profile/— Actualizar perfil de la empresa (requiere permiso: org.company.update) -
GET /api/org/companies/— Listar compañías accesibles por membresía (requiere permiso: org.company.read) -
POST /api/org/companies/— Crear compañía bajo el holding y clonar accesos del creador (requiere permiso: org.company.create) -
GET /api/org/branches/— Listar sucursales (requiere permiso: org.branch.read) -
POST /api/org/branches/— Crear sucursal (requiere permiso: org.branch.create) -
PATCH /api/org/branches/{branch_id}/— Actualizar sucursal (requiere permiso: org.branch.update)
-
Todos los listados soportan
limit/offsety respondencount/limit/offset/results. -
GET /api/hr/positions/— Listar puestos -
POST /api/hr/positions/— Crear puesto -
PATCH /api/hr/positions/<int:position_id>/— Actualizar puesto -
PUT /api/hr/positions/<int:position_id>/roles/— Mapear puesto a roles -
GET /api/hr/employees/— Listar empleados -
POST /api/hr/employees/— Crear empleado -
PATCH /api/hr/employees/<int:employee_id>/— Actualizar empleado -
POST /api/hr/employees/<int:employee_id>/assignments/— Asignar puesto/sucursal -
GET /api/hr/employees/<int:employee_id>/assignments/— Listar asignaciones del empleado (requiere permiso: hr.assignment.read) -
POST /api/hr/employees/<int:employee_id>/assignments/— Asignar puesto/sucursal -
POST /api/hr/employees/<int:employee_id>/assignments/<int:assignment_id>/end/— Finalizar asignación -
POST /api/hr/employees/<id>/provision-user/- Crea un usuario vinculado al empleado con contraseña provisional.
- Valida asignación activa y fuerza cambio de contraseña en primer login.
- Requiere permisos
iam.users.createyhr.employee.update.
-
POST /api/hr/employees/<id>/reset-temp-password/- Resetea la contraseña provisional del usuario ya vinculado al empleado.
- Payload opcional:
{ "temp_password": "..." }(si se omite, se autogenera). - Responde
409si no haylinked_usero si el empleado no tiene asignación activa. - Auditoría:
HR_EMPLOYEE_TEMP_PASSWORD_RESET(sin exponer la contraseña).
-
POST /api/hr/employees/<id>/revoke-access/- Revoca accesos del usuario vinculado al empleado en el scope de la company y sus sucursales.
- Desactiva
RoleAssignmentconorigin=POSITIONy cierra memberships (left_at) en scope. - Payload:
{ "disable_user": true|false }(opcional; si estrue, desactiva el usuario solo si no quedan memberships activas). - Responde
409si el empleado no tienelinked_user. - Auditoría:
HR_EMPLOYEE_ACCESS_REVOKED(sin incluir secretos).
GET /api/fuel/health/— Healthcheck del módulo (requiere sesión/auth)
Nota: el módulo FUEL está inicializado como “base” (scaffolding). El catálogo RBAC incluye roles/permisos fuel.* en seed_rbac_v01.
- Si tu base de datos ya tenía la columna
accounts_user.is_setup_completecomo NOT NULL, asegúrate de aplicar migraciones:docker compose exec backend python src/manage.py migrate --noinput.
python src/manage.py seed_rbac_v01— Siembra roles, permisos y mapeos estándar (idempotente, auditable)python src/manage.py bootstrap_company --company-name ... --branch-name ... --admin-username ...— Bootstrap de empresa, sucursal y admin- El comando es idempotente: si la empresa, sucursal o holding ya existen (por código o nombre), los reutiliza y reactiva si estaban desactivados.
- Si usas
--no-input, todos los parámetros son obligatorios y el comando falla si falta alguno. - AdminGrant siempre se crea con
org_unit=companyy se reactiva si estaba desactivado. - Membership y RoleAssignment también se reactivan si estaban off.
- Validado por el test:
tests/test_bootstrap_company_command.py.
En Docker, ejecuta estos comandos así:
docker compose exec backend python src/manage.py seed_rbac_v01
docker compose exec backend python src/manage.py bootstrap_company --company-name ... --branch-name ... --admin-username ...- Todos los endpoints de escritura generan eventos en apps.audit con reason_code y event_type según contrato.
- Ejemplo:
HR_POSITION_CREATED,ORG_BRANCH_CREATED,RBAC_SEEDED_V01. - El contrato de auditoría es estricto y validado por tests.
Guías de organización:
- Contract Pack v1.0: docs/CONTRACT_PACK_v1.0.md
- Addendum Offline-first v1.0: docs/ADDENDUM_OFFLINE_FIRST_v1.0.md
- Índice de docs: docs/README.md
tests/test_hr_position_role_automation.py: Valida automatización de roles por puesto y auditoría.tests/test_seed_rbac_v01_command.py: Valida comando seed_rbac_v01, creación de permisos y evento de auditoría.tests/test_bootstrap_company_command.py: Valida robustez, idempotencia y grants correctos del comando bootstrap_company.tests/test_org_endpoints_audit.py: Valida permisos RBAC por método en endpoints ORG y la trazabilidad/auditoría contractual de operaciones clave.tests/test_2fa_challenge.py: Valida challenge 2FA one-time y anti-replay.tests/test_pagination_list_endpoints.py: Valida paginación en listados ORG/HR/RBAC.
- Catálogo estándar en apps/rbac/seed_v01.py
- Roles: company_admin, branch_manager, hr_manager, etc.
- Permisos: hr.position.create, org.branch.create, etc.
- Siempre ejecutar los comandos de seed y bootstrap en entornos nuevos.
- Validar con tests antes de desplegar.
- Consultar la auditoría para trazabilidad de cambios críticos.
- La reconciliación de memberships ya no fuerza acceso a la empresa (COMPANY) por defecto.
- Solo se asignan memberships por asignaciones activas y roles mapeados.
- Mejora la robustez y evita accesos innecesarios.
- Nuevo permiso:
iam.users.createpara controlar el provisionamiento de usuarios desde HR.
Actualizado: 2026-02-09.

