2026-04-23 13:36:46 +02:00
|
|
|
# nomyo4J — Agent Instructions
|
|
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
Java 25 port of the NOMYO Python client. Hybrid encryption (RSA-4096 + AES-256-GCM) for secure API communication.
|
2026-04-23 13:36:46 +02:00
|
|
|
|
|
|
|
|
## 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
|
2026-04-29 16:59:33 +02:00
|
|
|
- **`errors/`** — 9 exception classes, all `extends Exception` (checked), all `extends APIError`
|
2026-04-23 13:36:46 +02:00
|
|
|
- **`util/`** — `Pass2Key` (PBKDF2 + AES-GCM), `PEMConverter`, `Splitter`
|
2026-04-29 16:59:33 +02:00
|
|
|
- **`EncryptedRequest`** — wire format model with Gson `@SerializedName` annotations
|
2026-04-23 13:36:46 +02:00
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
## Stubbed methods (check before implementing)
|
2026-04-23 13:36:46 +02:00
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
- `SecureMemory.lock()` — always returns `false` (FFM doesn't support locking)
|
|
|
|
|
- `SecureMemory.unlock()` — always returns `false`
|
|
|
|
|
- `SecureMemory.initMemoryLocking()` — always returns `false`
|
2026-04-23 13:36:46 +02:00
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
## Dependencies
|
2026-04-23 13:36:46 +02:00
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
- **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)
|
2026-04-23 13:36:46 +02:00
|
|
|
|
|
|
|
|
## Key files
|
|
|
|
|
|
2026-04-29 16:59:33 +02:00
|
|
|
- `TRANSLATION_REFERENCE.md` — **primary documentation**. Cross-language spec from Python reference. Read before implementing any method.
|
2026-04-23 13:36:46 +02:00
|
|
|
- `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
|
2026-04-29 16:59:33 +02:00
|
|
|
- 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
|