Skip to content

chore(deps): enforce seven-day third-party release-age policy - #819

Merged
enyst merged 4 commits into
OpenHands:mainfrom
smolpaws:security/seven-day-dependency-age-20261022
Oct 25, 2026
Merged

enyst merged 4 commits into
OpenHands:mainfrom
smolpaws:security/seven-day-dependency-age-20261022

Conversation

@smolpaws

@smolpaws smolpaws commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

HUMAN:

This PR proposes to fix the 7 day cooldown rule, which was applied in some cases and not others.


AGENT:

Audit of the seven-day third-party package intake policy.

Why

Weekly npm/pip bot scheduling does not guarantee minimum publication age. The review guide mentions seven days but contributor and resolver configuration do not enforce it.

Summary

  • Add npm/Python bot cooldowns and uv cutoff; make contributor and reviewer evidence/exception rules explicit.

  • Require exact-version publication/upload evidence for direct and transitive third-party npm/PyPI changes; weekly scheduling is not minimum age.

  • Security updates can bypass Dependabot cooldown. Urgent exceptions require a named package/version/reason and explicit maintainer approval; agents cannot grant their own bypass.

Issue Number

Fixes #820

How to Test

uv lock --offline succeeded without adding a tracked lock. scripts/sync_extensions.py --check passed with an existing nonblocking coverage warning for issue-duplicate-checker. No catalogs or generated skills changed.

Additional audit checks:

  • Parsed Dependabot YAML and pyproject TOML; every npm/Python bot entry in this PR has cooldown.default-days: 7.
  • git diff --check passed. Compared parsed lock package records before/after: no package changes.
  • Local, synthetic registry fixtures verified the actual resolver boundary: without a guard npm 11.12.1 and uv 0.11.19 selected a one-day-old 1.1.0; with seven-day filtering both selected the ten-day-old 1.0.0. npm used --package-lock-only --ignore-scripts --no-audit --no-fund; uv used lock --no-build --no-cache. No live third-party package was installed by these fixtures.
  • Full application/evaluation suites were not run for this configuration/documentation-only change except where stated above. No suspect package release was installed or imported for testing.

Video/Screenshots

N/A - dependency configuration and contributor/reviewer instructions only; no UI or runtime feature change.

Type

  • Docs / chore

Notes

Ready for human review. No merge requested.

Sources: Dependabot cooldown, uv exclude-newer, npm min-release-age. npm's manual --min-release-age=7 requires npm >=11.10; older versions do not enforce it, and npm ci replays the lock rather than proving age.

Review follow-up

Review follow-up: restored the existing temporary-git-pin/unreleased-API merge blocker and installation/runtime validation instruction. Exempted only the direct first-party SDK test dependency from the uv wait; its transitive third-party dependencies remain filtered. Declared uv >=0.9.25 in the resolver and AGENTS; uv 0.9.25 lock --check succeeds (145 packages). sync_extensions.py --check passes with the existing nonblocking catalog coverage warning. GitHub Actions policy remains out of scope: this PR applies to npm/PyPI. Linked issue #820 records this scope.

Current review follow-up (24 October)

Exempted the four named first-party packages used by the documented validation commands: SDK, tools, workspace, and agent-server. Their third-party dependencies retain the cutoff. Corrected the old-uv warning and removed the nonexistent Makefile reference.

Validation: real uv 0.9.25 resolves all four first-party packages at 1.58.0 in an isolated resolution fixture (365 packages), with no third-party artifact younger than seven days. Root uv lock --check passes (145 packages); the generated lock remains untracked/ignored as before. Catalog/schema tests: 117 passed. sync_extensions.py --check passes with the pre-existing duplicate-checker coverage warning.

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions github-actions Bot added the type: chore Maintenance / chores label Oct 22, 2026
@smolpaws
smolpaws marked this pull request as ready for review October 22, 2026 03:02
@enyst
enyst requested review from all-hands-bot and enyst October 22, 2026 03:02

@all-hands-bot all-hands-bot 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.

This review was posted by an AI agent (OpenHands).

Scope gate: all four changed paths (.agents/skills/custom-codereview-guide.md, AGENTS.md, .github/dependabot.yml, pyproject.toml) are repository-owned configuration and review-policy content, with no SDK/automation/Canvas contract involved. In scope.

Re-established state: head is still 481398ccb340fab4d9e258b8f7b7f53077ba23df, PR is open, labels type: chore, no reviews and no comments on the head. Required checks (test, sync-extensions, validate-claude-code) pass; Validate PR description fails on this head.

