Skip to content

feat(spec,gates): require the standards-track RateLimit header fields - #105

Open
ucekmez wants to merge 1 commit into
feat/rfc9457-problem-detailsfrom
feat/ietf-ratelimit-headers
Open

feat(spec,gates): require the standards-track RateLimit header fields#105
ucekmez wants to merge 1 commit into
feat/rfc9457-problem-detailsfrom
feat/ietf-ratelimit-headers

Conversation

@ucekmez

@ucekmez ucekmez commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

PR 13 of a stacked series. Base is #104. Not for merge without review.

§13 mandated X-RateLimit-Limit / -Remaining / -Reset — the de-facto convention inherited from early IETF drafts.

X--prefixed header names have been discouraged since RFC 6648 (2012). Mandating them on their own is a predictable finding on the IETF path this project intends to take at v0.2. The standards-track form is RateLimit and RateLimit-Policy from draft-ietf-httpapi-ratelimit-headers, active in the httpapi WG (draft-11, May 2026).

Both forms are kept

Removing X-RateLimit-* would break deployed clients for no functional gain. So §13 now requires the standards-track fields and keeps the de-facto ones as a compatibility SHOULD — plus a rule that matters: when both are present they MUST describe the same quota. An implementation that lets them drift is worse than one that sends only one form.

RateLimit: "sub"; r=87; t=120
RateLimit-Policy: "sub"; q=100; w=3600
Retry-After: 120

X-RateLimit-Limit: 100          # compatibility, SHOULD
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1708168200

What changed

  • §13 rewrittenRateLimit reports current state (r remaining, t seconds to reset), RateLimit-Policy describes the quota (q, w), Retry-After MUST accompany a 429.
  • build429Response emits RateLimit always, and RateLimit-Policy + the X-RateLimit-* trio when a quota is known. On a 429 the remaining quota is zero by definition, which the tests pin.
  • compliance-cli probes the standards-track fields as failures and the X- form as an optional skip — previously it probed only for X-RateLimit-Limit, which would have kept EEP pinned to the discouraged names indefinitely.

Scope

  • Spec / schema only
  • TypeScript package(s)
  • Python package(s)
  • Tests / CI
  • Docs / examples

Checklist

  • I read CONTRIBUTING.md and CODE_OF_CONDUCT.md.
  • Tests added or updated where appropriate.
  • Breaking change? Nothing removed — X-RateLimit-* still emitted. New normative MUST for the standards-track fields, so publishers that send only the X- form will newly fail the §13 probe. Worth a CHANGELOG line.
  • Documentation updated for user-visible behavior.

Verification

Suite Result
@eep-dev/gates 491 passed (was 486)
@eep-dev/compliance-cli 73 passed
tests/ 187 passed
codegen-schema-types --check no drift

Notes for reviewers

The draft is not yet an RFC. draft-ietf-httpapi-ratelimit-headers is an active Internet-Draft, not a published RFC, and its field syntax changed across revisions — earlier drafts defined three separate RateLimit-Limit/-Remaining/-Reset fields, the current one defines two structured fields. I've implemented the current (draft-11) two-field form. If the WG changes it again this will need a revision; pinning to the current draft still seems better than staying on a convention RFC 6648 discourages.

The quota policy name is hardcoded as "eep" in build429Response. A publisher with several named policies will want to pass its own; I did not add the parameter because nothing in-tree needs it yet and I'd rather not invent an API surface speculatively. Easy to add.

No middleware change@eep-dev/middleware does not implement rate limiting at all today, so there is no place to emit these from. The spec text plus the conformance probe is what makes it checkable.

Copilot AI lite review requested due to automatic review settings August 26, 2026 19:30

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

§13 mandated `X-RateLimit-Limit` / `-Remaining` / `-Reset` — the
de-facto convention inherited from early drafts. `X-`-prefixed header
names have been discouraged since RFC 6648 (2012), and mandating them
on their own would be a predictable finding on the IETF path this
project intends to take at v0.2.

The standards-track form is `RateLimit` and `RateLimit-Policy`
(draft-ietf-httpapi-ratelimit-headers, active in the httpapi WG).

Both forms are kept. Removing `X-RateLimit-*` would break deployed
clients for no functional gain, so §13 now requires the standards-track
fields and keeps the de-facto ones as a compatibility SHOULD, with a
rule that when both are present they MUST describe the same quota — an
implementation that lets them drift is worse than one that sends only
one.

Changes:
- §13 rewritten: `RateLimit` reports current state (`r` remaining, `t`
  seconds to reset), `RateLimit-Policy` describes the quota (`q`, `w`),
  `Retry-After` MUST accompany a 429.
- `build429Response` emits `RateLimit` always, and `RateLimit-Policy`
  plus the `X-RateLimit-*` trio when a quota is known. On a 429 the
  remaining quota is zero by definition.
- compliance-cli probes the standards-track fields as failures and the
  `X-` form as an optional skip, rather than probing only for `X-`.

Refs: EEP audit 2026-08 finding B8
Signed-off-by: Ugur Cekmez <ucekmez@gmail.com>
@ucekmez
ucekmez force-pushed the feat/rfc9457-problem-details branch from 4245e37 to 11bd504 Compare August 26, 2026 19:39
@ucekmez
ucekmez force-pushed the feat/ietf-ratelimit-headers branch from 6d6fb69 to 51e2c2b Compare August 26, 2026 19:39
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