package ar.com.companeros.runtime; import java.nio.file.*; import java.nio.file.attribute.PosixFilePermission; import java.util.*; import java.util.function.Supplier; /** Credencial del servicio confiable. El modelo y la DSL nunca reciben esta ruta ni su contenido. */ public final class ApiCredential implements Supplier { private final String key; public ApiCredential(Path configRoot) { key = load(configRoot.toAbsolutePath().normalize().resolve("secrets").resolve("openai.key")); } @Override public String get() { return key; } private static String load(Path file) { String environment = System.getenv("OPENAI_API_KEY"); if (environment != null && !environment.isBlank()) return environment.trim(); try { if (!Files.isRegularFile(file, LinkOption.NOFOLLOW_LINKS) || Files.size(file) > 512 || Files.isSymbolicLink(file.getParent())) return ""; if (Files.getFileStore(file).supportsFileAttributeView("posix")) { Files.setPosixFilePermissions(file.getParent(), EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE)); Files.setPosixFilePermissions(file, EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)); } String key = Files.readString(file, java.nio.charset.StandardCharsets.UTF_8).trim(); return key.matches("sk-[A-Za-z0-9_-]{20,500}") ? key : ""; } catch (java.io.IOException | SecurityException unavailable) { return ""; } } }