Skip to content

Bound runtime dependency ranges and pin build backend - #103

Merged
lelia merged 7 commits into
mainfrom
lelia/bound-runtime-dependency-ranges
Aug 6, 2026
Merged

Bound runtime dependency ranges and pin build backend#103
lelia merged 7 commits into
mainfrom
lelia/bound-runtime-dependency-ranges

Conversation

@lelia

@lelia lelia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Companion to the socket-python-cli dependency pinning work (SocketDev/socket-python-cli#289). The SDK's runtime dependencies were under-constrained:

  • requests was fully unbounded — a fresh install could resolve to any just-published release, which is both a supply-chain exposure and a problem for consumers running Socket Firewall with a cooldown policy.
  • typing-extensions>=4.12.2 had no upper bound.
  • The hatchling build backend was unpinned for sdist builds.

Changes

  • requests>=2.32.5,<3 and typing-extensions>=4.12.2,<5 — floors match the versions already resolved and tested in uv.lock; ceilings exclude the next major.
  • hatchling==1.31.0 in [build-system] (isolated build env, so an exact pin can't conflict with consumer environments).
  • Version bump to 3.5.0 (the new requests floor is a newly binding constraint for consumers on older versions, so minor rather than patch) and uv lock regenerated.
  • Seeded a CHANGELOG.md (the repo had none) in the socket-python-cli format: a curated 3.5.0 entry, plus the full history backfilled from the auto-generated GitHub release notes (all 53 published releases, dated, pre-releases labeled).

Why bounded ranges instead of exact pins

socketdev is a library, so it deliberately gets the library-appropriate version of the CLI's hardening rather than a copy of it. Exact == pins in a library's metadata become resolver constraints in every consumer's environment: socket-python-cli 2.6.0+ pins its entire runtime closure exactly (e.g. requests==2.34.2), and if this package pinned requests==2.32.5, every CLI install would fail with an unsatisfiable conflict — likewise for any downstream user who pins their own dependencies. Ranges here + exact pins in applications compose; pins in both places must move in lockstep forever.

Reproducibility for this repo's own development and CI is already handled where it belongs: the committed uv.lock (enforced with uv sync --locked in CI) and Dependabot on the uv ecosystem with a 7-day cooldown.

Testing

  • uv lock regenerated cleanly; only the project version entry changed (both floors were already the locked versions).
  • Test suite matches the main baseline exactly (183 passed; the same pre-existing integration-test failures requiring live API credentials fail identically on main).

Ref: CE-359


Note

Low Risk
Packaging and dependency-metadata only; no SDK runtime code changes, though consumers on requests below 2.32.5 will need to upgrade.

Overview
Release 3.5.0 tightens dependency metadata and adds project changelog documentation.

Runtime dependencies in pyproject.toml now use bounded ranges: requests>=2.32.5,<3 (was unbounded) and typing-extensions>=4.12.2,<5 (previously no upper cap). The build backend pins hatchling==1.27.0 for sdist builds, with a note that this is the newest hatchling compatible with Python 3.9. Project version moves from static 3.4.2 in pyproject.toml to dynamic = ["version"] (still sourced from socketdev/version.py, now 3.5.0), and uv.lock is updated to match the new specifiers.

A new CHANGELOG.md documents 3.5.0 (dependency pinning rationale) and backfills prior release notes from GitHub.

Reviewed by Cursor Bugbot for commit 64898c3. Configure here.

Add version bounds to the runtime dependencies: requests was fully
unbounded and typing-extensions had no upper bound, so a fresh install
could resolve either to any just-published release. As a library,
socketdev declares bounded ranges rather than exact pins - exact pins
in package metadata would conflict with consumers that pin their own
dependencies, including socket-python-cli, which pins its entire
runtime closure (socketsecurity 2.5.10+) and relies on this package's
ranges staying compatible.

Floors match the versions already resolved and tested in uv.lock;
ceilings exclude the next major. Also pins the hatchling build backend
used for sdist builds. Dependabot (uv ecosystem, 7-day cooldown)
already keeps the lockfile fresh within these bounds.

Companion to the socket-python-cli dependency pinning work (CE-359).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia
lelia requested a review from a team as a code owner August 6, 2026 02:30
@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 02:31 — with GitHub Actions Inactive
Seed a changelog in the socket-python-cli format, starting at 3.4.3,
with a pointer to GitHub releases for earlier history.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 02:34 — with GitHub Actions Inactive
Import all 53 published releases (v1.0.15 through v3.4.2) from the
auto-generated GitHub release notes: one dated entry per version,
pre-releases labeled, body headings demoted one level so version
headings stay the top-level structure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 02:40 — with GitHub Actions Inactive
The new requests floor is a newly binding constraint for consumers on
older versions, so this warrants a minor bump rather than a patch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 02:57 — with GitHub Actions Inactive
@lelia

lelia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Incomplete package version bump
    • Updated pyproject.toml and uv.lock from 3.4.2 to 3.5.0 so packaging metadata matches socketdev/version.py and CHANGELOG.md.

Create PR

Or push these changes by commenting:

@cursor push 804710c344
Preview (804710c344)
diff --git a/pyproject.toml b/pyproject.toml
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@
 
 [project]
 name = "socketdev"
-version = "3.4.2"
+version = "3.5.0"
 requires-python = ">= 3.9"
 dependencies = [
     'requests>=2.32.5,<3',

diff --git a/uv.lock b/uv.lock
--- a/uv.lock
+++ b/uv.lock
@@ -1353,7 +1353,7 @@
 
 [[package]]
 name = "socketdev"
-version = "3.4.2"
+version = "3.5.0"
 source = { editable = "." }
 dependencies = [
     { name = "requests" },

You can send follow-ups to the cloud agent here.

Comment thread pyproject.toml
Comment thread pyproject.toml Outdated
@lelia

lelia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Cursor (@cursor) push 804710c

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Could not push Autofix changes. The PR branch may have changed since the Autofix ran, or the Autofix commit may no longer exist.

@dc-larsen David Larsen (dc-larsen) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two blockers before this can ship, both matching what Bugbot flagged. I confirmed the first empirically.

1. [project].version in pyproject.toml is still 3.4.2. No dynamic = ["version"], so the static field wins and [tool.hatch.version] is inert. On this branch: hatch version returns 3.4.2, uv build produces socketdev-3.4.2.tar.gz/.whl (bounds are correct in the metadata, just under the old number), and uv.lock still carries version = "3.4.2" for the project entry. So tagging v3.5.0 aborts at the Get Version gate with Error: Git tag (v3.5.0) does not match hatch version (v3.4.2), and tagging v3.4.2 hits pypi_exists=true and skips build/publish, so the new bounds never ship. Bumping line 7 to 3.5.0 fixes it (verified: hatch version then returns 3.5.0 and the build produces socketdev-3.5.0).

Note check_version passes here because version-check.yml reads __version__ from socketdev/version.py only and never looks at pyproject.toml, so it can't see the drift. Declaring dynamic = ["version"] and dropping the static field would close that gap permanently.

2. hatchling==1.31.0 requires Python >=3.10, but this package declares requires-python = ">= 3.9". 1.27.0 is the newest hatchling allowing 3.9. Sdist builds on 3.9 fail to resolve the backend; wheel installs are unaffected. Either pin 1.27.0, use >=1.27,<2, or drop 3.9 (classifiers already start at 3.10).

Rest looks right: test suite matches the main baseline exactly (183 passed, same 14 failures / 19 errors from credential-gated integration tests), uv sync --locked clean, and ranges-not-pins is the correct call for a library.

The [project] version in pyproject.toml is static ([tool.hatch.version]
is only consulted when version is declared dynamic), so bumping
version.py alone left the packaging metadata and uv.lock at 3.4.2.
Set the static version to 3.5.0 to match.

Pin hatchling to 1.27.0 instead of 1.31.0: 1.28+ requires Python 3.10,
while this package's requires-python still includes 3.9, so the newer
pin would break sdist builds on 3.9.

Addresses PR#103 review findings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 03:33 — with GitHub Actions Inactive
Per review on PR#103: with dynamic = ["version"], hatchling reads
socketdev/version.py (the file version-check.yml already validates),
so packaging metadata can never drift from the checked version again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
@lelia

lelia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

David Larsen (@dc-larsen) thanks for the thorough verification — both blockers are addressed:

  1. Static version: fixed in 793d9d6 (static field bumped to 3.5.0), and then adopted your permanent fix in 64898c3dynamic = ["version"] with the static field dropped, so socketdev/version.py (the file version-check.yml already validates) is now the single source of truth. Verified on the branch: hatch version → 3.5.0, uv lock records 3.5.0, uv build produces socketdev-3.5.0-py3-none-any.whl.
  2. hatchling: pinned to 1.27.0 in 793d9d6 (newest release supporting 3.9), with a comment noting why so it doesn't get bumped back inadvertently.

On the classifiers-start-at-3.10 vs requires-python >= 3.9 mismatch you spotted: real, but pre-existing — dropping 3.9 is a support-policy call I'd rather not fold into this PR. The 1.27.0 pin keeps 3.9 working as declared; if 3.9 gets dropped later, the hatchling pin can move back up in the same change.

@lelia
lelia temporarily deployed to socket-firewall August 6, 2026 03:34 — with GitHub Actions Inactive
@lelia

lelia commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 64898c3. Configure here.

@dc-larsen David Larsen (dc-larsen) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both blockers fixed, and the dynamic-version route is the better fix than just bumping the static field. Re-verified locally on 64898c3:

  • hatch version returns 3.5.0, so the release Get Version gate now passes for tag v3.5.0 (and correctly rejects v3.4.2)
  • uv build produces socketdev-3.5.0.tar.gz/.whl with Requires-Python: >=3.9 and requests<3,>=2.32.5 / typing-extensions<5,>=4.12.2
  • 3.5.0 is not on PyPI yet (404), so pypi_exists=false and publish will actually run
  • uv sync --locked clean (picks up 3.4.2 -> 3.5.0); uv.lock correctly drops the root version line now that it's dynamic
  • hatchling 1.27.0 declares requires_python >=3.8, so the 3.9 sdist path is covered
  • Test suite still matches the main baseline exactly (183 passed, same 14 failures / 19 errors from credential-gated integration tests)

Diff since my last pass is just those two files, nothing else.

@lelia
lelia deployed to socket-firewall August 6, 2026 03:43 — with GitHub Actions Active
@lelia
lelia merged commit 6b855d3 into main Aug 6, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants