feat: initial commit - cybercore signer desktop agent

This commit is contained in:
Claudecio Martins
2026-10-11 08:20:24 -03:00
commit ccfa358f97
206 changed files with 23952 additions and 0 deletions
+162
View File
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>br.com.cybercore.signer</groupId>
<artifactId>cybercore-signer-parent</artifactId>
<version>0.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cybercore-app</artifactId>
<packaging>jar</packaging>
<name>CyberCore Signer :: Application</name>
<description>Módulo executável desktop, ciclo de vida da aplicação, shutdown hooks e empacotamento nativo.</description>
<dependencies>
<dependency>
<groupId>br.com.cybercore.signer</groupId>
<artifactId>cybercore-core</artifactId>
</dependency>
<dependency>
<groupId>br.com.cybercore.signer</groupId>
<artifactId>cybercore-ui</artifactId>
</dependency>
<!-- JavaFX Neutro -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
</dependency>
<!-- JavaFX Nativos Windows (para execução direta em ambiente Windows) -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
<classifier>win</classifier>
</dependency>
<!-- JavaFX Nativos Linux (para execução direta em ambiente Linux) -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>${javafx.version}</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<!-- Testes de Arquitetura -->
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<configuration>
<mainClass>br.com.cybercore.signer.app.CyberCoreSignerApplication</mainClass>
</configuration>
</plugin>
<!-- Geração de Fat JAR executável autocontido -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>cybercore-signer</finalName>
<shadedArtifactAttached>false</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>br.com.cybercore.signer.app.CyberCoreSignerApplication</mainClass>
<manifestEntries>
<Implementation-Title>CyberCore Signer</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Vendor>CyberCore</Implementation-Vendor>
</manifestEntries>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>module-info.class</exclude>
<exclude>META-INF/versions/**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,144 @@
package br.com.cybercore.signer.app;
import br.com.cybercore.signer.core.diagnostics.DiagnosticReport;
import br.com.cybercore.signer.core.diagnostics.DiagnosticService;
import br.com.cybercore.signer.core.crypto.SigningService;
import br.com.cybercore.signer.core.protocol.CcspServer;
import br.com.cybercore.signer.core.provider.CertificateManager;
import br.com.cybercore.signer.ui.CyberCoreDesktopApplication;
import javafx.application.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.GraphicsEnvironment;
/**
* Ponto de entrada (Main Class) e bootstrap do agente CyberCore Signer.
*/
public class CyberCoreSignerApplication {
private static final Logger logger = LoggerFactory.getLogger(CyberCoreSignerApplication.class);
private static boolean developmentMode = false;
private static boolean headlessMode = false;
private static boolean noWaitMode = false;
private static volatile CcspServer runningServer = null;
public static CcspServer getRunningServer() {
return runningServer;
}
public static void stopServer() {
if (runningServer != null) {
runningServer.stop();
runningServer = null;
}
}
public static void main(String[] args) {
parseArguments(args);
printBanner();
logger.info("Inicializando CyberCore Signer v0.1.0...");
if (developmentMode) {
logger.warn("=========================================================");
logger.warn(" MODO DE DESENVOLVIMENTO ATIVADO (--dev)");
logger.warn(" Logs detalhados ativos. Operação com certificados reais.");
logger.warn("=========================================================");
}
DiagnosticService diagnosticService = new DiagnosticService();
DiagnosticReport report = diagnosticService.runDiagnostic();
logger.info("Ambiente verificado: OS={} {} ({}), Java={} ({})",
report.osName(), report.osVersion(), report.osArch(),
report.javaVersion(), report.javaVendor());
if (!report.cryptoEngineOk()) {
logger.error("ALERTA CRÍTICO: Engine criptográfica JCA/JCE não está totalmente operacional!");
}
// Se o ambiente tiver suporte gráfico e não for headless forçado, abre a interface JavaFX
boolean isHeadless = headlessMode || GraphicsEnvironment.isHeadless();
if (isHeadless) {
logger.info("Executando em modo console / headless (sem interface gráfica).");
startHeadlessServer();
} else {
try {
logger.info("Iniciando interface gráfica desktop...");
CyberCoreDesktopApplication.setDevelopmentMode(developmentMode);
Application.launch(CyberCoreDesktopApplication.class, args);
} catch (Throwable t) {
logger.warn("Não foi possível inicializar ambiente gráfico ({}). Continuando em modo console.", t.getMessage());
startHeadlessServer();
}
}
logger.info("CyberCore Signer finalizado.");
}
private static void startHeadlessServer() {
try {
CertificateManager certManager = CertificateManager.createDefault();
if (developmentMode) {
logger.info("Modo de desenvolvimento ativo (com certificados reais do sistema).");
}
SigningService signingService = new SigningService(certManager);
runningServer = new CcspServer(certManager, signingService, null);
runningServer.start();
logger.info("Servidor local CCSP/1 pronto em http://127.0.0.1:{}", runningServer.getPort());
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
logger.info("Encerrando servidor local CCSP/1...");
stopServer();
}));
// Mantém processo vivo para atender requisições web, a menos que em modo no-wait
if (!noWaitMode) {
Thread.currentThread().join();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
logger.error("Falha ao inicializar servidor local CCSP/1 no modo console: {}", e.getMessage(), e);
}
}
private static void parseArguments(String[] args) {
if (args != null) {
for (String arg : args) {
if ("--dev".equalsIgnoreCase(arg) || "-dev".equalsIgnoreCase(arg)) {
developmentMode = true;
} else if ("--headless".equalsIgnoreCase(arg) || "-headless".equalsIgnoreCase(arg)
|| "--cli".equalsIgnoreCase(arg)) {
headlessMode = true;
} else if ("--no-wait".equalsIgnoreCase(arg) || "-no-wait".equalsIgnoreCase(arg)
|| "--test".equalsIgnoreCase(arg)) {
noWaitMode = true;
}
}
}
}
public static boolean isDevelopmentMode() {
return developmentMode;
}
public static boolean isHeadlessMode() {
return headlessMode;
}
private static void printBanner() {
System.out.println("""
============================================================
____ _ ____
/ ___| _ _ __| | ___ _ __ / ___|___ _ __ ___
| | | | | |/ _` | / _ \\| '__| | | / _ \\ | '__|/ _ \\
| |___ | |_| | (_| || __/| | | |__| (_) || | | __/
\\____| \\__, |\\__,_| \\___||_| \\____\\___/ |_| \\___|
|___/
SIGNER AGENT v0.1.0
============================================================
""");
}
}
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
<logger name="br.com.cybercore.signer" level="DEBUG" />
</configuration>
@@ -0,0 +1,37 @@
package br.com.cybercore.signer.app;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
class ArchitectureTest {
private final JavaClasses importedClasses = new ClassFileImporter()
.importPackages("br.com.cybercore.signer");
@Test
@DisplayName("O módulo Core não deve depender de classes dos pacotes UI ou App")
void coreShouldNotDependOnUiOrApp() {
ArchRule rule = noClasses()
.that().resideInAPackage("br.com.cybercore.signer.core..")
.should().dependOnClassesThat()
.resideInAnyPackage("br.com.cybercore.signer.ui..", "br.com.cybercore.signer.app..");
rule.check(importedClasses);
}
@Test
@DisplayName("O módulo Core não deve conter dependências de bibliotecas JavaFX")
void coreShouldNotDependOnJavaFx() {
ArchRule rule = noClasses()
.that().resideInAPackage("br.com.cybercore.signer.core..")
.should().dependOnClassesThat()
.resideInAPackage("javafx..");
rule.check(importedClasses);
}
}
@@ -0,0 +1,20 @@
package br.com.cybercore.signer.app;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThatCode;
class CyberCoreSignerApplicationTest {
@Test
@DisplayName("Deve inicializar a aplicação com argumentos sem erros")
void shouldBootstrapWithoutErrors() {
try {
assertThatCode(() -> CyberCoreSignerApplication.main(new String[]{"--dev", "--headless", "--no-wait"}))
.doesNotThrowAnyException();
} finally {
CyberCoreSignerApplication.stopServer();
}
}
}