# nomyo4J — Agent Instructions Java 25 port of the NOMYO Python client. Hybrid encryption (RSA-4096 + AES-256-GCM) for secure API communication. ## Build & Run ``` mvn compile # Java 25, Lombok annotation processor mvn test # JUnit Jupiter 5.12.1, @Order enforced mvn test -Dtest=ClassName # single test class ``` ## Architecture - **`SecureCompletionClient`** — low-level client: key mgmt, HTTP, encryption, decryption - **`SecureChatCompletion`** — high-level OpenAI-compatible surface (`create()`, `acreate()`) - **`Constants`** — all protocol/crypto constants (version, algorithms, timeouts) - **`SecureMemory`** — Java 25 FFM `SecureBuffer` for locked/zeroed memory. Use `try-with-resources` for all sensitive cryptographic material (AES keys, private RSA keys, IVs, nonce, plaintext bytes) to guarantee zeroing on scope exit. - **`errors/`** — 9 exception classes, all `extends Exception` (checked), all `extends APIError` - **`util/`** — `Pass2Key` (PBKDF2 + AES-GCM), `PEMConverter`, `Splitter` - **`EncryptedRequest`** — wire format model with Gson `@SerializedName` annotations ## Stubbed methods (check before implementing) - `SecureMemory.lock()` — always returns `false` (FFM doesn't support locking) - `SecureMemory.unlock()` — always returns `false` - `SecureMemory.initMemoryLocking()` — always returns `false` ## Security — SecureBuffer Usage - **High security application** — all sensitive cryptographic material must use `SecureBuffer` with `try-with-resources` - Wrap AES key bytes, private RSA key bytes, IVs, nonces, and plaintext bytes in `SecureBuffer` - Pattern: `try (SecureBuffer buf = SecureMemory.secureByteArray(sensitiveBytes)) { ... }` - Never store raw `byte[]` for sensitive material on the heap longer than necessary - After encryption/decryption, zero and discard AES keys and plaintext immediately ## Dependencies - **Gson** (2.13.2) — JSON serialization, in `pom.xml` - **Lombok** (1.18.44, `provided` scope) — annotation processor configured in maven-compiler-plugin - **JUnit Jupiter** (5.12.1, `test` scope) - **Maven Surefire** (3.5.0) ## Key files - `TRANSLATION_REFERENCE.md` — **primary documentation**. Cross-language spec from Python reference. Read before implementing any method. - `client_keys/` — contains real RSA keys. **Gitignored.** Do not commit. - `Main.java` — entry point is `static void main()` — **not `public static void main(String[])`**. Cannot run standalone. ## Conventions - Package: `ai.nomyo` - Lombok: `@Getter` on fields, `@Setter` on static flags - Tests: `@TestMethodOrder(OrderAnnotation.class)`, `@DisplayName` on every test - Error classes: checked exceptions with `statusCode` and `errorDetails` (immutable, via `Collections.unmodifiableMap`) - Key files: `PosixFilePermissions.fromString("rw-------")` for private, `"rw-r--r--"` for public - RSA: 4096-bit, exponent 65537, OAEP-SHA256 (MGF1 with SHA-256) - Protocol constants in `Constants.java` — marked "never change" (downgrade detection) - `SecureChatCompletion.acreate()` is a sync alias, not async — delegates to `create()` - Streaming is explicitly rejected with `IllegalArgumentException` - `SecureCompletionClient.ValueError` — inner class, maps to Python `ValueError` - Retry: 429/500/502/503/504 + network errors, exponential backoff 2^(attempt-1)s, default 2 retries - All HTTP endpoints use `application/octet-stream` content type for encrypted payloads