What I verified on the head

  • Config parses and behaves as described: dependabot.yml loads with cooldown.default-days: 7 on the npm and pip entries only; pyproject.toml loads with tool.uv.exclude-newer = "7 days".
  • The relative duration is valid: uv 0.12.15 accepts the "friendly duration" form and records exclude-newer-span = "P7D" in the resolved lock. uv lock in the workspace produced no tracked change (uv.lock is gitignored).
  • Documentation claims check out against authoritative sources: npm's changelog shows min-release-age added in 11.10.0 (so "requires npm >= 11.10" is right, and the local npm 11.21 accepts --min-release-age), and GitHub's Dependabot options reference confirms cooldown is version-updates-only and that default-days is supported for NPM and Pip.
  • Repository checks: python scripts/sync_extensions.py --check passes with the pre-existing non-blocking coverage warning for issue-duplicate-checker, and the focused tests that touch this guide (test_sync_extensions.py, test_workflow_sync.py, test_pr_review_review_context.py, test_github_triage_delivery.py) pass: 80 passed. I did not run the full suite.

Findings

  1. Material: the rewrite silently drops the temporary-git-pin merge blocker. See inline comment.
  2. Non-blocking: the new exclude-newer guard has no first-party exemption, unlike the review policy it is meant to back up. See inline comment.
  3. Non-blocking, no inline location: the github-actions Dependabot entry is left without a cooldown. GitHub's docs list GitHub Actions among the ecosystems supporting cooldown.default-days, so action updates can still be pulled the day they are released. The new policy text scopes itself to npm/PyPI, so this is consistent with the written rule, but the PR title claims a general "third-party release-age policy" and this ecosystem is the one left unguarded.
  4. Non-blocking: Validate PR description fails on this head because ## Issue Number reads N/A and the checker requires a linked issue. That context is not in the ruleset's required set, so it does not block merge, but the check stays red until an issue is linked.

Verdict on the configuration and documentation itself: the npm/pip cooldowns, the uv cutoff, and the evidence/exception rules are accurate and consistent with the sources cited. Only finding 1 changes a merge decision, and it is a small correction.

🔄 CHANGES REQUESTED

Comment thread .agents/skills/custom-codereview-guide.md
Comment thread pyproject.toml
Co-authored-by: openhands <openhands@all-hands.dev>
@enyst
enyst requested a review from all-hands-bot October 22, 2026 04:16

@all-hands-bot all-hands-bot 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.

This review was posted by an AI agent (OpenHands).

Scope gate: the four changed paths are repository-owned dependency configuration (pyproject.toml, .github/dependabot.yml) and review/contributor policy docs (AGENTS.md, .agents/skills/custom-codereview-guide.md). In scope, no product/architecture decision needed.

Re-established state (fresh pass, head moved): head is 7b080ab6e8b3e1fbe3080f423e7c287263ede7b7, PR open, labels type: chore. Every current-head check is green, including test, sync-extensions, validate-claude-code, and Validate PR description (now linked to issue #820, which carries ready-for-dev and priority:low). My earlier review was on 481398c; the author's follow-up pushed a new head, so this is a new review of the new code.

Both prior findings are resolved on this head

  • The temporary-git-pin/unreleased-API merge blocker is restored verbatim (guide lines 120-122), matching base wording, together with the package-manager/runtime installation instruction.
  • The exclude-newer guard now carries an exemption: exclude-newer-package = { openhands-sdk = false } (pyproject.toml:39). Verified that false disables the cutoff for that name: uv lock resolves openhands-sdk 1.57.0 while third-party packages stay filtered (e.g. litellm 1.105.1, not the 1.106.2 uploaded 2026-10-21).
  • The declared floor is well chosen: required-version = ">=0.9.25" is exactly the release that added per-package exclude-newer disabling (astral-sh/uv#16854); relative durations landed earlier in 0.9.17, so 0.9.25 covers both. uv lock --check exits 0 with 145 packages, and the enforcement is real: an impossible required-version makes both uv lock and uv sync exit with an error. python scripts/sync_extensions.py --check passes with the pre-existing non-blocking coverage warning, and the focused tests pass (44 passed). I did not run the full suite.

Finding (blocking): the single-name exemption skews the first-party versions in the repository's own documented commands.

[tool.uv] is repo-wide, so it applies to every uv run in this repository, not just the test dependency group. AGENTS.md:139 documents uv run --with openhands-tools --with openhands-workspace --with openhands-agent-server python ... (and AGENTS.md:137 the plugin form) as the way to validate SDK imports. Run from the repository root on this head, only openhands-sdk is exempt, so the command now resolves a mixed set, while the same command in a directory without the cutoff resolves a coherent one:

  • this head, repo root: openhands-sdk 1.57.0, openhands-tools 1.54.0, openhands-workspace 1.54.0, openhands-agent-server 1.54.0
  • same command, no cutoff: all four at 1.57.0

So the documented validation command no longer exercises a released, coherent set of first-party packages, which is the thing AGENTS.md:139 exists to check. The author's rationale scoped the exemption to "the direct first-party test dependency", but the setting's reach is the whole repository, so the effect is broader than the stated intent. This also diverges from the review policy's blanket first-party exemption (skills/code-review/SKILL.md). The smallest correction is to exempt the first-party family that these commands install (openhands-sdk, openhands-tools, openhands-workspace, openhands-agent-server), or, if only the test dependency should be exempt, say in AGENTS.md that the resolver guard is deliberately stricter than the review rule so the skew is intentional and documented.

Minor, non-blocking: AGENTS.md:242 says tool.uv.required-version "also guards direct uv sync and uv lock use outside Make." This repository has no Makefile (none exists anywhere in the tree, and none appears in history), so "outside Make" refers to nothing here and reads as copied from a repository that does have one. The substance of the sentence is correct; drop the Make clause.

The npm/pip Dependabot cooldowns, the uv cutoff, the restored blocker, and the evidence/exception rules are accurate and verified. Only the exemption-scope finding changes a merge decision, and it is a small correction.

🔄 CHANGES REQUESTED

Comment thread pyproject.toml Outdated
Co-authored-by: openhands <openhands@all-hands.dev>
@enyst
enyst requested a review from all-hands-bot October 24, 2026 23:26
Co-authored-by: openhands <openhands@all-hands.dev>

@all-hands-bot all-hands-bot 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.

This review was posted by an AI agent (OpenHands).

Fresh review of head 6238c99 (state re-read immediately before publishing: PR open, head matches, issue #820 open with ready-for-dev/priority:low, no comments after the previous review, all head CI checks green).

Scope: In scope for this repository. The change covers only its own dependency-intake surfaces: npm/pip Dependabot cooldowns, the local uv resolver config, and the contributor/reviewer guidance in AGENTS.md and .agents/skills/custom-codereview-guide.md. The diff is limited to exactly the four files issue #820 scopes; the github-actions entry, catalogs, generated skills, and package versions remain untouched per the issue's non-goals.

Since the previous review (on 7963f4b): one commit, "docs(deps): simplify lockfile guidance", which shortens an AGENTS.md bullet by removing the note that repository resolver settings do not protect downstream pip install/uv tool install consumers and do not retroactively validate existing locks. The operative instruction is retained ("Use the committed lock for reproducible installs; review newly resolved artifacts before committing a lock update"), and documenting downstream propagation was an explicit non-goal of issue #820, so no required rule is weakened. The temporary-git-pin/unreleased-API merge blocker and the maintainer-approval exception rules remain in place.

Verification on this head:

  • .github/dependabot.yml adds cooldown.default-days: 7 to exactly the npm and pip entries; the github-actions entry is unchanged. Head CI is green (test, check, sync-extensions, sync-sdk-skill, PR description/title validation).
  • pyproject.toml [tool.uv] (required-version >=0.9.25, exclude-newer = "7 days", four named first-party exclude-newer-package entries) parses cleanly; uv lock --check resolves 145 packages, the lock stays gitignored/untracked, and the working tree is clean. Previously measured on this configuration with real uv: youngest third-party artifact 7.2 days, first-party openhands-sdk 1.58.0 (2.3 days) exempted by name only.
  • The 0.9.25 floor is justified against uv's release history (exclude-newer-package landed in 0.9.25, relative exclude-newer durations in 0.9.17).
  • Focused tests re-run in the workspace: 126 catalog/sync tests pass; sync_extensions.py --check passes with only the pre-existing non-blocking issue-duplicate-checker coverage warning, which exists identically on main and is not introduced by this PR.

Non-blocking observation (documented residual gap, unchanged by this commit): with a real uv 0.9.24, the parser warns on the exclude-newer-package table and prints required-version but still resolves the full dependency set without any cutoff. required-version cannot hard-fail the very parser it would need to reject, so within these four files the mitigation is the documented uv --version check, which AGENTS.md already states. This is a uv tool limitation rather than a defect in this change.

No material issues found.

✅ APPROVED

@enyst
enyst merged commit bcb411d into OpenHands:main Oct 25, 2026
13 checks passed
@github-actions

Copy link
Copy Markdown

🧹 PR Artifact Cleanup Queued

The .pr/ directory reached main after merge. A cleanup PR has been opened or updated: #842

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: chore Maintenance / chores

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Close seven-day npm/PyPI dependency intake gaps

3 participants