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
@@ -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();
}
}
}