first commit

This commit is contained in:
JOSE ANASTACIO ESQUIVEL SALAS 2026-10-26 13:32:22 -06:00
parent b50f4955d6
commit 62401d3791
11 changed files with 138 additions and 7 deletions

View File

@ -1,11 +1,12 @@
# Copiar a .env y completar antes de ejecutar docker compose up --build -d. # Copiar a .env y completar antes de ejecutar docker compose up --build -d.
# PostgreSQL externo: sustituir por su DNS/IP. No usar localhost dentro del contenedor. # PostgreSQL externo: sustituir por su DNS/IP. No usar localhost dentro del contenedor.
# Para una base en el equipo anfitrión: jdbc:postgresql://host.docker.internal:5432/orquestador # Para una base en el equipo anfitrión: jdbc:postgresql://host.docker.internal:5432/orquestador
DB_URL=jdbc:postgresql://postgres.example.com:5432/orquestador DB_URL=jdbc:postgresql://server02:30432/orquestador
DB_USERNAME=orchestrator DB_USERNAME=pgadmin
DB_PASSWORD= DB_PASSWORD=
JWT_ISSUER_URI= SPRING_PROFILES_ACTIVE=postgres96
JWT_JWK_SET_URI= JWT_ISSUER_URI=http://keycloakic.ddns.net/auth/realms/controlms
JWT_JWK_SET_URI=http://keycloakic.ddns.net/auth/realms/controlms/protocol/openid-connect/certs
JWT_AUDIENCE=orquestador-nmp JWT_AUDIENCE=orquestador-nmp
APP_BIND_ADDRESS=127.0.0.1 APP_BIND_ADDRESS=127.0.0.1
APP_PORT=8080 APP_PORT=8080

View File

@ -9,7 +9,7 @@ Incluye la estructura Maven, configuración JWT/PostgreSQL, Docker y salud verif
## Requisitos y ejecución ## Requisitos y ejecución
- Docker con contenedores Linux y Compose v2. La imagen compila con JDK 21 y Maven Wrapper; no requiere Java/Maven en el anfitrión. - Docker con contenedores Linux y Compose v2. La imagen compila con JDK 21 y Maven Wrapper; no requiere Java/Maven en el anfitrión.
- PostgreSQL 17 externo con base y usuario existentes, accesible desde Docker. - PostgreSQL externo con base y usuario existentes, accesible desde Docker. El entorno actual usa PostgreSQL 9.6.2 en server02:30432 mediante el perfil postgres96; ver ADR-006.
- Un issuer JWT con JWKS y audiencia; se conserva la autenticación. - Un issuer JWT con JWKS y audiencia; se conserva la autenticación.
```powershell ```powershell
@ -23,6 +23,8 @@ docker compose logs -f orquestador
Compose levanta únicamente `orquestador`. Para PostgreSQL en otra máquina usar `jdbc:postgresql://HOST:5432/BASE`; si está en el anfitrión de Docker, usar `host.docker.internal` en lugar de `localhost`. Ver [RUNBOOK](specs/RUNBOOK.md). Compose levanta únicamente `orquestador`. Para PostgreSQL en otra máquina usar `jdbc:postgresql://HOST:5432/BASE`; si está en el anfitrión de Docker, usar `host.docker.internal` en lugar de `localhost`. Ver [RUNBOOK](specs/RUNBOOK.md).
Compose selecciona `postgres96` por defecto para el servidor disponible. `.env.example` contiene su URL/usuario y los endpoints Keycloak; completar DB_PASSWORD externamente y confirmar JWT_AUDIENCE con los tokens. Para una base moderna se puede seleccionar otro perfil, como `SPRING_PROFILES_ACTIVE=local`, conservando su DB_URL explícita. No se desactivan Flyway ni la validación del esquema en el servicio.
Salud: `http://localhost:8080/actuator/health/readiness`. El puerto publicado se configura con APP_PORT. El healthcheck incluye PostgreSQL; liveness no depende de proveedores. Las demás rutas requieren JWT. No hay endpoints de negocio implementados todavía. Salud: `http://localhost:8080/actuator/health/readiness`. El puerto publicado se configura con APP_PORT. El healthcheck incluye PostgreSQL; liveness no depende de proveedores. Las demás rutas requieren JWT. No hay endpoints de negocio implementados todavía.
## Organización y seguimiento ## Organización y seguimiento

