Oracle3
Open-source trading engine and MCP server for prediction markets. Fee-aware no-arbitrage trading across related contracts, live on Kalshi, Polymarket and Solana or on paper.
Ahorro rotativo comunitario con la calidez de la comunidad y el rigor de una fintech. Tu plata, tu grupo, tu confianza.
Translation pending
FinanceJava · TypeScriptGitHub @PabloArauzCaballeroOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
AportaYa — billetera móvil de pasanaku boliviano: modelo de datos, especificación y landing
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
AportaYa es un sistema para crear, administrar y seguir grupos de pasanaku, operado como una billetera móvil: los participantes tienen saldo, aportan y cobran desde la app, y la plataforma cobra una comisión pequeña por cada juego. Esta rama contiene el modelo de datos completo del sistema.Read the full README ↗
AportaYa es un sistema para crear, administrar y seguir grupos de pasanaku, operado como una billetera móvil: los participantes tienen saldo, aportan y cobran desde la app, y la plataforma cobra una comisión pequeña por cada juego. Esta rama contiene el modelo de datos completo del sistema.
Ese salto —de herramienta de organización a proveedor de servicios de pago— es lo que explica los tres módulos finales: custodia del dinero con encaje verificable (M10), motor de tarifas parametrizable con facturación (M11) y el aparato de cumplimiento que un supervisor financiero espera encontrar implementado (M12).
La carpeta docs/ es además una bóveda de Obsidian: ábrala con
Abrir carpeta como bóveda y empiece por Index.md para recorrer el modelo como
grafo, con una nota por tabla y una por clave foránea
(docs/Modelos/, generadas con
scripts/generar_boveda.py).
Para cada módulo hay dos archivos en docs/entidades/:
.puml con dos diagramas: el modelo de clases (diseño orientado a
objetos, con estereotipos DDD) y el modelo relacional (entidad-relación
listo para traducir a DDL);.md que documenta, entidad por entidad, qué hace y por qué debería
existir: qué problema real del pasanaku resuelve, qué se rompería si se
elimina, y qué papel cumple en el sistema.Cubre el Documento de Requerimientos v2.0 (pago QR, WhatsApp, transparencia, reputación), el Parche A (organizador digital automatizado, organizador humano sin comisión y fondo de garantía) y el Parche B: billetera móvil con custodia, comisión de plataforma y cumplimiento regulatorio (módulos 10 a 12).
Los catorce servicios arrancan, sirven sus rutas y niegan sin token. Estos comandos estan ejecutados, no supuestos.
# 1 · la base, con las 306 tablas, los roles y los catalogos
docker compose -f despliegue/compose/base.yml --profile base up -d --wait
# 2 · el gate completo: formato, arquitectura, atomos, casos de uso, contratos y sagas
./gradlew verificar
# 3 · que los catorce LEVANTAN, no solo que compilan
./gradlew integrationTest # incluye ArranqueTest de cada servicio
# 4 · el stack entero en contenedores
python3 scripts/generar_compose.py
python3 scripts/generar_gateway.py # las rutas de la entrada publica, desde PREFIJOS
docker buildx create --name aportaya --driver docker-container \
--driver-opt network=aportaya-interna --use # una sola vez
# La construccion tiene que ALCANZAR la base para generar las clases de jOOQ, y el
# paso RUN de buildkit no usa el DNS de Docker: se le pasa la IP del contenedor.
IP=$(docker inspect aportaya-postgres --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}')
for s in identidad grupos aportes nucleo-financiero garantia organizador transparencia; do
docker buildx build --load --allow network.host --network=host \
-f despliegue/Dockerfile --build-arg SERVICIO="$s" \
--build-arg BD_URL_ADMIN="jdbc:postgresql://$IP:5432/pasanaku" \
-t "aportaya/${s}:local" .
done
docker compose -f despliegue/compose/base.yml -f despliegue/compose/servicios.yml \
--profile todo up -d --no-build --wait
El constructor va atado a aportaya-interna porque las clases de jOOQ se generan
introspeccionando la base viva y .dockerignore deja **/build afuera: la
construccion tiene que alcanzar a PostgreSQL. Sin eso, compileJava falla con
«package bo.aportaya.<servicio>.generado does not exist» y no hay imagen posible.
Y se construye de a uno: catorce Gradle en paralelo se pelean por el mismo lock del
cache y la corrida muere a los cuatro minutos.
El gateway (y, cuando cada servicio los adopte, el resto) usa
spring.profiles.active para decidir su configuración: local (default en
despliegue/compose/base.yml), test (espejo de dev), staging y
production. Los dos últimos son fail closed: arrancan sin CORS
configurado (APORTAYA_CORS_ORIGENES sin setear) y el proceso se niega a
levantar — ver plataforma/gateway/src/main/java/bo/aportaya/gateway/ConfiguracionCors.java
y [[ADR-050]].
# local (lo que trae el compose de desarrollo por omisión)
SPRING_PROFILES_ACTIVE=local
# production — exige el dominio real, no arranca sin él
SPRING_PROFILES_ACTIVE=production APORTAYA_CORS_ORIGENES=https://app.aportaya.example
Las cuentas de sql/61_dev/ se siembran sin contrasena en claro —el repositorio no
guarda credenciales— asi que hay que ponerle una a la base local:
CLAVE_DEV='la-que-quieras' python3 scripts/clave_dev.py --huella <32 hex de la app>
Eso pone la misma contrasena a las once cuentas de prueba (+59171000001…009,
+59171000090 participante y +59171000091 backoffice) y marca ese dispositivo como
de confianza. Lo segundo importa: ExigeSegundoFactor pide MFA a todo dispositivo
desconocido, y las cuentas de prueba no tienen factor enrolado, asi que sin eso el
ingreso no termina. La huella la genera la app al instalarse.
La app apunta por omision a http://localhost/api/v1, que es NGINX. Para el simulado:
--dart-define=API=http://localhost:4010/api/v1.
El simulador de iOS no tiene camara y no puede usar la del Mac: no expone ningun
AVCaptureDevice, asi que image_picker con ImageSource.camera devuelve nada. Es
de Apple, no del codigo — Apple lista la camara entre el hardware que el simulador no
simula. Hay dos formas de recorrer igual el alta:
1 · Prestarle la camara del Mac (gratis, en este repositorio):
python3 scripts/camara_del_mac.py # queda escuchando en 8899
flutter run --dart-define=CAMARA_DEV=http://localhost:8899/foto
La primera vez macOS pide permiso de camara para la terminal. Hay que aceptarlo una vez, o la captura se queda esperando el dialogo; para provocarlo a mano:
ffmpeg -f avfoundation -framerate 30 -i "0" -frames:v 1 -y /tmp/prueba.jpg
La foto es real y sale de la camara del Mac; lo unico que falta es el visor. Sin la
bandera CAMARA_DEV este camino no existe en el binario.
2 · SimCam (de Software Mansion, 19 USD por unica vez, con prueba gratuita):
https://simcam.swmansion.com — se abre ANTES que la app, hace de camara virtual y da
visor de verdad. Su autor confirma que funciona con image_picker. No hay que tocar
la app. Tiene un tope conocido de 480x640 en la resolucion entregada.
Y siempre, sin nada de lo anterior: «Elegir de mis fotos». Se le carga una imagen
a la fototeca del simulador con xcrun simctl addmedia booted foto.jpg.
Los cuatro verificadores de la boveda corren solos y no necesitan nada levantado:
python3 scripts/verificar_boveda.py # cifras, enlaces y cobertura de la boveda
python3 scripts/verificar_carriles.py # cada servicio con su dueno y su descriptor
python3 scripts/verificar_criterios.py # cada criterio de aceptacion, con su prueba
python3 scripts/verificar_seguridad.py # patrones prohibidos, secretos y rutas abiertas
Que hay y que falta esta en
planes/informes/carril-T.md: 122 de las 138
operaciones servidas, dieciseis declaradas como huecos de contrato entre carriles, y
la lista de lo que la Fase 17 todavia debe.
La carpeta docs/ no es solo documentación: es la especificación ejecutable
del sistema, en cuatro capas encadenadas.
| Capa | Dónde | Responde |
|---|---|---|
| Norma | docs/Cumplimiento.md | qué obliga ASFI, UIF, BCB, el SIN y las ISO |
| Caso de uso | docs/CasosDeUso/ | cómo se ejecuta cada flujo, paso a paso — 99 casos |
| Restricción | docs/Restricciones.md | qué impide, en la base, que se viole — 141 reglas |
| Seguridad | docs/Seguridad.md | cómo se escribe el código para que resista un ataque, y con qué comando se comprueba cada control |
| Modelo | docs/Modelos/ | dónde vive cada dato |
| Esquema | sql/ | el DDL ejecutable, generado desde las tres capas anteriores |
| Arquitectura | docs/Arquitectura/ | con qué se implementa, y por qué así |
| Stack | docs/Stack.md | qué tecnología se eligió y qué alternativas perdieron |
python3 scripts/generar_boveda.py # notas del modelo (Obsidian) desde los .puml
python3 scripts/generar_ddl.py # esquema SQL completo desde los .puml + el catálogo
./gradlew bd:aplicar # esquema y reglas sobre la base de trabajo
./gradlew bd:semillas # los 20 catálogos mínimos
./gradlew bd:humo # 165 comprobaciones, sobre una base DESECHABLE
El esquema son 306 tablas en un archivo cada una, con las claves foráneas y los
índices en pasadas aparte —el orden que necesita la introspección de tipos— más el
sellado de las tablas append-only y el catálogo de restricciones. Verificado sobre
PostgreSQL 16: aplica sin errores las veces que haga falta —cada objeto se borra
si existe antes de crearse, porque aplicar.sql no es una migración sino el esquema
entero— y la prueba de humo confirma que las restricciones
rechazan lo que deben rechazar.
La arquitectura está en docs/Arquitectura/:
una decisión por documento, cada una con el motivo por el que se tomó y lo que la
revertiría, más el método con el
que se diseña siempre y tres prompts generalistas
—general, backend y frontend— que imponen dividir todo en átomos, moléculas y
organismos.
Las skills del proyecto describen cómo se trabaja sobre esta bóveda, en siete
grupos: método y arquitectura, especificación, construcción, interfaz, dominio,
cumplimiento y control, y operación y entrega. El índice completo —con cuándo se usa
cada una— está en .claude/skills/README.md, y
scripts/verificar_boveda.py comprueba que ninguna quede fuera de ese índice.
Los lineamientos externos que se incorporaron —y los que se eliminaron por contradecir una decisión ya tomada— están en Lineamientos adoptados y descartados.
El contraste requisito por requisito contra ASFI (Reglamento ETF Res. 540/2025,
protección del consumidor financiero, riesgo operativo, seguridad de la
información), UIF (instructivo vigente y sus umbrales de billetera móvil), BCB
(RD 079/2022), facturación electrónica del SIN e ISO/IEC 27001, 22301, 31000 y
19011 está en docs/Cumplimiento.md, con el estado de cada
requisito y las brechas abiertas —incluida la principal: este producto requiere
autorización de ASFI antes de operar con dinero real.
| Módulo | Diagramas | Fichas de entidades | Requerimientos |
|---|---|---|---|
| Identidad, Usuarios y Seguridad de Acceso | .puml | .md | RF-01, RF-18 (base), RN-01, RN-17 |
| Grupos, Cupos, Turnos y Gobernanza | .puml | .md | Núcleo + RF-19 |
| Aportes, Pagos QR, Conciliación y Contabilidad | .puml | .md | RF-15, RN-05, RN-17 |
| Entregas de Fondo (liquidación y desembolso) | .puml | .md | Núcleo, RN-05 |
| Notificaciones y Comunicaciones | .puml |
Estas son las decisiones que separan un modelo de clase de un modelo que aguanta producción con dinero de terceros:
TokenVerificacion → TokenOTP / TokenEnlaceFirmado / TokenRefresco,
con PoliticaToken parametrizable por propósito, IntentoValidacionToken
para detectar fuerza bruta y clave de idempotencia para evitar doble
emisión. Nunca se persiste el valor plano: solo su hash con pepper.RegistroIncumplimiento con evidencia, línea de tiempo de estados,
descargo del participante, gestión de cobranza escalonada, deuda exigible,
subrogación al fondo, aval solidario, sanción proporcional y apelación. La
reputación es una consecuencia de este expediente, no el registro mismo.AsientoContable +
MovimientoContable con invariante SUM(debe) = SUM(haber). El panel de
transparencia se calcula desde el mayor, no desde sumas ad-hoc. Nada se
edita: se reversa.clave_idempotencia única. Un reintento del proveedor no acredita dos veces.tipo × severidad × reincidencia, plazo de descargo, estado FIRME antes de
ejecutar y derecho a apelación en dos instancias.hash_anterior, auditoría de lectura separada de la de
escritura, y EventoDominio escrito en la misma transacción que el cambio.Los módulos comparten claves foráneas, señaladas en notas dentro de cada diagrama. Mapa general de dependencias:
1. Identidad y Seguridad ─── usuario_id, token_id ──┬──► 2, 3, 4, 5, 7, 8
│ │
│ restriccion_usuario ◄───────────────────── 8 (incumplimiento)
▼
2. Grupos, Cupos y Turnos ──► 3. Aportes y Pagos QR ──► 4. Entregas de Fondo
│ grupo/cupo/periodo │ obligacion_id │
│ │ │ deducciones
│ ▼ ▼
│ 8. Garantía e Incumplimiento ◄─────┘
│ │ cobertura, deuda, sanción
│ ▼
└────────────────► 6. Transparencia y Reputación ◄──── eventos
▲
2. Grupos ──► 7. Organizador y Automatización ──► 3 (cobro) y 4 (entrega)
5. Notificaciones consume eventos de 2, 3, 4, 7 y 8 (cobranza)
3 / 4 / 7 / 8 ──► 9. Auditoría, Reportes y Cumplimiento (transversal)
── capa de dinero real (Parche B) ──
10. Billetera y Custodia ◄── aporta/cobra ──► 2, 3, 4 y 8
│ saldo, retenciones, encaje 100%
│ ▲
▼ │ cobro por débito o deducción
11. Tarifas y Comisiones ──────┘──► 4 (deducción de la bolsa) y 3 (mayor)
│ devengo, factura, ingreso
▼
12. Cumplimiento Regulatorio ◄── vigila ── 10 (saldo y operaciones)
│ límites por nivel, monitoreo, reportes, reclamos
└──► 10 (bloqueo de saldo) · 9 (auditoría) · 11 (devolución por reclamo)
Puntos de integración concretos más usados:
token_verificacion (M1) respalda invitaciones (M2), enlaces de pago (M3/M5),
confirmación de entrega (M4), firma de reglamento (M2) y aceptación de aval (M8).obligacion_aporte (M3) es el eje: la cubre el fondo (M8), la deduce la
entrega (M4) y la puntúa la reputación (M6).acuerdo (M2) autoriza lo que no puede ser unilateral: condonaciones,
expulsiones, permutas, cambio de reglamento y disolución.evento_dominio (M9) es el canal por el que M5, M6 y el cumplimiento se
enteran de lo que pasa, sin acoplar los módulos entre sí.cuenta_billetera (M10) da titularidad al dinero: hay una cuenta del grupo
—no del organizador— y el aporte es una transferencia interna instantánea.devengo_comision (M11) se cobra por tres vías intercambiables por
configuración: deducción de la entrega (M4), débito de billetera (M10) u
obligación de aporte (M3).calificacion_riesgo_cliente (M12) gobierna los limite_operativo_billetera
(M10): subir de nivel de verificación es lo que habilita operar más.Diagramas de clases
- privado, # protegido, + público; {static} para
operaciones de clase.<<AR>> raíz de agregado, <<VO>> objeto de valor,
<<Svc>> servicio de dominio, <<Pol>> política configurable.creadoEn, actualizadoEn,
creadoPor, version (bloqueo optimista) y eliminadoEn (borrado lógico).Modelo relacional
* PK, # FK, <<UQ>> único, <<IDX>> indexado, <<CK>> restricción
CHECK, <<NULL>> admite nulos. Nombres en snake_case.DECIMAL(14,2) (o 16,2 para acumulados) siempre acompañados de
moneda CHAR(3) ISO-4217. Fechas en TIMESTAMPTZ.UPDATE/DELETE a nivel de rol de base de datos.VS Code: extensión PlantUML (jebbs), Alt+D para previsualizar (se
generan dos vistas por archivo, una por cada @startuml).
Línea de comandos (requiere Java + plantuml.jar):
java -jar plantuml.jar -tsvg -charset UTF-8 docs/entidades/*.puml
Genera un .svg por diagrama, nombrado según el título interno del @startuml
(..._clases.svg y ..._relacional.svg). Para PNG use -tpng; los diagramas
grandes (módulos 1, 2, 7 y 8) se leen mejor en SVG.
En línea: pegue el contenido en https://www.plantuml.com/plantuml. Si el
visor solo renderiza un diagrama a la vez, copie cada bloque
@startuml ... @enduml por separado.
.md| RF-16 |
| Transparencia, Reputación y Confianza | .puml | .md | RF-17, RF-18 |
| Organizador y Automatización | .puml | .md | RF-20, RN-18, RN-22 |
| Garantía, Incumplimiento, Cobranza y Sanciones | .puml | .md | RF-21, RN-21 |
| Auditoría, Reportes y Cumplimiento | .puml | .md | RN-17 |
| Billetera, Custodia y Dinero Electrónico | .puml | .md | RF-22, RN-23, RN-24 |
| Tarifas, Comisiones, Impuestos y Facturación | .puml | .md | RF-23, RN-25, RN-26 |
| Cumplimiento Regulatorio y Consumidor Financiero | .puml | .md | RN-27 a RN-30 |
| Contabilidad Financiera y ERP | .puml | .md | CU-100 a CU-106 |
| Publicidad y Campañas | .puml | .md | CU-110 a CU-114 |
organizadorUPDATE cuenta SET saldo = saldo - 500. Hay un libro append-only
(transaccion_billetera + movimiento_billetera) con partida doble interna:
todo movimiento tiene contrapartida, y la columna de saldo es apenas una caché
que un job verifica contra el libro.conciliacion_custodia
compara la suma de todos los saldos de billetera contra el saldo real de la
cuenta de custodia. Si el ratio de cobertura baja de 1, el sistema entra en
modo restringido solo y el descuadre escala como incidente y como evento de
riesgo operativo. El dinero de los usuarios es un pasivo exigible, no
patrimonio de la empresa.concepto_tarifa. Cambiar la política comercial es cargar un
tarifario nuevo, simularlo y publicarlo con preaviso; no es un despliegue. Y
el precio se congela por grupo (tarifa_congelada_grupo): no cambia a mitad
del juego.