|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to `nullrun-sdk` will be documented here. |
| 4 | + |
| 5 | +Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) |
| 6 | +Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html) |
| 7 | + |
| 8 | +--- |
| 9 | + |
| 10 | +## [Unreleased] |
| 11 | + |
| 12 | +### Added |
| 13 | + |
| 14 | +- **Async Policy Cache**: `AsyncTransport` now uses `PolicyCache` for CACHED fallback mode. Previously the async transport always fell back to PERMISSIVE when gateway was unreachable. Now it caches successful execute decisions and uses them when gateway is unavailable. |
| 15 | +- **Custom Sensitive Tools API**: Added `add_sensitive_tool()`, `remove_sensitive_tool()`, `register_sensitive_tools()`, and `get_sensitive_tools()` methods to `NullRunRuntime`. Users can now register custom tools as sensitive requiring strict mode enforcement. |
| 16 | +- **`NullRunBlockedException.tool_name` attribute** (FIX-5): The `tool_name` |
| 17 | + kwarg is now a first-class attribute on `NullRunBlockedException` |
| 18 | + (and its subclasses `LoopDetectedException`, etc.) instead of being |
| 19 | + absorbed into `**details`. Cookbook examples that read `exc.tool_name` |
| 20 | + no longer raise `AttributeError`. Backwards-compatible: `tool_name` |
| 21 | + defaults to `None` and does not appear in `exc.details` when unset. |
| 22 | + The stringified exception now includes `tool={name}` when set. |
| 23 | + |
| 24 | +### Fixed |
| 25 | + |
| 26 | +- **SDK silent runtime fallback removed** (FIX-4): `_get_or_create_runtime` |
| 27 | + in `nullrun.decorators` no longer wraps `NullRunRuntime.get_instance()` |
| 28 | + in a `try/except Exception` that rebuilds a no-arg `NullRunRuntime()`. |
| 29 | + In 0.3.0 (T3-S2) the no-arg constructor requires `api_key` and raises |
| 30 | + `NullRunAuthenticationError` — so the fallback swallowed the auth |
| 31 | + error from `get_instance()` only to crash with the same error from |
| 32 | + the fallback path itself. After this fix, the auth error propagates |
| 33 | + cleanly to the first `@protect` invocation, mirroring the fail-loud |
| 34 | + contract of `nullrun.init()`. Aligns with the T3-S2 invariant that |
| 35 | + the SDK has no local mode: a missing API key is a hard error, not a |
| 36 | + silent allow-all. |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +## [0.3.0] — 2026-06-15 |
| 41 | + |
| 42 | +### Breaking |
| 43 | + |
| 44 | +- **No-api-key init now raises** (T3-S2): `nullrun.init()` and |
| 45 | + `NullRunRuntime(...)` without an `api_key` (and with `NULLRUN_API_KEY` |
| 46 | + unset) now raise `NullRunAuthenticationError` instead of falling back |
| 47 | + to a `NullRunNoop` stub. The previous silent fallback silently |
| 48 | + bypassed every backend gate (budget, policy, control plane) — a real |
| 49 | + safety hole in production. **Action required:** ensure |
| 50 | + `api_key="nr_live_..."` is passed to `init()` (or `NULLRUN_API_KEY` |
| 51 | + is set) in every entry point. The `0.2.0` deprecation warning has |
| 52 | + been removed; the new behavior is hard. |
| 53 | +- **`local_mode` field removed**: The auto-derived `local_mode` flag |
| 54 | + on `NullRunRuntime` is gone. The `is_local_mode` property and the |
| 55 | + `NullRunNoop` / `NullRunNoopBreaker` / `_NullContext` classes are |
| 56 | + deleted (`nullrun.noop` module removed). All call sites that read |
| 57 | + `runtime.local_mode` will see `AttributeError` — there is no |
| 58 | + migration path because the field no longer has meaning. Code paths |
| 59 | + that previously branched on `local_mode` now always go through the |
| 60 | + cloud runtime (auth + policy fetch + control plane). |
| 61 | + |
| 62 | +### Removed |
| 63 | + |
| 64 | +- **Legacy Breaker exports** (T9): The 7 legacy re-exports |
| 65 | + (`nullrun.BreakerError`, `nullrun.CostLimitExceeded`, |
| 66 | + `nullrun.ApprovalRequired`, `nullrun.BreakerTimeout`, |
| 67 | + `nullrun.Policy`, `nullrun.FallbackMode`, `nullrun.PoolConfig`) |
| 68 | + are no longer reachable as `from nullrun import X`. The canonical |
| 69 | + exception names (`NullRunBlockedException`, `WorkflowPausedException`, |
| 70 | + `WorkflowKilledException`, `NullRunAuthenticationError`, …) and the |
| 71 | + canonical policy/transport modules |
| 72 | + (`from nullrun.runtime import Policy`, |
| 73 | + `from nullrun.transport import FallbackMode, PoolConfig`) remain |
| 74 | + available. Audited for 0 external callers. |
| 75 | + |
| 76 | +### Migration |
| 77 | + |
| 78 | +- **0.2.x → 0.3.0**: |
| 79 | + - `nullrun.init()` calls without `api_key` will raise. Pass |
| 80 | + `api_key="nr_live_..."` explicitly or set `NULLRUN_API_KEY`. |
| 81 | + - `NullRunRuntime(...)` constructions without `api_key` will raise |
| 82 | + (same fix). |
| 83 | + - Tests using `NullRunNoop` / `local_mode=True` mocking must switch |
| 84 | + to `NullRunRuntime(api_key="test-key", _test_mode=True)` — |
| 85 | + `_test_mode` skips the network calls without silently bypassing |
| 86 | + policy. |
| 87 | + - `from nullrun import BreakerError` (and the 6 other legacy names) |
| 88 | + must use the canonical paths above. |
| 89 | + |
| 90 | +### Added |
| 91 | + |
| 92 | +- **Async Policy Cache**: `AsyncTransport` now uses `PolicyCache` for CACHED fallback mode. Previously the async transport always fell back to PERMISSIVE when gateway was unreachable. Now it caches successful execute decisions and uses them when gateway is unavailable. |
| 93 | +- **Custom Sensitive Tools API**: Added `add_sensitive_tool()`, `remove_sensitive_tool()`, `register_sensitive_tools()`, and `get_sensitive_tools()` methods to `NullRunRuntime`. Users can now register custom tools as sensitive requiring strict mode enforcement. |
| 94 | + |
| 95 | +### Deprecated |
| 96 | + |
| 97 | +- **No-api-key init / local mode** (T3-S1): Calling `nullrun.init()` or constructing `NullRunRuntime(...)` without an `api_key` (and with `NULLRUN_API_KEY` unset) now emits a `DeprecationWarning`. The runtime still falls back to local mode and silently bypasses every backend gate (budget, policy, control plane). The fallback will be **removed in 0.3.0** — passing `api_key='nr_live_...'` explicitly or setting `NULLRUN_API_KEY` is the only supported path going forward. Pin the warning to a hard error with `python -W error::DeprecationWarning` to catch callers in CI. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## [0.1.1] — 2026-05-20 |
| 102 | + |
| 103 | +### Fixed |
| 104 | + |
| 105 | +- **CR-2**: Fixed buffer overflow when circuit breaker is OPEN. Previously, re-queued events were prepended to buffer, causing newest events to be dropped first. Now appends to buffer end and checks max_buffer_size before re-queue. |
| 106 | +- **CR-5**: Async circuit breaker now uses `asyncio.Lock` instead of `threading.Lock` for proper async context handling. |
| 107 | +- **CR-1+CR-4**: `runtime.py` now creates Transport before `_authenticate()` and `_fetch_policy()`, reusing the HTTP client for connection pooling and consistent timeout/retry policies. |
| 108 | +- **AsyncAwait**: Fixed `_call_async()` not awaiting `_on_success_async()` and `_on_failure_async()` coroutines, causing "coroutine was never awaited" warnings in async transport. |
| 109 | + |
| 110 | +### Changed |
| 111 | + |
| 112 | +- Transport buffer now enforces max_buffer_size **before** re-queuing events on circuit breaker OPEN |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## [0.1.0] — 2026-05-18 |
| 117 | + |
| 118 | +### Added |
| 119 | + |
| 120 | +- Circuit breaker core (`src/nullrun/breaker/`) with STRICT / PERMISSIVE / CACHED fallback modes |
| 121 | +- HTTP transport with batch event sending (`transport.py`) |
| 122 | +- Async transport for asyncio applications |
| 123 | +- Retry logic with jitter and policy-aware backoff |
| 124 | +- `@protect` decorator for wrapping functions (`decorators.py`) |
| 125 | +- Workflow context support (`context.py`) |
| 126 | +- Main runtime entrypoint (`runtime.py`) |
| 127 | +- `X-API-Version` header on all outgoing requests |
| 128 | + |
| 129 | +### Notes |
| 130 | + |
| 131 | +- Requires Python ≥ 3.10 |
| 132 | +- Compatible with NullRun API version `2024-01-15` |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## How to upgrade |
| 137 | + |
| 138 | +### 0.x → next |
| 139 | + |
| 140 | +_No breaking changes yet. Watch this file._ |
| 141 | + |
| 142 | +--- |
| 143 | + |
| 144 | +[Unreleased]: https://github.com/maltsev-dev/nullrun-sdk/compare/v0.1.1...HEAD |
| 145 | +[0.1.1]: https://github.com/maltsev-dev/nullrun-sdk/releases/tag/v0.1.1 |
| 146 | +[0.1.0]: https://github.com/maltsev-dev/nullrun-sdk/releases/tag/v0.1.0 |
0 commit comments