View File

@ -5,6 +5,7 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
image: orquestador-nmp:local image: orquestador-nmp:local
environment: environment:
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-postgres96}
DB_URL: ${DB_URL:?Configura DB_URL en .env} DB_URL: ${DB_URL:?Configura DB_URL en .env}
DB_USERNAME: ${DB_USERNAME:?Configura DB_USERNAME en .env} DB_USERNAME: ${DB_USERNAME:?Configura DB_USERNAME en .env}
DB_PASSWORD: ${DB_PASSWORD:?Configura DB_PASSWORD en .env} DB_PASSWORD: ${DB_PASSWORD:?Configura DB_PASSWORD en .env}

14
pom.xml
View File

@ -22,6 +22,7 @@
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webmvc</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
<dependency><groupId>org.hibernate.orm</groupId><artifactId>hibernate-community-dialects</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security-oauth2-resource-server</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security-oauth2-resource-server</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
@ -54,6 +55,19 @@
</plugins> </plugins>
</build> </build>
<profiles> <profiles>
<profile>
<id>postgres96-check</id>
<build><plugins><plugin>
<groupId>org.apache.maven.plugins</groupId><artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<includes>
<include>**/*IT.java</include><include>**/IT*.java</include><include>**/*ITCase.java</include>
<include>**/Postgres96CompatibilityProbe.java</include>
</includes>
<failIfNoTests>true</failIfNoTests>
</configuration>
</plugin></plugins></build>
</profile>
<profile> <profile>
<id>deployment-smoke</id> <id>deployment-smoke</id>
<build> <build>

View File

