cleanlib-sdk 0.4.4__tar.gz → 0.4.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cleanlib_sdk-0.4.6/CHANGELOG.md +82 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/PKG-INFO +1 -1
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/__init__.py +7 -1
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/types.py +22 -0
- cleanlib_sdk-0.4.6/cleanlib_sdk/verdict_to_envelope.py +156 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/pyproject.toml +1 -1
- cleanlib_sdk-0.4.4/CHANGELOG.md +0 -41
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/.gitignore +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/README.md +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/client.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/derive_status.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/errors.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/__init__.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/enrich_client.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/enrich_types.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/remediation_client.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/types.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/http/verdict_client.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/reason_codes.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/schema/__init__.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/schema/verdict_envelope_v1.py +0 -0
- {cleanlib_sdk-0.4.4 → cleanlib_sdk-0.4.6}/cleanlib_sdk/transport.py +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# cleanlib-sdk changelog
|
|
2
|
+
|
|
3
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
4
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
## [0.4.6] — 2026-06-05
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- `cleanlib_sdk.verdict_to_envelope_v1(verdict)` — pure-function structural
|
|
11
|
+
adapter that converts the App's wire-shape `Verdict` to the canonical
|
|
12
|
+
customer-facing `VerdictEnvelopeV1` (returned as a `dict[str, Any]`
|
|
13
|
+
matching `VerdictEnvelopeV1Schema`). Second of four parity-locked
|
|
14
|
+
implementations across the SDK fleet (Rust: `cleanlib_client::verdict_to_envelope_v1`
|
|
15
|
+
shipped in v0.1.4; JS + Go to follow). Ratified at
|
|
16
|
+
`decisions/2026-06-05-cycle-14-cleanlib-48-envelope-shape-ratification.md`
|
|
17
|
+
(cleanlib monorepo).
|
|
18
|
+
- Status/reason_code derivation table mirrors the Rust adapter byte-for-byte:
|
|
19
|
+
`VECTOR_VERDICT + CRITICAL → DENY + VERDICT_EXPLOITATION_CRITICAL`,
|
|
20
|
+
`+ HIGH → DENY + VERDICT_LOW_TRUST`,
|
|
21
|
+
`+ MEDIUM → WARN + VERDICT_ABANDONED`,
|
|
22
|
+
`DM_THRESHOLD_BLOCK + HIGH/CRITICAL → DENY + VERDICT_DENY_LIST`,
|
|
23
|
+
`+ MEDIUM → WARN + VERDICT_DENY_LIST`,
|
|
24
|
+
`ALLOWED_NO_FINDINGS / INSUFFICIENT_DATA / unknown → ALLOW + VERDICT_CLEAN`.
|
|
25
|
+
`stale_since_at` set overrides `reason_code` to `VERDICT_DEGRADED_STALE`
|
|
26
|
+
while preserving the status tier.
|
|
27
|
+
- `rich_data` sub-object populated with `suggested_actions`, `similar_to`,
|
|
28
|
+
`evidence_gaps`, `previous_verdict`, `confidence`, `composite_score`,
|
|
29
|
+
`source`, `severity`, `staleness_reason` when present on the Verdict.
|
|
30
|
+
- Enrich-cascade slots (`remediation`, `exploitability`, `availability`)
|
|
31
|
+
are left `None`; consumers populate them via `HttpEnrichClient` before
|
|
32
|
+
calling `derive_status` for the canonical (status, reason_code) decision.
|
|
33
|
+
|
|
34
|
+
## [0.4.5] — 2026-06-04
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- `Verdict.previous_verdict` field plus a new `PreviousVerdict` pydantic
|
|
39
|
+
model (`verdict_id`, `verdict`, `computed_at`, `diff`). Parity-ripple with
|
|
40
|
+
`sdk-go.PreviousVerdict`. The CleanLibrary App emits this field in its
|
|
41
|
+
`/v1/customer/verdicts/...` envelope when a prior verdict exists for the
|
|
42
|
+
same package version; previously sdk-py deserialized it as a no-op via
|
|
43
|
+
pydantic-default tolerance and customers lost the verdict-state-change
|
|
44
|
+
signal. `PreviousVerdict` is exported from the package root alongside
|
|
45
|
+
`Verdict`.
|
|
46
|
+
|
|
47
|
+
## [0.4.4] — 2026-06-04
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- `cleanlib_sdk.__version__` synchronized with the package manifest version.
|
|
52
|
+
Previously the in-code `__version__` reported `0.4.2` while the published
|
|
53
|
+
artifact was `0.4.3` — telemetry that relied on `__version__` for User-Agent
|
|
54
|
+
composition was under-reporting deployment penetration.
|
|
55
|
+
- Wheel + sdist now include `CHANGELOG.md`. Customers running `pip download`
|
|
56
|
+
+ tar inspection (or browsing the PyPI release files page) see the version
|
|
57
|
+
history alongside the package code.
|
|
58
|
+
|
|
59
|
+
## [0.4.3] — 2026-06-03
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- `pyproject.toml` `[project.urls]` table sanitized: `Homepage`,
|
|
64
|
+
`Documentation`, and `Bug Tracker` now point at `cleanlibrary.clnstrt.dev`
|
|
65
|
+
rather than the internal source-of-truth URLs that previously rendered on
|
|
66
|
+
the PyPI listing page.
|
|
67
|
+
- `README.md` cross-references brand-clean: repo-internal links replaced with
|
|
68
|
+
the customer-facing `cleanlibrary.clnstrt.dev` documentation site and
|
|
69
|
+
cross-language SDK registry pages (crates.io, pkg.clnstrt.dev, npmjs.com).
|
|
70
|
+
|
|
71
|
+
### Notes
|
|
72
|
+
|
|
73
|
+
- No runtime API or wire-protocol changes; this is a metadata + docs ship.
|
|
74
|
+
- Verified via `python -m build` against the resulting `cleanlib_sdk-0.4.3-py3-none-any.whl`
|
|
75
|
+
`METADATA` + `cleanlib_sdk-0.4.3.tar.gz` `PKG-INFO`: zero
|
|
76
|
+
internal-source URL references.
|
|
77
|
+
|
|
78
|
+
## 0.4.2 — enrich verb cascade + F4 default-flip to cleanlib-enrich
|
|
79
|
+
|
|
80
|
+
## 0.4.1 — per-domain HTTP client split (HttpRemediationClient) + schema/reason-codes mirror + DeriveStatus + Client @deprecated
|
|
81
|
+
|
|
82
|
+
## 0.4.0 — verb cascade + rich-data
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cleanlib-sdk
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: CleanLibrary Python SDK — HttpVerdictClient + HttpRemediationClient + HttpEnrichClient triad (sister-shape with @cleanstart/cleanlib-sdk v0.4.4)
|
|
5
5
|
Project-URL: Homepage, https://cleanlibrary.clnstrt.dev
|
|
6
6
|
Project-URL: Documentation, https://cleanlibrary.clnstrt.dev/docs/sdk-python
|
|
@@ -92,6 +92,7 @@ from cleanlib_sdk.types import (
|
|
|
92
92
|
PolicyPreviewResponse,
|
|
93
93
|
PolicyPreviewResult,
|
|
94
94
|
RecommendedVersion,
|
|
95
|
+
PreviousVerdict,
|
|
95
96
|
RiskAcceptResponse,
|
|
96
97
|
ScanResponse,
|
|
97
98
|
ScanResult,
|
|
@@ -99,7 +100,9 @@ from cleanlib_sdk.types import (
|
|
|
99
100
|
Verdict,
|
|
100
101
|
)
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
from cleanlib_sdk.verdict_to_envelope import verdict_to_envelope_v1
|
|
104
|
+
|
|
105
|
+
__version__ = "0.4.6"
|
|
103
106
|
|
|
104
107
|
__all__ = [
|
|
105
108
|
# v0.4.2 per-domain HTTP client triad (primary API)
|
|
@@ -142,8 +145,11 @@ __all__ = [
|
|
|
142
145
|
"AVAILABILITY_ENUM",
|
|
143
146
|
"derive_status",
|
|
144
147
|
"StatusResult",
|
|
148
|
+
# CLEANLIB-48 envelope-shape ratification (v0.4.6)
|
|
149
|
+
"verdict_to_envelope_v1",
|
|
145
150
|
# cycle-6 v0.4.0 types
|
|
146
151
|
"Verdict",
|
|
152
|
+
"PreviousVerdict",
|
|
147
153
|
"Attestation",
|
|
148
154
|
"SignedAttestation",
|
|
149
155
|
"RecommendedVersion",
|
|
@@ -110,6 +110,28 @@ class Verdict(BaseModel):
|
|
|
110
110
|
# Cycle-6 9th field (App PR #105). Package-level vuln/risk summary.
|
|
111
111
|
package_risk: Optional["PackageRisk"] = None
|
|
112
112
|
|
|
113
|
+
# v0.4.5 CLEANLIB-50: previous_verdict parity with sdk-go.PreviousVerdict.
|
|
114
|
+
# CleanLibrary App emits this when a prior verdict exists for the same
|
|
115
|
+
# (ecosystem, package, version); previously sdk-py deserialized it as a
|
|
116
|
+
# no-op via pydantic-default tolerance and customers lost the
|
|
117
|
+
# verdict-state-change signal.
|
|
118
|
+
previous_verdict: Optional["PreviousVerdict"] = None
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class PreviousVerdict(BaseModel):
|
|
122
|
+
"""Prior-verdict comparison surfaced on the canonical Verdict envelope
|
|
123
|
+
when a prior verdict exists for the same package version. Sister-shape
|
|
124
|
+
with `cleanlib_sdk_go.PreviousVerdict` + `cleanlib_client::PreviousVerdict`
|
|
125
|
+
+ `cleanlib_core::PreviousVerdict` in the App.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
129
|
+
|
|
130
|
+
verdict_id: Optional[str] = None
|
|
131
|
+
verdict: Optional[str] = None
|
|
132
|
+
computed_at: Optional[str] = None
|
|
133
|
+
diff: Optional[str] = None
|
|
134
|
+
|
|
113
135
|
|
|
114
136
|
class RecommendedVersion(BaseModel):
|
|
115
137
|
"""Recommended upgrade target. Mirrors cleanlib_core::RecommendedVersion;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""verdict_to_envelope_v1 — Verdict (App wire) → VerdictEnvelopeV1 (canonical) adapter.
|
|
2
|
+
|
|
3
|
+
Ratified at ``decisions/2026-06-05-cycle-14-cleanlib-48-envelope-shape-ratification.md``
|
|
4
|
+
(in the cleanlib monorepo). Sister of:
|
|
5
|
+
|
|
6
|
+
- ``cleanlib_client::verdict_to_envelope_v1`` (Rust)
|
|
7
|
+
- ``verdictToEnvelopeV1`` (sdk-js, planned)
|
|
8
|
+
- ``VerdictToEnvelopeV1`` (sdk-go, planned)
|
|
9
|
+
|
|
10
|
+
All four implementations produce byte-identical output for the same input
|
|
11
|
+
Verdict; this is verified by the ``cleanlib-contract-fixtures`` Verdict-to-
|
|
12
|
+
envelope golden pack (planned, decision doc action D.1).
|
|
13
|
+
|
|
14
|
+
The adapter is a PURE STRUCTURAL CONVERSION. The output envelope's
|
|
15
|
+
``remediation`` / ``exploitability`` / ``availability`` slots are always
|
|
16
|
+
``None``; consumers populate them via the ``HttpEnrichClient`` cascade
|
|
17
|
+
before running ``derive_status`` for the canonical decision derivation.
|
|
18
|
+
|
|
19
|
+
Status/reason_code mapping table (App's view; consumer may re-derive
|
|
20
|
+
after enriching)::
|
|
21
|
+
|
|
22
|
+
verdict label | severity | status | reason_code
|
|
23
|
+
----------------------|-----------------|--------|---------------------------------
|
|
24
|
+
VECTOR_VERDICT | CRITICAL | DENY | VERDICT_EXPLOITATION_CRITICAL
|
|
25
|
+
VECTOR_VERDICT | HIGH | DENY | VERDICT_LOW_TRUST
|
|
26
|
+
VECTOR_VERDICT | MEDIUM | WARN | VERDICT_ABANDONED
|
|
27
|
+
VECTOR_VERDICT | LOW / NONE | ALLOW | VERDICT_CLEAN
|
|
28
|
+
DM_THRESHOLD_BLOCK | CRITICAL / HIGH | DENY | VERDICT_DENY_LIST
|
|
29
|
+
DM_THRESHOLD_BLOCK | MEDIUM | WARN | VERDICT_DENY_LIST
|
|
30
|
+
DM_THRESHOLD_BLOCK | LOW / NONE | ALLOW | VERDICT_CLEAN
|
|
31
|
+
ALLOWED_NO_FINDINGS | any | ALLOW | VERDICT_CLEAN
|
|
32
|
+
INSUFFICIENT_DATA | any | ALLOW | VERDICT_CLEAN
|
|
33
|
+
(unknown label) | any | ALLOW | VERDICT_CLEAN
|
|
34
|
+
|
|
35
|
+
Freshness override: if ``verdict.stale_since_at`` is not ``None``, the
|
|
36
|
+
``reason_code`` is overridden to ``VERDICT_DEGRADED_STALE`` (status tier
|
|
37
|
+
preserved). Sister of the enrich-substrate freshness override applied by
|
|
38
|
+
``derive_status`` after the enrich cascade lands.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from __future__ import annotations
|
|
42
|
+
|
|
43
|
+
from typing import Any
|
|
44
|
+
|
|
45
|
+
from cleanlib_sdk.types import Verdict
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def verdict_to_envelope_v1(verdict: Verdict) -> dict[str, Any]:
|
|
49
|
+
"""Convert a wire-shape :class:`Verdict` to a :data:`VerdictEnvelopeV1` dict.
|
|
50
|
+
|
|
51
|
+
Returns the envelope as a plain ``dict[str, Any]`` matching the
|
|
52
|
+
``VerdictEnvelopeV1Schema`` (sdk-js v0.4.1 source-of-truth schema). The
|
|
53
|
+
returned dict can be passed directly to :func:`derive_status` after
|
|
54
|
+
populating the enrich-cascade fields.
|
|
55
|
+
"""
|
|
56
|
+
status, reason_code = _derive_initial_status_reason(verdict)
|
|
57
|
+
|
|
58
|
+
# `as_of` falls back: computed_at → data_freshness_at → "". Mirrors
|
|
59
|
+
# Rust adapter's `verdict_to_envelope_v1` behavior exactly.
|
|
60
|
+
as_of = _isoformat_or_empty(verdict.computed_at) or _isoformat_or_empty(
|
|
61
|
+
verdict.data_freshness_at
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"status": status,
|
|
66
|
+
"reason_code": reason_code,
|
|
67
|
+
"human_message": verdict.reasoning or "",
|
|
68
|
+
"as_of": as_of,
|
|
69
|
+
"rich_data": _build_rich_data(verdict),
|
|
70
|
+
"remediation": None,
|
|
71
|
+
"exploitability": None,
|
|
72
|
+
"availability": None,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _derive_initial_status_reason(verdict: Verdict) -> tuple[str, str]:
|
|
77
|
+
# The wire shape carries `verdict_label` (alias for ``verdict``) and
|
|
78
|
+
# ``severity`` as Optional strings. Normalize to upper-case so legacy
|
|
79
|
+
# lower-case fixtures don't misclassify.
|
|
80
|
+
label = (verdict.verdict_label or "").upper()
|
|
81
|
+
severity = (verdict.severity or "NONE").upper()
|
|
82
|
+
|
|
83
|
+
if label == "VECTOR_VERDICT":
|
|
84
|
+
if severity == "CRITICAL":
|
|
85
|
+
status, reason = "DENY", "VERDICT_EXPLOITATION_CRITICAL"
|
|
86
|
+
elif severity == "HIGH":
|
|
87
|
+
status, reason = "DENY", "VERDICT_LOW_TRUST"
|
|
88
|
+
elif severity == "MEDIUM":
|
|
89
|
+
status, reason = "WARN", "VERDICT_ABANDONED"
|
|
90
|
+
else:
|
|
91
|
+
status, reason = "ALLOW", "VERDICT_CLEAN"
|
|
92
|
+
elif label == "DM_THRESHOLD_BLOCK":
|
|
93
|
+
if severity in ("CRITICAL", "HIGH"):
|
|
94
|
+
status, reason = "DENY", "VERDICT_DENY_LIST"
|
|
95
|
+
elif severity == "MEDIUM":
|
|
96
|
+
status, reason = "WARN", "VERDICT_DENY_LIST"
|
|
97
|
+
else:
|
|
98
|
+
status, reason = "ALLOW", "VERDICT_CLEAN"
|
|
99
|
+
else:
|
|
100
|
+
# ALLOWED_NO_FINDINGS / INSUFFICIENT_DATA / unknown → ALLOW + CLEAN.
|
|
101
|
+
# Forward-compat: future App-side labels default to ALLOW so older
|
|
102
|
+
# SDKs don't break on schema additions.
|
|
103
|
+
status, reason = "ALLOW", "VERDICT_CLEAN"
|
|
104
|
+
|
|
105
|
+
if verdict.stale_since_at is not None:
|
|
106
|
+
# Sister of the enrich-substrate freshness override in
|
|
107
|
+
# derive_status: status tier preserved, reason_code overridden.
|
|
108
|
+
reason = "VERDICT_DEGRADED_STALE"
|
|
109
|
+
return status, reason
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _build_rich_data(verdict: Verdict) -> dict[str, Any]:
|
|
113
|
+
"""Build the envelope's ``rich_data`` sub-object from the wire-shape
|
|
114
|
+
Verdict's rich fields. Mirrors the Rust adapter's `build_rich_data`."""
|
|
115
|
+
rich: dict[str, Any] = {}
|
|
116
|
+
if verdict.suggested_actions:
|
|
117
|
+
rich["suggested_actions"] = list(verdict.suggested_actions)
|
|
118
|
+
if verdict.similar_to:
|
|
119
|
+
rich["similar_to"] = list(verdict.similar_to)
|
|
120
|
+
if verdict.evidence_gaps:
|
|
121
|
+
rich["evidence_gaps"] = list(verdict.evidence_gaps)
|
|
122
|
+
if verdict.previous_verdict is not None:
|
|
123
|
+
pv = verdict.previous_verdict
|
|
124
|
+
rich["previous_verdict"] = {
|
|
125
|
+
"verdict_id": pv.verdict_id or "",
|
|
126
|
+
"verdict": pv.verdict or "",
|
|
127
|
+
"computed_at": pv.computed_at or "",
|
|
128
|
+
"diff": pv.diff or "",
|
|
129
|
+
}
|
|
130
|
+
rich["confidence"] = verdict.confidence if verdict.confidence is not None else 0.0
|
|
131
|
+
rich["composite_score"] = (
|
|
132
|
+
verdict.composite_score if verdict.composite_score is not None else 0
|
|
133
|
+
)
|
|
134
|
+
if verdict.source:
|
|
135
|
+
rich["source"] = verdict.source
|
|
136
|
+
if verdict.severity:
|
|
137
|
+
rich["severity"] = verdict.severity
|
|
138
|
+
if verdict.staleness_reason:
|
|
139
|
+
rich["staleness_reason"] = verdict.staleness_reason
|
|
140
|
+
return rich
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _isoformat_or_empty(dt: Any) -> str:
|
|
144
|
+
"""Render a datetime or ISO string as a UTC ISO string with Z suffix."""
|
|
145
|
+
if dt is None:
|
|
146
|
+
return ""
|
|
147
|
+
if isinstance(dt, str):
|
|
148
|
+
return dt
|
|
149
|
+
# pydantic datetime — use isoformat; convert +00:00 → Z for wire-parity
|
|
150
|
+
# with the Rust adapter which emits whatever the App's serializer
|
|
151
|
+
# produced.
|
|
152
|
+
try:
|
|
153
|
+
s = dt.isoformat()
|
|
154
|
+
except Exception:
|
|
155
|
+
return str(dt)
|
|
156
|
+
return s.replace("+00:00", "Z")
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cleanlib-sdk"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.6"
|
|
8
8
|
description = "CleanLibrary Python SDK — HttpVerdictClient + HttpRemediationClient + HttpEnrichClient triad (sister-shape with @cleanstart/cleanlib-sdk v0.4.4)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
cleanlib_sdk-0.4.4/CHANGELOG.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# cleanlib-sdk changelog
|
|
2
|
-
|
|
3
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
4
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
-
|
|
6
|
-
## [0.4.4] — 2026-06-04
|
|
7
|
-
|
|
8
|
-
### Fixed
|
|
9
|
-
|
|
10
|
-
- `cleanlib_sdk.__version__` synchronized with the package manifest version.
|
|
11
|
-
Previously the in-code `__version__` reported `0.4.2` while the published
|
|
12
|
-
artifact was `0.4.3` — telemetry that relied on `__version__` for User-Agent
|
|
13
|
-
composition was under-reporting deployment penetration.
|
|
14
|
-
- Wheel + sdist now include `CHANGELOG.md`. Customers running `pip download`
|
|
15
|
-
+ tar inspection (or browsing the PyPI release files page) see the version
|
|
16
|
-
history alongside the package code.
|
|
17
|
-
|
|
18
|
-
## [0.4.3] — 2026-06-03
|
|
19
|
-
|
|
20
|
-
### Fixed
|
|
21
|
-
|
|
22
|
-
- `pyproject.toml` `[project.urls]` table sanitized: `Homepage`,
|
|
23
|
-
`Documentation`, and `Bug Tracker` now point at `cleanlibrary.clnstrt.dev`
|
|
24
|
-
rather than the internal source-of-truth URLs that previously rendered on
|
|
25
|
-
the PyPI listing page.
|
|
26
|
-
- `README.md` cross-references brand-clean: repo-internal links replaced with
|
|
27
|
-
the customer-facing `cleanlibrary.clnstrt.dev` documentation site and
|
|
28
|
-
cross-language SDK registry pages (crates.io, pkg.clnstrt.dev, npmjs.com).
|
|
29
|
-
|
|
30
|
-
### Notes
|
|
31
|
-
|
|
32
|
-
- No runtime API or wire-protocol changes; this is a metadata + docs ship.
|
|
33
|
-
- Verified via `python -m build` against the resulting `cleanlib_sdk-0.4.3-py3-none-any.whl`
|
|
34
|
-
`METADATA` + `cleanlib_sdk-0.4.3.tar.gz` `PKG-INFO`: zero
|
|
35
|
-
internal-source URL references.
|
|
36
|
-
|
|
37
|
-
## 0.4.2 — enrich verb cascade + F4 default-flip to cleanlib-enrich
|
|
38
|
-
|
|
39
|
-
## 0.4.1 — per-domain HTTP client split (HttpRemediationClient) + schema/reason-codes mirror + DeriveStatus + Client @deprecated
|
|
40
|
-
|
|
41
|
-
## 0.4.0 — verb cascade + rich-data
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|