superapp

command
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

README

superapp — arnés de aceptación cross-engine de Quark

Arnés headless que ejerce la superficie pública de Quark contra los 6 motores (SQLite, PostgreSQL, MySQL, MariaDB, MSSQL, Oracle) y demuestra la cobertura: no afirma "lo probamos todo", lo reconcilia contra un manifiesto de la API generado del propio código.

No es producto. Es la versión productizada y permanente del bug-bash F1–F14, conducida por una capa de servicio→Quark y gateada por manifiesto. Complementa, no sustituye, la suite unitaria/integración del repo.

Requisitos

  • Go 1.25.7 (igual que el go.mod del repo).
  • Docker: PG/MySQL/MariaDB/MSSQL vía testcontainers; Oracle vía docker run (no testcontainers — su lifecycle crashea en runners, igual que en .github/workflows/ci.yml), con GRANT EXECUTE ON DBMS_LOCK y pool corto (ORA-12516 en la imagen free).

Layout

examples/superapp/
├── README.md            ← este blueprint
├── COVERAGE.md          ← inventario de la API de Quark ejercida por fase (snapshot manual)
├── domain/              ← modelos que fuerzan la amplitud de la API
│   └── models.go
├── control/             ← maquinaria de cobertura/paridad/gate (stdlib, compila solo)
│   ├── capability.go    ← matriz de capacidad por motor (qué espera ErrUnsupportedFeature)
│   ├── report.go        ← status + matriz método×motor + gate
│   └── manifest.go      ← manifiesto de superficie + allowlist + reconciliador
├── recorder/            ← middleware+observer Quark → invocación por símbolo/motor + captura SQL
│   ├── recorder.go
│   ├── recorder_test.go ← e2e contra SQLite real
│   └── infra_test.go    ← [tag superapp_infra] Docker: OTel→Jaeger + logger + caché Redis
├── engine/              ← runner por motor (docker-run, no testcontainers) + anti-fugas (goroutines/pool)
│   ├── engine.go        ← Up/Down/waitReady (espeja bugbash); SUPERAPP_DSN_<ENGINE> override
│   ├── leak.go          ← Run(): client por motor → fn → Close → verifica pool=0 + goroutines
│   ├── engine_test.go   ← SQLite in-process, sin Docker
│   └── engine_docker_test.go ← [tag superapp_engine] Postgres docker-run real
├── exercise/            ← exercisers por área (reusan engine.Run) + cobertura por símbolo
│   ├── suite.go         ← Run(): recorder por motor → exercisers → cobertura (control.Invoked)
│   ├── crud.go          ← patrón canónico: Create/First/Count/Update/Delete(soft)/List
│   ├── tx.go            ← transacciones: commit multi-entidad + rollback atómico
│   └── builder.go       ← agregados/GroupBy/WhereIn/Or/OrderBy/Distinct/Iter/Cursor/Find/Paginate
├── cli/                 ← cobertura del binario cmd/quark (manifiesto de comandos, no de símbolos)
│   ├── doc.go
│   └── cli_test.go      ← [tag superapp_cli] exerciser de los 21 comandos + database-first (SQLite)
├── workload/            ← carga de alto volumen + informe ejecutivo (datos relacionados/tx/caché)
│   ├── workload.go      ← seed masivo + mezcla de queries/tx/cache; métricas vía recorder
│   └── report.go        ← executive-report.md + metrics.json
├── cmd/
│   ├── workload/        ← runnable: go run … → REPORTS/workload-<stamp>/{report,metrics,log}
│   └── gen-apisurface/  ← go/packages+go/types → apisurface.json (determinista; go:generate)
├── REPORTS/             ← [generado, gitignored] artefactos de cada corrida del workload
├── apisurface.json      ← [generado, versionado] denominador: 655 símbolos en 7 paquetes
├── allowlist.json       ← out-of-scope justificado (Symbol.Key → motivo)
└── main.go              ← [S6] wiring: corre exercisers, reconcilia, emite matriz a REPORTS/, gatea

Ejecución

# un motor (gate off por defecto: sólo falla con asserts rojos / fugas)
go run ./examples/superapp -engines=sqlite

# todos, gate estricto (falla si queda símbolo in-scope sin cubrir fuera de allowlist)
# Oracle requiere el contenedor levantado + SUPERAPP_DSN_ORACLE
go run ./examples/superapp -engines=all -gate=strict

Emite a REPORTS/superapp-<stamp>/: matrix.txt (matriz método×motor con estados PASS/MISSING/FAIL + una fila de salud por motor) y summary.json (cobertura/missing/allowlisted/strays + error funcional o fuga por motor, para consumir desde CI). Flags: -engines, -gate, -out, -manifest, -allowlist, -keep. Nota: los motores fuera de -engines aparecen MISSING en la matriz y quedan fuera del gate; el 100% in-scope sólo es alcanzable con -engines=all (cada símbolo debe invocarse en cada motor, capability-gated incluidos vía su sentinel). Lo pendiente para cerrar el gate vive en S7 (CI) y S8.

