release: 0.7.0 — thin-client refactor#34
Merged
Merged
Conversation
BREAKING CHANGES
----------------
SDK is now a thin client. All enforcement decisions arrive from the
backend via /api/v1/gate and /api/v1/execute. Local policy
enforcement, its dataclass, and its hardcoded thresholds are removed.
Removed:
* class Policy, Policy.default_local(), Policy.strict_local(),
Policy.from_dict() (was at nullrun.runtime.Policy)
* NullRunRuntime.policy property
* NullRunRuntime(policy=...) constructor kwarg
* NullRunStatus.active_policy, .fallback_policy,
.fallback_reason, .last_policy_fetch,
.last_policy_fetch_age_seconds fields
* Transport.fetch_policy() method
* Transport.clear_policy_cache() method
* FallbackMode.CACHED enum value
* Local loop/rate detectors: LoopTracker, RateTracker,
LocalDecision classes
* NullRunRuntime._local_check(), _loop_tracker, _rate_tracker
instance attrs
* _local_loop_threshold, _local_rate_limit (hardcoded 6/1000)
* CachedDecision, PolicyCache transport classes
* NULLRUN_FALLBACK_MODE env var
* NULLRUN_POLICY_FAIL_OPEN env var (backend is authoritative)
* NullRunRuntime._fetch_policy() method
* WS on_policy_invalidated callback
Migration: if you need to display policy values in a UI, fetch them
directly via GET /api/v1/orgs/{org_id}/policies. The SDK no longer
mirrors them.
Audit: Drift D-01 from 2026-06-26 SDK↔backend audit
(PolicyResponse lacked fields SDK expected; local defaults silently
widened limits).
Transport finalizer behavior change
-----------------------------------
Transport._atexit_flush_safe is now a no-op that emits a single
DEBUG log line. It does NOT persist buffered events to the WAL
anymore — by the time weakref.finalize fires, self._buffer /
self._lock / self._client are already gone. Crash-safety now lives
exclusively in stop() and the context-manager pattern. Callers who
relied on the implicit on-exit WAL flush MUST switch to:
with nullrun.Transport(api_url=..., api_key=...) as t:
...
or call t.stop() explicitly before process exit.
Tests
-----
* tests/test_signal_safety.py::TestAtexitViaWeakref rewritten to
pin the new no-op-finalizer contract (was written against an
intended but-unimplemented WAL-persist finalizer).
* tests/test_deprecation_warnings.py removed (NULLRUN_FALLBACK_MODE
env var is gone; deprecation warning is moot).
* tests/test_no_local_policy.py added (pins absence of
NullRunRuntime._local_check and the local Policy dataclass).
* Various test updates reflecting runtime/transport refactors
(-1883 / +1432 in tests/, mostly deletions of policy- and
fallback-mode-specific cases).
Other
-----
* pyproject.toml: version bumped 0.6.1 -> 0.7.0 (was inconsistent
with __version__.py before this commit).
* CHANGELOG.md: full 0.7.0 entry covering BREAKING CHANGES, the
transport-finalizer contract change, and migration guidance.
Verification (local on Windows / Python 3.14.2):
pytest 913 passed, 13 skipped (0:08:50)
ruff check clean on src/ and tests/
mypy src/ clean on 26 source files
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BREAKING CHANGES
SDK is now a thin client. All enforcement decisions arrive from the backend via /api/v1/gate and /api/v1/execute. Local policy enforcement, its dataclass, and its hardcoded thresholds are removed.
Removed:
Migration: if you need to display policy values in a UI, fetch them directly via GET /api/v1/orgs/{org_id}/policies. The SDK no longer mirrors them.
Audit: Drift D-01 from 2026-06-26 SDK↔backend audit (PolicyResponse lacked fields SDK expected; local defaults silently widened limits).
Transport finalizer behavior change
Transport._atexit_flush_safe is now a no-op that emits a single DEBUG log line. It does NOT persist buffered events to the WAL anymore — by the time weakref.finalize fires, self._buffer / self._lock / self._client are already gone. Crash-safety now lives exclusively in stop() and the context-manager pattern. Callers who relied on the implicit on-exit WAL flush MUST switch to:
or call t.stop() explicitly before process exit.
Tests
Other
Verification (local on Windows / Python 3.14.2):
pytest 913 passed, 13 skipped (0:08:50)
ruff check clean on src/ and tests/
mypy src/ clean on 26 source files
What
Why
How
Test plan
cd backend && cargo test,cd frontend && npm test)cd frontend && npm run lint)cd frontend && npm run type-check)Risk
Checklist
CONTRIBUTING.md(if present)