From 1f0890300d3f81879f312cb65c865ec753d1aadb Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Thu, 9 Apr 2026 10:24:55 +0200 Subject: [PATCH 1/2] bump: python ver fix: race condition in SecureMemory global vs. client instance - no more global state mutation --- nomyo/SecureCompletionClient.py | 13 +++++++------ nomyo/__init__.py | 2 +- nomyo/nomyo.py | 14 ++++---------- pyproject.toml | 4 +--- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/nomyo/SecureCompletionClient.py b/nomyo/SecureCompletionClient.py index 4892937..66cd94a 100644 --- a/nomyo/SecureCompletionClient.py +++ b/nomyo/SecureCompletionClient.py @@ -4,14 +4,13 @@ from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.primitives.kdf.hkdf import HKDF # Setup module logger logger = logging.getLogger(__name__) # Import secure memory module try: - from .SecureMemory import secure_bytearray, get_memory_protection_info, _get_secure_memory + from .SecureMemory import secure_bytearray, _get_secure_memory _SECURE_MEMORY_AVAILABLE = True except ImportError: _SECURE_MEMORY_AVAILABLE = False @@ -77,19 +76,21 @@ class SecureCompletionClient: - Response parsing """ - def __init__(self, router_url: str = "https://api.nomyo.ai:12435", allow_http: bool = False): + def __init__(self, router_url: str = "https://api.nomyo.ai:12435", allow_http: bool = False, secure_memory: bool = True): """ Initialize the secure completion client. Args: router_url: Base URL of the NOMYO Router (must use HTTPS for production) allow_http: Allow HTTP connections (ONLY for local development, never in production) + secure_memory: Whether to use secure memory operations for this instance. """ self.router_url = router_url.rstrip('/') self.private_key = None self.public_key_pem = None self.key_size = 4096 # RSA key size self.allow_http = allow_http # Store for use in fetch_server_public_key + self._use_secure_memory = _SECURE_MEMORY_AVAILABLE and secure_memory # Validate HTTPS for security if not self.router_url.startswith("https://"): @@ -122,7 +123,7 @@ class SecureCompletionClient: - Rotate keys regularly - Store keys outside the project directory in production """ - if not _SECURE_MEMORY_AVAILABLE or not self.private_key: + if not self._use_secure_memory or not self.private_key: return try: @@ -416,7 +417,7 @@ class SecureCompletionClient: aes_key = secrets.token_bytes(32) # 256-bit key try: - if _SECURE_MEMORY_AVAILABLE: + if self._use_secure_memory: with secure_bytearray(payload_json) as protected_payload: with secure_bytearray(aes_key) as protected_aes_key: return await self._do_encrypt( @@ -500,7 +501,7 @@ class SecureCompletionClient: ) # Use secure memory to protect AES key and decrypted plaintext - if _SECURE_MEMORY_AVAILABLE: + if self._use_secure_memory: with secure_bytearray(aes_key) as protected_aes_key: ciphertext = base64.b64decode(package["encrypted_payload"]["ciphertext"]) nonce = base64.b64decode(package["encrypted_payload"]["nonce"]) diff --git a/nomyo/__init__.py b/nomyo/__init__.py index 6f19d3c..1463d19 100644 --- a/nomyo/__init__.py +++ b/nomyo/__init__.py @@ -51,6 +51,6 @@ try: except ImportError: pass -__version__ = "0.1.1" +__version__ = "0.2.1" __author__ = "NOMYO AI" __license__ = "Apache-2.0" diff --git a/nomyo/nomyo.py b/nomyo/nomyo.py index a7068b6..7787c0a 100644 --- a/nomyo/nomyo.py +++ b/nomyo/nomyo.py @@ -4,9 +4,9 @@ import uuid from typing import Dict, Any, List, Optional from .SecureCompletionClient import SecureCompletionClient -# Import secure memory module for configuration +# Check if secure memory module is available (used only for the user-facing warning) try: - from .SecureMemory import disable_secure_memory, enable_secure_memory + from . import SecureMemory as _ # noqa: F401 _SECURE_MEMORY_AVAILABLE = True except ImportError: _SECURE_MEMORY_AVAILABLE = False @@ -69,20 +69,14 @@ class SecureChatCompletion: key_dir: Directory to load/save RSA keys. If None, ephemeral keys are generated in memory for this session only. """ - self.client = SecureCompletionClient(router_url=base_url, allow_http=allow_http) + self.client = SecureCompletionClient(router_url=base_url, allow_http=allow_http, secure_memory=secure_memory) self._keys_initialized = False self._keys_lock = asyncio.Lock() self.api_key = api_key self._key_dir = key_dir self._secure_memory_enabled = secure_memory - # Configure secure memory if available - if _SECURE_MEMORY_AVAILABLE: - if secure_memory: - enable_secure_memory() - else: - disable_secure_memory() - elif secure_memory: + if secure_memory and not _SECURE_MEMORY_AVAILABLE: import warnings warnings.warn( "Secure memory requested but not available. " diff --git a/pyproject.toml b/pyproject.toml index 08bde43..d423e78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,8 +17,6 @@ classifiers = [ "Intended Audience :: Information Technology", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -27,7 +25,7 @@ classifiers = [ "Topic :: Communications :: Chat", "Operating System :: OS Independent", ] -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [ "anyio==4.12.0", "certifi==2025.11.12", From 36b4c00e4d29481ba529579916974c241f34f557 Mon Sep 17 00:00:00 2001 From: alpha nerd Date: Thu, 9 Apr 2026 13:02:15 +0200 Subject: [PATCH 2/2] test: all test pass, ready for deployment --- nomyo/__init__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nomyo/__init__.py b/nomyo/__init__.py index 1463d19..9c4d160 100644 --- a/nomyo/__init__.py +++ b/nomyo/__init__.py @@ -51,6 +51,6 @@ try: except ImportError: pass -__version__ = "0.2.1" +__version__ = "0.2.2" __author__ = "NOMYO AI" __license__ = "Apache-2.0" diff --git a/pyproject.toml b/pyproject.toml index d423e78..3abe372 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "nomyo" -version = "0.2.1" +version = "0.2.2" description = "OpenAI-compatible secure chat client with end-to-end encryption for NOMYO Inference Endpoints" authors = [ {name = "NOMYO.AI", email = "ichi@nomyo.ai"},