Carga de alto volumen + informe ejecutivo (ya disponible)
# SQLite, ~93k filas relacionadas (escala ×3 por defecto)
go run ./examples/superapp/cmd/workload

# más volumen / otro motor
go run ./examples/superapp/cmd/workload -scale=10
go run ./examples/superapp/cmd/workload -driver=pgx -dsn="$QUARK_TEST_POSTGRES_DSN"

Siembra datos relacionados (accounts→projects→tasks, memberships con PK compuesta, attachments binarios), ejerce queries/paginación/preload, transacciones multi-entidad, updates/deletes y lecturas cacheadas; con el recorder midiendo cada statement. Emite a REPORTS/workload-<stamp>/: executive-report.md (volumen, perfil SQL, latencias p50/p95/p99, hit-rate de caché, throughput), metrics.json y quark.log (slog JSON: fases + slow-query WARN). Flags: -scale, -driver, -dsn, -out, -slow-ms.

DSNs por env (igual que la suite del repo): QUARK_TEST_POSTGRES_DSN, QUARK_TEST_MYSQL_DSN, QUARK_TEST_MSSQL_DSN, QUARK_TEST_ORACLE_DSN. SQLite corre en proceso.

Mecanismos de control (mapa archivo → control)

  1. Cobertura de superficiecontrol/manifest.go (Reconcile) + recorder/ + cmd/gen-apisurface. Gate principal.
  2. Paridad cross-engineexercise/ (oráculo diferencial; normaliza Oracle ''→NULL, MSSQL uuid, wire UTC).
  3. Snapshots de SQLrecorder/ captura el SQL por método/dialecto → golden files.
  4. Aserciones funcionales — cada exercise/* comprueba estado/retorno: cache hit = 0 SQL, N+1 acotado, ErrStaleEntity, audit atómico, eventos post-commit.
  5. Seguridadexercise/security.go (attack suite SQLGuard: identificadores/JSON-path/JOIN-ON hostiles → ErrInvalid*).
  6. Concurrencia/resilienciaexercise/ha.go (deadlock retry real, pool exhaustion sin leak, savepoints, routing de replicas, sharding sin fuga cross-shard).
  7. Migraciones/schemaexercise/migrate.go (round-trip MigratePlanMigration vacío en los 6, Sync, Up/Down, Backfill con resume).
  8. Observabilidadexercise/observability.go (exporter OTel en memoria: counter + histogramas + redacción por defecto).
  9. Fugas/teardownengine/ (goroutines + sql.DBStats.InUse==0, contenedores sin residuo).
  10. Reporte y gatecontrol/report.go + main.go (matriz método×motor a REPORTS; falla si <100% in-scope o cualquier assert rojo).
  11. CLI (cmd/quark)cli/ (cobertura del binario por manifiesto de COMANDOS, no de símbolos: build→exec→assert exit-code + golden output; allowlist para comandos diferidos). El gate de símbolos de S3 no aplica al package main; el contrato público del CLI es su interfaz cobra.

Scope (honesto)

"100% cobertura" = 100% de la superficie in-scope (655 símbolos hoy). Lo fuera de scope vive en allowlist.json con motivo (Symbol.Key → razón). Nota verificada al generar el manifiesto: los diferidos a v1.2 (F6-3b binder codegen, scatter-gather + shard-key-from-entity, stampede cross-instancia) no están en el denominador —no son símbolos exportados hoy (el binder vive en internals de codegen; scatter-gather/stampede son features futuras sin símbolo)— así que no necesitan entrada de allowlist. La allowlist se reserva para símbolos que SÍ existen pero el exerciser no debe cubrir (p.ej. el alias deprecado RowLevelSecurity).

Capacidad desigual por motor (no es fallo): RowLevelSecurityNative y LISTEN/NOTIFY son PG-only; el lock de migración no está en SQLite/Oracle. La matriz de control/capability.go lo codifica y el exerciser exige ErrUnsupportedFeature en esos motores.

Estado de construcción

  • Blueprint + esqueleto (este drop)
  • Núcleo de control: capability/report/manifest (stdlib)
  • Dominio
  • recorder (Middleware símbolo→SQL por context + QueryObserver filas; Mark/Note/Collectcontrol.Invoked, Statements → snapshots; e2e SQLite verde)
  • cmd/gen-apisurface + apisurface.json (655 símbolos, determinista) + allowlist.json (S3)
  • engine matrix runner (engine/, S4): docker-run + anti-fugas; verde en SQLite in-process + Postgres docker-run (pool 0/0, goroutines estables)
  • [~] exercisers (S5, en curso): harness suite.go + crud + tx + builder + relations + security verdes en SQLite y PG real (34 símbolos); faltan cache/tenant/migrate/security/ha/observability + oráculo de paridad
  • [~] CLI cmd/quark (S9): exerciser SQLite verde (cli/, 20/21 comandos + tenant provision en allowlist; database-first model generate --from-table → compila); falta manifiesto enumerado de cobra + golden output + cross-engine
  • workload de alto volumen + informe ejecutivo (workload/ + cmd/workload/): ~310k filas / 0 errores en SQLite ×10; report.md + metrics.json + quark.log
  • main + gate + CI

Nota: este andamiaje se escribió sin compilador en el entorno de la sesión; compílalo con Go 1.25.7. Los slices pendientes se entregan compile-checked.

Documentation

Overview

Command superapp ejerce TODA la superficie pública de Quark contra los motores seleccionados y DEMUESTRA la cobertura reconciliándola contra el manifiesto generado (apisurface.json, el denominador). Emite la matriz método×motor a REPORTS/ y gatea: falla si algún assert funcional es rojo (o hay una fuga) y —en modo estricto— si queda un símbolo in-scope sin cubrir fuera de la allowlist.

# un motor (por defecto, gate off → sólo falla con asserts rojos)
go run ./examples/superapp -engines=sqlite

# los 6 con gate estricto (Oracle requiere su contenedor o SUPERAPP_DSN_ORACLE)
go run ./examples/superapp -engines=all -gate=strict

SQLite corre in-process; el resto se levanta por `docker run` (o se reusa vía SUPERAPP_DSN_<ENGINE>); ver engine.Up. La matriz va a REPORTS/superapp-<stamp>/ (gitignored). Invócalo desde la raíz del repo, o pasa -manifest/-allowlist.

Directories

Path Synopsis
Package cli es el área de cobertura del BINARIO `cmd/quark` dentro del arnés de aceptación (superapp S9).
Package cli es el área de cobertura del BINARIO `cmd/quark` dentro del arnés de aceptación (superapp S9).
cmd
gen-allowlist command
Command gen-allowlist genera allowlist.json: la decisión de DENOMINADOR del gate de cobertura (S7-coverage).
Command gen-allowlist genera allowlist.json: la decisión de DENOMINADOR del gate de cobertura (S7-coverage).
gen-apisurface command
Command gen-apisurface genera apisurface.json: el DENOMINADOR del gate de cobertura del superapp — todo símbolo exportado de la superficie pública de Quark (el paquete raíz + los subpaquetes públicos).
Command gen-apisurface genera apisurface.json: el DENOMINADOR del gate de cobertura del superapp — todo símbolo exportado de la superficie pública de Quark (el paquete raíz + los subpaquetes públicos).
workload command
Command workload ejerce el dominio de la superapp a alto volumen y emite un informe ejecutivo, métricas y el log de la aplicación, para contrastar cómo corre Quark con datos relacionados, consultas, transacciones y caché.
Command workload ejerce el dominio de la superapp a alto volumen y emite un informe ejecutivo, métricas y el log de la aplicación, para contrastar cómo corre Quark con datos relacionados, consultas, transacciones y caché.
Package control implementa la maquinaria de cobertura, paridad y gating de la superapp de aceptación: el manifiesto de superficie pública, el reconciliador invocado-vs-manifiesto, la matriz de capacidad por motor y el reporte/gate.
Package control implementa la maquinaria de cobertura, paridad y gating de la superapp de aceptación: el manifiesto de superficie pública, el reconciliador invocado-vs-manifiesto, la matriz de capacidad por motor y el reporte/gate.
Package domain define el modelo de la superapp.
Package domain define el modelo de la superapp.
Package engine arranca y teardownea los 6 motores para el arnés del superapp, y verifica que no haya fugas (goroutines, conexiones del pool) tras cerrar.
Package engine arranca y teardownea los 6 motores para el arnés del superapp, y verifica que no haya fugas (goroutines, conexiones del pool) tras cerrar.
Package exercise ejerce la superficie pública de Quark contra cada motor, marcando los símbolos que invoca (para el gate de cobertura del manifiesto) y asertando el resultado funcional.
Package exercise ejerce la superficie pública de Quark contra cada motor, marcando los símbolos que invoca (para el gate de cobertura del manifiesto) y asertando el resultado funcional.
Package recorder instrumenta un Client de Quark para la superapp de aceptación: observa cada statement SQL y lo atribuye al símbolo de la API pública que lo originó, alimentando dos mecanismos del arnés:
Package recorder instrumenta un Client de Quark para la superapp de aceptación: observa cada statement SQL y lo atribuye al símbolo de la API pública que lo originó, alimentando dos mecanismos del arnés:
Package workload ejerce el dominio de la superapp a ALTO VOLUMEN —datos relacionados, consultas, transacciones y caché— y recolecta métricas para un informe ejecutivo.
Package workload ejerce el dominio de la superapp a ALTO VOLUMEN —datos relacionados, consultas, transacciones y caché— y recolecta métricas para un informe ejecutivo.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL