Skip to content

Include created_at in compact index /info endpoint#6380

Open
marcbest wants to merge 4 commits intorubygems:masterfrom
marcbest:feature/compact-index-created-at
Open

Include created_at in compact index /info endpoint#6380
marcbest wants to merge 4 commits intorubygems:masterfrom
marcbest:feature/compact-index-created-at

Conversation

@marcbest
Copy link
Copy Markdown

@marcbest marcbest commented Apr 1, 2026

Problem

Supply chain attacks targeting package registries are a growing concern. Other package managers have already shipped minimum age features — npm, pnpm, and yarn all allow users to reject recently published versions during resolution.

Bundler currently has no equivalent. Adding one requires knowing when each gem version was published, but the compact index has no publication timestamp. Without it, clients must make a separate V1 API call per gem (/api/v1/versions/<gem>.json) — adding seconds of latency and hitting the RubyGems.org rate limit (10 req/s) on projects with 50+ gems.

The compact index /info endpoint already carries all the version data Bundler needs during resolution — except created_at.

Solution

Pass the version's created_at (already in the SQL query) to CompactIndex::GemVersion.new as the 8th argument, formatted as ISO 8601 UTC.

Before:

name, platform, checksum, info_checksum, ruby_version, rubygems_version, = r
CompactIndex::GemVersion.new(name, platform, Version._sha256_hex(checksum),
  info_checksum, deps, ruby_version, rubygems_version)

After:

name, platform, checksum, info_checksum, ruby_version, rubygems_version, created_at, = r
CompactIndex::GemVersion.new(name, platform, Version._sha256_hex(checksum),
  info_checksum, deps, ruby_version, rubygems_version, created_at&.utc&.iso8601)

The created_at column is already selected in the requirements_and_dependencies query, included in the GROUP BY, and used for ORDER BY. It just wasn't being passed through.

Info line output

1.0.0 rack:>= 1.0|checksum:abc123,ruby:>= 2.7.0,created_at:2024-05-01T12:00:00Z

Old clients ignore unknown requirement fields, so this is fully backwards compatible.

Dependencies

Requires rubygems/compact_index#183 — adds created_at as an optional 8th field to GemVersion struct.

@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 8, 2026

📝 We need to pick rubygems/compact_index#183 into this PR after merging #6404

@tenderlove
Copy link
Copy Markdown
Contributor

@marcbest do you mind rebasing? If looks like #6404 landed

@hsbt hsbt force-pushed the feature/compact-index-created-at branch from d780667 to eff42b2 Compare April 8, 2026 23:51
@colby-swandale
Copy link
Copy Markdown
Member

@hsbt where are we at with the cooldown discussion on RubyGems CLI? Is this work going ahead? Any idea on timeline?

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.50%. Comparing base (72312b4) to head (64ae839).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6380      +/-   ##
==========================================
- Coverage   97.06%   94.50%   -2.56%     
==========================================
  Files         494      494              
  Lines       10502    10562      +60     
==========================================
- Hits        10194     9982     -212     
- Misses        308      580     +272     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 9, 2026

@colby-swandale ruby/rubygems#9113 is only place that. But I haven't decided how to implement the cooldown option/configuration yet.

@hsbt hsbt force-pushed the feature/compact-index-created-at branch from dcab294 to 5abddbb Compare April 9, 2026 01:02
@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 9, 2026

We need to handle https://rubygems.org/gems/gem_server_conformance/ for this PR. I will do that at another pull request.

@hsbt hsbt force-pushed the feature/compact-index-created-at branch 4 times, most recently from 7fc5b6c to 86e960d Compare April 9, 2026 03:39
@colby-swandale
Copy link
Copy Markdown
Member

@jenshenny before this merges, I think we need a rollout plan that accounts for a full compact index regeneration, which as far as I know hasn't happened since the initial population.

marcbest and others added 3 commits April 9, 2026 17:42
Pass the version's created_at timestamp to CompactIndex::GemVersion
so it is included in the /info response. The timestamp is formatted
as ISO 8601 UTC.

This enables Bundler clients to read publication dates from the
compact index directly, avoiding separate V1 API calls per gem when
implementing supply chain security features like min_age checks.

Depends on rubygems/compact_index adding created_at as an optional
8th field to the GemVersion struct.
Add a created_at field to the GemVersion struct so that the /info
endpoint can include the publication timestamp for each gem version.

When present, created_at is appended to the requirements section of
the info line. When nil, the field is omitted for backwards
compatibility.
Port the rspec tests from rubygems/compact_index#183 to minitest,
covering created_at presence, coexistence with other fields, and
nil omission.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@hsbt hsbt force-pushed the feature/compact-index-created-at branch 3 times, most recently from 26c1374 to d071c63 Compare April 9, 2026 09:03
The compact index info endpoint now includes created_at timestamps,
so the expected output in tests needs to account for this by
dynamically including each version's created_at value.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@hsbt hsbt force-pushed the feature/compact-index-created-at branch from d071c63 to 64ae839 Compare April 9, 2026 09:19
@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 9, 2026

Now all of related tests are fixed.

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

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

4 participants