@ -70,3 +70,15 @@ Herramientas fijadas, únicamente scope test: networknt json-schema-validator 1.
Se conserva una copia del schema oficial OpenAPI 3.1 (2022-10-07), SHA256 DA01BA28852CAC0DE53893797CB8D1942BC3B05084F526DCC216717DEC314ED0, para validar sin red. Swagger Parser con resolve=true intentó expandir indefinidamente las referencias recursivas del AST: se usa resolve=false y comprobación explícita de todos los $ref locales. Networknt valida los schemas y ejemplos reales. No se relajan límites ni se ignoran referencias rotas para resolver esa incompatibilidad. Se conserva una copia del schema oficial OpenAPI 3.1 (2022-10-07), SHA256 DA01BA28852CAC0DE53893797CB8D1942BC3B05084F526DCC216717DEC314ED0, para validar sin red. Swagger Parser con resolve=true intentó expandir indefinidamente las referencias recursivas del AST: se usa resolve=false y comprobación explícita de todos los $ref locales. Networknt valida los schemas y ejemplos reales. No se relajan límites ni se ignoran referencias rotas para resolver esa incompatibilidad.
Referencias: [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0), [schema oficial](https://spec.openapis.org/oas/3.1/schema/2022-10-07), [networknt](https://github.com/networknt/json-schema-validator), [Swagger Parser y soporte 3.1](https://github.com/swagger-api/swagger-parser). Detalles de uso en contracts/README.md y schemas/README.md. Referencias: [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0), [schema oficial](https://spec.openapis.org/oas/3.1/schema/2022-10-07), [networknt](https://github.com/networknt/json-schema-validator), [Swagger Parser y soporte 3.1](https://github.com/swagger-api/swagger-parser). Detalles de uso en contracts/README.md y schemas/README.md.
## ADR-006 — Compatibilidad con PostgreSQL disponible (2026-10-26)
El usuario solicita adaptar la conexión al PostgreSQL existente, identificado por JDBC como 9.6.2 en server02:30432/orquestador. Esta instrucción sustituye el requisito de PostgreSQL 17 para el entorno actual. La especificación original permanece como antecedente; las migraciones de T03 deberán ser compatibles con 9.6 (incluidas las formas de DDL de triggers), sin cambiar semántica de locking, idempotencia o seguridad.
Se añade hibernate-community-dialects 7.4.13.Final, alineado al BOM/core, y application-postgres96.yaml con PostgreSQLLegacyDialect. Compose activa postgres96 por defecto y permite elegir otro perfil explícito. Spring Boot/Java/JDBC/Flyway no se degradan. Se preservan ddl-auto=validate, Flyway habilitado y clean-disabled en runtime; no se modifica JWT. .env.example contiene parámetros públicos de conexión, nunca la contraseña.
Flyway 12.4.0 inspeccionado admite desde PostgreSQL 9.0 y la validación real sobre 9.6.2 pasó; registra que 9.6 queda fuera del soporte comunitario Redgate. El dialecto legacy pertenece al módulo comunitario de Hibernate, no al conjunto de dialectos actuales soportados. Esta adaptación no promete soporte oficial para la combinación ni prueba todavía consultas de entidades/migraciones del motor.
Verificación: clean verify con Java 21 (92 tests) y postgres96-check (1 prueba de integración compuesta). La prueba inicia el servicio local con pool read-only, Flyway automático desactivado, SQL init desactivado y validación Hibernate; después invoca exclusivamente Flyway.validate() con createSchemas=false. No ejecuta migrate/create/clean ni modifica la instancia externa. La primera propuesta de arranque fue rechazada por la revisión automática por riesgo de migraciones; se usó esta alternativa explícitamente de sólo lectura, aprobada y ejecutada.
Fuentes: [dialectos y módulo comunitario Hibernate](https://docs.hibernate.org/stable/core/dialect/), [versiones de bases de datos Flyway](https://documentation.red-gate.com/fd/supported-databases-and-versions-143754067.html). La compatibilidad se comprobó con las dependencias reales del proyecto, no sólo con la documentación.

View File

@ -55,6 +55,8 @@ Cerrado el 2026-10-26: clean verify con Java 21, 92 comprobaciones, 0 fallos/err
Dependencias: T02. Entregables: db/migration/, pruebas *IT. Dependencias: T02. Entregables: db/migration/, pruebas *IT.
Entorno objetivo actualizado por el usuario: PostgreSQL 9.6.2 disponible en server02; ver ADR-006. Usar DDL compatible con 9.6 y un entorno aislado para pruebas de escritura. La comprobación de conexión/arranque E11 no cierra esta tarea.
- [ ] Crear tablas, FKs e índices. - [ ] Crear tablas, FKs e índices.
- [ ] Añadir idempotencia de creación/admin_audit/reconciliation_resolution. - [ ] Añadir idempotencia de creación/admin_audit/reconciliation_resolution.
- [ ] Proteger inmutabilidad e historial con roles y triggers. - [ ] Proteger inmutabilidad e historial con roles y triggers.

View File

@ -8,7 +8,7 @@ Estados permitidos: PENDING, IN_PROGRESS, BLOCKED, DONE. No más de una tarea pr
|---|---|---|---|---|---|---|---| |---|---|---|---|---|---|---|---|
| T01 | DONE | — | pom.xml, mvnw*, .mvn, configuración, DeploymentSmokeCheck.java, ADR-001/004 | E09: clean verify con JDK 21 y deployment-smoke | BUILD SUCCESS; 5 pruebas, 0 fallos, 0 errores, 0 omitidas | Ninguno para T01 | Iniciar T02: OpenAPI y JSON Schema | | T01 | DONE | — | pom.xml, mvnw*, .mvn, configuración, DeploymentSmokeCheck.java, ADR-001/004 | E09: clean verify con JDK 21 y deployment-smoke | BUILD SUCCESS; 5 pruebas, 0 fallos, 0 errores, 0 omitidas | Ninguno para T01 | Iniciar T02: OpenAPI y JSON Schema |
| T02 | DONE | T01 DONE | contracts/openapi.yaml, schemas/*.schema.json, examples/contracts, ContractValidationTest.java, ADR-005 | E10: clean verify con Java 21 | BUILD SUCCESS; 92 comprobaciones, 0 fallos/errores/omisiones | Ninguno para T02 | Iniciar T03: migraciones PostgreSQL y Testcontainers | | T02 | DONE | T01 DONE | contracts/openapi.yaml, schemas/*.schema.json, examples/contracts, ContractValidationTest.java, ADR-005 | E10: clean verify con Java 21 | BUILD SUCCESS; 92 comprobaciones, 0 fallos/errores/omisiones | Ninguno para T02 | Iniciar T03: migraciones PostgreSQL y Testcontainers |
| T03 | PENDING | T02 DONE | db/migration/, pruebas *IT | Pendiente: Testcontainers PostgreSQL, rollback y migraciones | No ejecutado | Docker requerido para pruebas; dependencia T02 satisfecha | Crear tablas, FKs e índices y preparar entorno Testcontainers | | T03 | PENDING | T02 DONE | db/migration/, pruebas *IT | E11 verifica conexión/arranque 9.6; migraciones pendientes | Compatibilidad inicial aprobada; modelo no implementado | Falta entorno aislado para pruebas de migraciones | Crear DDL compatible con PostgreSQL 9.6 según ADR-006 |
| T04 | PENDING | T02,T03 | flow/, request/, execution/, decision/, action/ | Pendiente: Pruebas de dominio y dependencias entre capas | No ejecutado | Dependencias sin completar | Definir records y errores estables | | T04 | PENDING | T02,T03 | flow/, request/, execution/, decision/, action/ | Pendiente: Pruebas de dominio y dependencias entre capas | No ejecutado | Dependencias sin completar | Definir records y errores estables |
| T05 | PENDING | T04 | decision/, pruebas de AST | Pendiente: JUnit parametrizado: 71/70/61/60, tipos y solapamientos | No ejecutado | Dependencias sin completar | Implementar operadores/JSON Pointer/BigDecimal | | T05 | PENDING | T04 | decision/, pruebas de AST | Pendiente: JUnit parametrizado: 71/70/61/60, tipos y solapamientos | No ejecutado | Dependencias sin completar | Implementar operadores/JSON Pointer/BigDecimal |
| T06 | PENDING | T03,T04,T05 | flow/, admin_audit, pruebas *IT | Pendiente: Pruebas PostgreSQL de carreras publicación/activación/retiro | No ejecutado | Dependencias sin completar | Validar grafo, mappings, roles y capacidades | | T06 | PENDING | T03,T04,T05 | flow/, admin_audit, pruebas *IT | Pendiente: Pruebas PostgreSQL de carreras publicación/activación/retiro | No ejecutado | Dependencias sin completar | Validar grafo, mappings, roles y capacidades |
@ -24,6 +24,17 @@ Estados permitidos: PENDING, IN_PROGRESS, BLOCKED, DONE. No más de una tarea pr
| T16 | PENDING | T15 | src/test/, CI, matriz A01–A20 | Pendiente: ./mvnw clean verify con Docker, sin skips de integración | No ejecutado | Dependencias sin completar | Automatizar A01–A20 | | T16 | PENDING | T15 | src/test/, CI, matriz A01–A20 | Pendiente: ./mvnw clean verify con Docker, sin skips de integración | No ejecutado | Dependencias sin completar | Automatizar A01–A20 |
| T17 | PENDING | T16 | Dockerfile, compose.yaml, README, RUNBOOK, examples/http, CI | Pendiente: Build de imagen, compose, verify y demo completa de sección 16 | No ejecutado | Dependencias sin completar | Construir imagen y Compose completos | | T17 | PENDING | T16 | Dockerfile, compose.yaml, README, RUNBOOK, examples/http, CI | Pendiente: Build de imagen, compose, verify y demo completa de sección 16 | No ejecutado | Dependencias sin completar | Construir imagen y Compose completos |
## E11 — Adaptación PostgreSQL 9.6.2 — 2026-10-26 13:23 (America/Mexico_City)
- Solicitud del usuario: utilizar el PostgreSQL disponible. ADR-006 documenta la modificación del objetivo PostgreSQL 17 al entorno 9.6.2 actual.
- Configuración: perfil Spring postgres96, Hibernate PostgreSQLLegacyDialect (community-dialects 7.4.13.Final), Compose selecciona ese perfil por defecto. .env.example apunta a server02:30432/orquestador y no incluye contraseña.
- `.\mvnw.cmd --batch-mode --no-transfer-progress clean verify` con Java 21: BUILD SUCCESS, 92 tests aprobados (16.074 s).
- `.\mvnw.cmd --batch-mode --no-transfer-progress failsafe:integration-test failsafe:verify -Ppostgres96-check`, con DB/JWT en variables de proceso: BUILD SUCCESS, 1 prueba compuesta aprobada (12.696 s). Reporte: target/failsafe-reports/com.organizacion.compatibility.Postgres96CompatibilityProbe.txt.
- Evidencia: conexión real 9.6.2, dialecto PostgreSQLLegacyDialect, default_transaction_read_only=on, validación Flyway 12.4.0 de 0 migraciones, health/readiness/liveness HTTP 200 UP y ruta protegida HTTP 401. Servicio local detenido al terminar.
- Sin cambios a datos, schemas o historial de migraciones. El inicializador automático Flyway y SQL init se desactivaron únicamente en la prueba; la configuración normal conserva Flyway. No se desplegó el JAR en server02.
- La revisión automática rechazó el primer diseño por posible migración; la alternativa explícitamente read-only fue aprobada y ejecutada. No queda bloqueo de aprobación para esta adaptación.
- T03 sigue PENDING: faltan tablas, migraciones y pruebas de restricciones/concurrencia. La conexión disponible permite diseñar para 9.6, pero no sustituye un entorno aislado de pruebas ni prueba soporte completo del motor.
## E10 — Cierre T02 — 2026-10-26 11:58 (America/Mexico_City) ## E10 — Cierre T02 — 2026-10-26 11:58 (America/Mexico_City)
- Estado: DONE. 14 operaciones REST OpenAPI 3.1.0, DTOs, schema DSL 2020-12, ejemplos de resultados normalizados y fixtures contractuales completos para esta fase. - Estado: DONE. 14 operaciones REST OpenAPI 3.1.0, DTOs, schema DSL 2020-12, ejemplos de resultados normalizados y fixtures contractuales completos para esta fase.

View File

@ -4,13 +4,14 @@
Requiere Docker con contenedores Linux y Compose v2. La imagen compila con JDK 21 y ejecuta con JRE 21; no requiere Java/Maven en el anfitrión. PostgreSQL y el proveedor JWT son externos. Requiere Docker con contenedores Linux y Compose v2. La imagen compila con JDK 21 y ejecuta con JRE 21; no requiere Java/Maven en el anfitrión. PostgreSQL y el proveedor JWT son externos.
1. Crear base y usuario en PostgreSQL 17. Permitir conexión desde Docker según firewall, listen_addresses y pg_hba.conf del servidor. 1. Usar la base externa existente. Actualmente server02:30432/orquestador ejecuta PostgreSQL 9.6.2 y requiere el perfil postgres96; se conserva PostgreSQL 17 como alternativa futura. Permitir conexión desde Docker según firewall, listen_addresses y pg_hba.conf del servidor.
2. Copiar `.env.example` a `.env`, sin sobrescribir uno ya configurado. 2. Copiar `.env.example` a `.env`, sin sobrescribir uno ya configurado.
3. Completar DB_URL, DB_USERNAME, DB_PASSWORD, JWT_ISSUER_URI, JWT_JWK_SET_URI y JWT_AUDIENCE. 3. Completar DB_URL, DB_USERNAME, DB_PASSWORD, JWT_ISSUER_URI, JWT_JWK_SET_URI y JWT_AUDIENCE.
| Variable | Uso | | Variable | Uso |
|---|---| |---|---|
| DB_URL | JDBC de la base externa: jdbc:postgresql://db.interna:5432/orquestador | | DB_URL | JDBC de la base externa: jdbc:postgresql://db.interna:5432/orquestador |
| SPRING_PROFILES_ACTIVE | postgres96 para la instancia disponible; selecciona PostgreSQLLegacyDialect de Hibernate |
| DB_USERNAME / DB_PASSWORD | Credenciales del usuario de la base existente | | DB_USERNAME / DB_PASSWORD | Credenciales del usuario de la base existente |
| JWT_ISSUER_URI | Issuer exacto de los tokens | | JWT_ISSUER_URI | Issuer exacto de los tokens |
| JWT_JWK_SET_URI | Endpoint JWKS correspondiente, accesible desde Docker | | JWT_JWK_SET_URI | Endpoint JWKS correspondiente, accesible desde Docker |
@ -54,6 +55,8 @@ Estos comandos no administran la base externa. Flyway permanece habilitado y apl
## Ejecución desde el IDE ## Ejecución desde el IDE
Para el servidor actual configurar `DB_URL=jdbc:postgresql://server02:30432/orquestador`, `DB_USERNAME=pgadmin` y `SPRING_PROFILES_ACTIVE=postgres96`; la contraseña sólo en el entorno local. El argumento de perfil local del ejemplo siguiente debe reemplazarse por postgres96 cuando se use PostgreSQL 9.6.
Configurar JDK 21 y las seis variables DB/JWT en la sesión o Run Configuration. Spring Boot no importa `.env` automáticamente fuera de Compose. Configurar JDK 21 y las seis variables DB/JWT en la sesión o Run Configuration. Spring Boot no importa `.env` automáticamente fuera de Compose.
```powershell ```powershell
@ -63,6 +66,18 @@ Configurar JDK 21 y las seis variables DB/JWT en la sesión o Run Configuration.
## Diagnóstico ## Diagnóstico
### Prueba de compatibilidad con PostgreSQL 9.6
Con JDK 21 y las seis variables DB/JWT exportadas, ejecutar:
```powershell
.\mvnw.cmd clean verify -Ppostgres96-check
```
La prueba arranca el checkout local en 127.0.0.1 con puerto aleatorio y cierra el contexto al terminar. Fuerza PostgreSQL default_transaction_read_only=on, desactiva el inicializador automático Flyway y SQL init sólo en la prueba, conserva ddl-auto=validate y ejecuta Flyway.validate() sin crear schemas ni migrar. Comprueba versión 9.6, dialecto legacy, health/readiness/liveness UP y 401 sin token. No corre en el build normal ni depende de Docker. No sustituye pruebas de migraciones, DML/concurrencia ni Testcontainers de T03.
Hibernate community-dialects se alinea al BOM (7.4.13.Final). Flyway 12.4.0 detecta 9.6 y valida; informa que esa versión queda fuera de soporte comunitario de Redgate. La compatibilidad verificada se limita al arranque/conexión actual, todavía sin entidades ni migraciones de negocio.
Para automatizar la comprobación del despliegue con JDK 21: Para automatizar la comprobación del despliegue con JDK 21:
```powershell ```powershell

View File

@ -0,0 +1,5 @@
# Compatibilidad explícita para la instancia PostgreSQL 9.6 del entorno actual.
# Flyway y ddl-auto=validate conservan su configuración normal.
spring:
jpa:
database-platform: org.hibernate.community.dialect.PostgreSQLLegacyDialect

View File

@ -0,0 +1,66 @@
package com.organizacion.compatibility;
import com.organizacion.orchestrator.OrchestratorApplication;
import jakarta.persistence.EntityManagerFactory;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.flywaydb.core.Flyway;
import javax.sql.DataSource;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import tools.jackson.databind.json.JsonMapper;
import static org.junit.jupiter.api.Assertions.*;
/** Explicit integration probe; starts this checkout against an external DB without writes. */
class Postgres96CompatibilityProbe {
@Test
void applicationStartsAndServesHealthAgainstPostgres96WithoutWrites() throws Exception {
for (String name : new String[]{"DB_URL", "DB_USERNAME", "DB_PASSWORD", "JWT_ISSUER_URI", "JWT_JWK_SET_URI", "JWT_AUDIENCE"}) {
assertNotNull(System.getenv(name), "Missing environment variable: " + name);
assertFalse(System.getenv(name).isBlank(), "Empty environment variable: " + name);
}
var app = new SpringApplication(OrchestratorApplication.class);
try (var context = app.run(
"--spring.profiles.active=postgres96",
"--spring.flyway.enabled=false",
"--spring.jpa.hibernate.ddl-auto=validate",
"--spring.sql.init.mode=never",
"--server.address=127.0.0.1", "--server.port=0",
"--spring.datasource.hikari.data-source-properties.options=-c default_transaction_read_only=on",
"--spring.datasource.hikari.maximum-pool-size=2",
"--spring.datasource.hikari.connection-timeout=10000",
"--spring.datasource.hikari.data-source-properties.connectTimeout=10",
"--spring.datasource.hikari.data-source-properties.socketTimeout=10")) {
try (var connection = context.getBean(DataSource.class).getConnection();
var statement = connection.createStatement();
var result = statement.executeQuery("select current_setting('server_version_num')::int, current_setting('default_transaction_read_only')")) {
assertTrue(result.next());
assertTrue(result.getInt(1) >= 90600 && result.getInt(1) < 100000, "This probe targets PostgreSQL 9.6");
assertEquals("on", result.getString(2));
}
// No migration initializer exists in this probe. Only validate() is invoked,
// using the same read-only pool; schema creation is explicitly forbidden.
Flyway.configure().dataSource(context.getBean(DataSource.class))
.locations("classpath:db/migration").createSchemas(false).load().validate();
var sessionFactory = context.getBean(EntityManagerFactory.class).unwrap(SessionFactoryImplementor.class);
assertEquals("org.hibernate.community.dialect.PostgreSQLLegacyDialect",
sessionFactory.getJdbcServices().getDialect().getClass().getName());
int port = Integer.parseInt(context.getEnvironment().getRequiredProperty("local.server.port"));
var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
for (String endpoint : new String[]{"health", "health/readiness", "health/liveness"}) {
var request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + port + "/actuator/" + endpoint))
.timeout(Duration.ofSeconds(10)).GET().build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals(200, response.statusCode(), endpoint);
assertEquals("\"UP\"", JsonMapper.builder().build().readTree(response.body()).path("status").toString());
}
var protectedRequest = HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + port + "/api/v1/requests"))
.timeout(Duration.ofSeconds(10)).GET().build();
assertEquals(401, client.send(protectedRequest, HttpResponse.BodyHandlers.discarding()).statusCode());
}
}
}

View File

@ -9,3 +9,5 @@ Sólo efectúa GET sin credenciales y no modifica datos. No demuestra JWT válid
El build normal/CI no contacta servidores privados: este smoke requiere un despliegue ya iniciado. El build normal/CI no contacta servidores privados: este smoke requiere un despliegue ya iniciado.
T03 incorpora Testcontainers PostgreSQL; nunca sustituir concurrencia o JSONB por H2. T03 incorpora Testcontainers PostgreSQL; nunca sustituir concurrencia o JSONB por H2.
No omitir integraciones silenciosamente cuando Docker no esté disponible. No omitir integraciones silenciosamente cuando Docker no esté disponible.
Postgres96CompatibilityProbe (paquete com.organizacion.compatibility) se ejecuta únicamente con -Ppostgres96-check y variables DB/JWT externas. Arranca el checkout con PostgreSQL 9.6 en modo sólo lectura, valida dialecto/Flyway y salud. No cambia el comportamiento de migración del servicio normal ni sustituye T03.