Saltar al contenido principal
Versión: v0.1.5

platform-core

platform-core es un conjunto de módulos Java/Spring Boot publicados como artefactos versionados que los proyectos de dominio de EchoTechs consumen como dependencia. No se clona este repositorio — se agregan las coordenadas Maven al build.gradle.kts (o pom.xml) del proyecto nuevo.

El objetivo es que un proyecto nuevo no vuelva a reimplementar autenticación, autorización multi-tenant, almacenamiento de archivos, máquina de estados, notificaciones ni reportes.

Coordenadas y publicación​

Todos los módulos se publican bajo el grupo dev.echotechs.core en el Nexus interno:

Grupodev.echotechs.core
Última release0.1.0 (https://github.com/echotech-sv/echotechs-core/releases/tag/v0.1.0)
Versión en desarrollo en main0.1.0-SNAPSHOT
Repo de releaseshttps://nexus.lab.echotechs.net/repository/maven-releases
Repo de snapshotshttps://nexus.lab.echotechs.net/repository/maven-snapshots

El repositorio de destino se elige automáticamente según la versión — publicar un GitHub Release con tag vX.Y.Z la manda a maven-releases con esa versión exacta; un push a main sin release sigue publicando 0.1.0-SNAPSHOT a maven-snapshots (buildSrc/src/main/kotlin/echotechs.java-library-conventions.gradle.kts). La publicación depende de check, así que un módulo cuyos tests fallan no llega a Nexus.

build.gradle.kts de tu proyecto
repositories {
mavenCentral()
maven {
// maven-public agrupa releases + snapshots + el proxy de Maven Central — apuntá siempre acá,
// no directo a maven-releases, así el mismo bloque sirve cuando publiquen una versión nueva.
url = uri("https://nexus.lab.echotechs.net/repository/maven-public")
credentials {
username = System.getenv("NEXUS_USERNAME")
password = System.getenv("NEXUS_PASSWORD")
}
}
}

dependencies {
implementation("dev.echotechs.core:core-authz:0.1.0")
}

Los nueve módulos​

MóduloQué resuelveDepende de
core-persistenceBase JPA portable Postgres/Oracle: CoreEntity y el esquema core—
core-webErrores uniformes, paginación, convención MapStruct—
core-authIdentidad: JWT + refresh de usuario, client credentials, API keys, TenantContextcore-web, core-persistence
core-authzAutorización con OpenFGA: @RequiresPermission, tuplascore-auth
core-storageArchivos en S3/MinIO con URLs prefirmadascore-auth, core-authz, core-persistence
core-workflowMáquina de estados con auditoría y eventoscore-auth, core-persistence
core-notificationsEnvío de email con plantillas Thymeleaf—
core-reportingPDF desde plantillas, subido vía core-storagecore-storage
core-configCatálogo de configuración editable en runtimecore-auth, core-authz, core-persistence

Las dependencias se declaran como api(...), así que son transitivas: agregar core-storage arrastra core-auth, core-authz y core-persistence automáticamente.

Stack fijado​

Del gradle/libs.versions.toml y del convention plugin:

  • Java 25 (toolchain), Spring Boot 4.1.0 sobre Spring Framework 7
  • Gradle con Kotlin DSL y catálogo de versiones centralizado
  • Jackson 3 (tools.jackson.core:jackson-databind) — no Jackson 2; Spring Boot 4.1 autoconfigura el ObjectMapper de Jackson 3
  • Liquibase para migraciones, Hibernate/Spring Data JPA para acceso a datos
  • OpenFGA SDK 0.9.9 (crudo, no el starter — ver core-authz)

Convención de configuración (spec 1.10)​

Cada módulo expone sus propias propiedades bajo su propio prefijo echotechs.* (echotechs.storage.*, echotechs.authz.*, echotechs.auth.jwt.*) — nunca se reinventan prefijos para lo que Spring ya resuelve de forma estándar (spring.datasource.*, spring.mail.*).

  • spring-boot-configuration-processor está en el convention plugin compartido — el IDE autocompleta cualquier echotechs.* con tooltips, igual que con las propiedades nativas de Spring.
  • Las propiedades genuinamente obligatorias (sin default sensato) fallan rápido: JwtProperties.secret, OpenFgaProperties.apiUrl, StorageProperties.bucket están anotadas @Validated + @NotBlank — si falta una, el contexto no arranca y el error nombra exactamente esa propiedad, en vez de un NullPointerException la primera vez que se usa. core-notifications es la excepción deliberada — ver la nota en core-notifications.
Gradle 8.14 no arranca bajo JDK 25

El wrapper de este repo necesita un JDK 21 como launcher y el JDK 25 sólo como toolchain. Todos los workflows de CI y el Dockerfile del reference-app usan ese doble JDK:

./gradlew build --no-daemon -Porg.gradle.java.installations.paths="$JAVA_HOME_25_ARM64" -Porg.gradle.java.installations.auto-detect=false

Cómo leer esta documentación​

Cada página de módulo documenta lo que el código hace hoy, con firmas extraídas del fuente y ejemplos adaptados de los tests de integración reales de cada módulo. Donde el código diverge de platform-core-spec.md, la diferencia está anotada al final de la página en Notas de implementación.

Dos páginas de referencia complementan eso: