Plataforma técnica · Arquitectura
Diagramas del Sistema
Arquitectura Diagramas
Esta página contiene los diagramas técnicos del ecosistema Nostromo: flujos de datos, capas, autenticación, multi-tenancy y despliegue. Las explicaciones narrativas viven en Arquitectura del Sistema y Arquitectura Hexagonal.
Ecosistema Contable (Overview)
Section titled “Ecosistema Contable (Overview)”Flujo completo de datos desde servicios externos hasta la UI:
flowchart LR
%% External Services
subgraph External["Servicios Externos"]
SII["SII"]
PREVIRED["Previred"]
BC["Banco Central"]
end
%% Loaders Layer
subgraph Loaders["Nostromo · Python ETL"]
BCL["bc_loader.py"]
I2C["impuesto_2cat_loader.py"]
PRL["previred_loader.py"]
SIIL["sii_loader.py"]
RCS["run_cargas_sii.py"]
end
%% Database Layer
subgraph DB["Mother · PostgreSQL 16"]
direction TB
subgraph Parametros["nostromo_common · parametros"]
direction TB
PAR_MON["monedas"]
PAR_IND["indicadores"]
PAR_TAX["impuesto_2cat"]
PAR_AFP["afp · afc"]
end
subgraph Operaciones["tenant · operaciones_sii"]
OP_COM["compras"]
OP_VEN["ventas"]
OP_DET["compras_ventas_detalle"]
end
subgraph Remuneraciones["tenant · remuneraciones"]
REM_EMP["empleados"]
REM_CON["contratos"]
REM_LIQ["liquidaciones"]
REM_HON["honorarios"]
end
SP_DET(["sp_generar_compras_ventas_detalle"])
end
%% Orchestrator + Sevastopol
subgraph Backend["Orchestrator · Node + TS"]
PAYENG["PayrollEngine.calculate()"]
SVCS["Services / Repositories"]
end
subgraph Frontend["Sevastopol · Astro + SolidJS"]
VIEWS["Islands UI"]
API["authenticatedFetch"]
end
%% Connections
BC -->|API| BCL
BCL -->|Upsert| PAR_MON
PREVIRED -->|JSON| PRL
PRL -->|Upsert| PAR_IND
PRL -->|Upsert| PAR_AFP
SII -->|Scraping| I2C
I2C -->|Upsert| PAR_TAX
SII -->|Playwright| SIIL
SIIL --> RCS
RCS -->|Insert| OP_COM
RCS -->|Insert| OP_VEN
OP_COM -->|Trigger| SP_DET
OP_VEN -->|Trigger| SP_DET
SP_DET -->|Gen| OP_DET
VIEWS -->|HTTPS + cookie sid| API
API -->|REST JSON| SVCS
SVCS -->|Pool| REM_EMP
SVCS -->|Pool| REM_CON
SVCS -->|Pool| PAR_IND
SVCS --> PAYENG
PAYENG -->|PayrollResult| SVCS
SVCS -->|Insert| REM_LIQ
classDef ext fill:#2d2d2d,stroke:#d3095f,stroke-width:2px,color:#fff;
classDef py fill:#0d1117,stroke:#e3b341,stroke-width:2px,color:#fff;
classDef db fill:#0d1117,stroke:#2b95d6,stroke-width:2px,color:#fff;
classDef sp fill:#1f1235,stroke:#8e44ad,stroke-width:2px,stroke-dasharray: 5 5,color:#fff;
classDef back fill:#0d1117,stroke:#27ae60,stroke-width:2px,color:#fff;
classDef front fill:#0d1117,stroke:#16a085,stroke-width:2px,color:#fff;
class SII,PREVIRED,BC ext;
class BCL,I2C,PRL,SIIL,RCS py;
class PAR_MON,PAR_IND,PAR_TAX,PAR_AFP,OP_COM,OP_VEN,OP_DET,REM_EMP,REM_CON,REM_LIQ,REM_HON db;
class SP_DET sp;
class PAYENG,SVCS back;
class VIEWS,API front; Leyenda de Colores
Section titled “Leyenda de Colores”| Color | Componente | Descripción |
|---|---|---|
| Magenta | Externo | Servicios fuera de la red (SII, Previred, Banco Central). |
| Amarillo | Python ETL | Loaders de accounting_system/. |
| Cyan | PostgreSQL | Tablas en nostromo_common y bases por tenant. |
| Violeta | Stored Proc | Lógica residual en PostgreSQL (compras/ventas detalle). |
| Verde | Orchestrator | Servicios y motor de cálculo en TypeScript. |
| Teal | Sevastopol | Islands SolidJS y proxy autenticado. |
Flujos de Datos Principales
Section titled “Flujos de Datos Principales”Carga de parámetros desde servicios externos hacia el schema parametros de nostromo_common:
flowchart LR
BC["Banco Central"] -->|API| BCL["bc_loader.py"]
BCL -->|Upsert| PM["parametros.monedas"]
PR["Previred"] -->|JSON| PRL["previred_loader.py"]
PRL -->|Upsert| PP["parametros.indicadores · afp · afc"]
SII["SII"] -->|Scraping| I2C["impuesto_2cat_loader.py"]
I2C -->|Upsert| PI["parametros.impuesto_2cat"]
classDef ext fill:#2d2d2d,stroke:#d3095f,stroke-width:2px,color:#fff;
classDef py fill:#0d1117,stroke:#e3b341,stroke-width:2px,color:#fff;
classDef db fill:#0d1117,stroke:#2b95d6,stroke-width:2px,color:#fff;
class BC,PR,SII ext
class BCL,PRL,I2C py
class PM,PP,PI db Extracción de compras y ventas del SII hacia el schema operaciones_sii del tenant:
flowchart LR
SII["SII"] -->|Playwright| RCS["run_cargas_sii.py"]
RCS -->|Insert| OPC["operaciones_sii.compras"]
RCS -->|Insert| OPV["operaciones_sii.ventas"]
RCS -->|Insert| OPB["operaciones_sii.boletas"]
OPC -->|Trigger| SP["sp_generar_compras_ventas_detalle"]
OPV -->|Trigger| SP
SP -->|Insert| CVD["operaciones_sii.compras_ventas_detalle"]
classDef ext fill:#2d2d2d,stroke:#d3095f,stroke-width:2px,color:#fff;
classDef py fill:#0d1117,stroke:#e3b341,stroke-width:2px,color:#fff;
classDef sp fill:#1f1235,stroke:#8e44ad,stroke-width:2px,stroke-dasharray: 5 5,color:#fff;
classDef db fill:#0d1117,stroke:#2b95d6,stroke-width:2px,color:#fff;
class SII ext
class RCS py
class SP sp
class OPC,OPV,OPB,CVD db Generación de liquidaciones con Hybrid Core (TypeScript Engine + Smart Views):
flowchart LR
SEV["Sevastopol Island"] -->|POST /api/remuneraciones/payroll/generate| API["Orchestrator Route"]
API -->|getPayrollContext| REPO["PayrollRepository"]
REPO -->|SELECT| CTX[("empleados + contratos<br/>+ indicadores + topes")]
CTX --> REPO
REPO -->|context| SVC["PayrollService"]
SVC -->|calculate input| ENG["PayrollEngine"]
ENG -->|result| SVC
SVC -->|savePayroll| REPO
REPO -->|INSERT| LIQ[("remuneraciones.liquidaciones<br/>+ liquidaciones_detalle")]
classDef front fill:#0d1117,stroke:#16a085,stroke-width:2px,color:#fff;
classDef back fill:#0d1117,stroke:#27ae60,stroke-width:2px,color:#fff;
classDef db fill:#0d1117,stroke:#2b95d6,stroke-width:2px,color:#fff;
class SEV front
class API,REPO,SVC,ENG back
class CTX,LIQ db Flujo de Generación de Liquidación
Section titled “Flujo de Generación de Liquidación”Capas que recorre una petición POST /api/remuneraciones/payroll/generate:
- Route (
routes/remuneraciones/payroll.ts) — Parsea el body, validacontrato_idyperiodo_mes, resuelve la base del tenant. - Service (
PayrollService.generatePayroll) — OrquestagetPayrollContext→mapContextToInput→calculate→savePayroll. - Repository.getPayrollContext — Consulta empleados, contratos, asistencia, indicadores, topes y tramos de impuesto. Llamadas paralelas con
Promise.all. - Engine.calculate — Función pura: sueldo base prorrateado, gratificación, leyes sociales (AFP, salud, AFC), impuesto único, totales.
- Repository.savePayroll — Inserta cabecera en
liquidacionesy líneas enliquidaciones_detalledentro de una transacción. - Response — JSON
snake_caseconid_liquidacion,total_liquido,total_haberes,total_descuentos.
flowchart TD
A[POST /api/remuneraciones/payroll/generate] --> R[Route handler]
R --> S[PayrollService.generatePayroll]
S --> CTX[PayrollRepository.getPayrollContext]
CTX --> MAP[mapContextToInput]
MAP --> ENG[PayrollEngine.calculate]
ENG --> SAVE[PayrollRepository.savePayroll]
SAVE --> RES[Response JSON]
style ENG stroke:#27ae60,stroke-width:4px
style CTX stroke:#2b95d6,stroke-width:2px
style SAVE stroke:#2b95d6,stroke-width:2px Arquitectura de Despliegue
Section titled “Arquitectura de Despliegue”graph TD
subgraph Client["Cliente"]
Browser["Navegador Web"]
end
subgraph CDN["Cloudflare Pages"]
Static["Jean d'Arc (Docs)"]
App["Sevastopol (App)"]
end
subgraph Backend["Servidor Node.js"]
Orchest["Orchestrator API"]
end
subgraph Data["Base de Datos"]
PG["PostgreSQL · Mother"]
end
Browser -->|HTTPS / 443| CDN
Browser -->|HTTPS / API| Orchest
Orchest -->|TCP / 5432| PG
classDef cdn fill:#f39c12,stroke:#d35400,color:#000;
classDef node fill:#27ae60,stroke:#2ecc71,color:#fff;
classDef db fill:#16a085,stroke:#1abc9c,color:#fff;
class Static,App cdn;
class Orchest node;
class PG db; graph TB
subgraph Presentación
A[Sevastopol · Astro + SolidJS]
end
subgraph API
B[Orchestrator · Express + TS]
end
subgraph Negocio
C[Services + Engines · TS]
D[Smart Views · SQL]
end
subgraph Datos
E[PostgreSQL · Mother]
end
A -->|HTTP/REST| B
B -->|Domain| C
B -->|Read-only| D
C -->|CRUD| E
D -->|Lee| E
linkStyle 0 stroke:#27ae60,stroke-width:2px;
linkStyle 1 stroke:#16a085,stroke-width:2px; Flujo de Autenticación
Section titled “Flujo de Autenticación”sequenceDiagram
participant U as Usuario
participant F as Sevastopol
participant A as Orchestrator
participant D as PostgreSQL
U->>F: Ingresa credenciales
F->>A: POST /api/auth/login
A->>D: SELECT * FROM nostromo_command.users WHERE email = $1
D-->>A: User + hash
A->>A: bcrypt.compare(password, hash)
alt Credenciales válidas
A->>D: INSERT INTO nostromo_command.sessions
A->>A: jwt.sign(payload, JWT_SECRET)
A-->>F: Set-Cookie sid=JWT (HttpOnly)
F->>U: Redirige al dashboard
else Credenciales inválidas
A-->>F: 401 Unauthorized
F->>U: Muestra error
end Multi-Tenancy (Database-per-Tenant)
Section titled “Multi-Tenancy (Database-per-Tenant)”Cada empresa tiene su propia base de datos PostgreSQL. El Orchestrator mantiene un pool cacheado por tenant.
flowchart LR
U["Usuario autenticado"] --> M["authenticateToken<br/>+ tenantResolver"]
M -->|tenant A| PA["Pool nostromo_60004317"]
M -->|tenant B| PB["Pool nostromo_70001234"]
subgraph DBA["nostromo_60004317"]
SA1[("remuneraciones")]
SA2[("operaciones_sii")]
SA3[("administracion")]
end
subgraph DBB["nostromo_70001234"]
SB1[("remuneraciones")]
SB2[("operaciones_sii")]
SB3[("administracion")]
end
PA --> SA1 & SA2 & SA3
PB --> SB1 & SB2 & SB3
linkStyle 0 stroke:#27ae60,stroke-width:2px;
linkStyle 1 stroke:#f39c12,stroke-width:2px;
linkStyle 2 stroke:#f39c12,stroke-width:2px;