From 55ef450fdafc39514b0ec826c069849b3638786a Mon Sep 17 00:00:00 2001 From: Joost de Valk Date: Fri, 11 Sep 2026 08:08:30 +0200 Subject: [PATCH 1/2] add(considered): 419 Purpose Declined is a draft no client acts on draft-ietf-httpbis-pre-denied (revised 2026-09-09) defines 419 for refusing a request by its declared Sec-Purpose. Recorded as too-early: unregistered at IANA, no client treats it differently from any other refusal, Sec-Purpose itself is Limited availability, and 419 collides with Laravel's unofficial "Page Expired". Co-Authored-By: Claude Opus 5 (1M context) --- .../considered/purpose-declined-419.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/content/considered/purpose-declined-419.md diff --git a/src/content/considered/purpose-declined-419.md b/src/content/considered/purpose-declined-419.md new file mode 100644 index 00000000..c0494e1c --- /dev/null +++ b/src/content/considered/purpose-declined-419.md @@ -0,0 +1,22 @@ +--- +title: "419 Purpose Declined (draft-ietf-httpbis-pre-denied)" +date: "2026-09-11" +reason: too-early +revisit: "The draft reaching RFC with 419 registered at IANA, and a client — a browser, or a declared-purpose crawler — treating a 419 differently from any other refusal. `Sec-Purpose` gaining a purpose beyond prefetch that sites have real reason to decline would make that far more likely." +sources: + - title: "draft-ietf-httpbis-pre-denied — the 419 (Purpose Declined) status code" + url: "https://datatracker.ietf.org/doc/draft-ietf-httpbis-pre-denied/" + publisher: "IETF" + - title: "Fetch Standard — `Sec-Purpose` header" + url: "https://fetch.spec.whatwg.org/#sec-purpose-header" + publisher: "WHATWG" + - title: "MDN — Sec-Purpose" + url: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Purpose" + publisher: "MDN" +--- + +The draft defines status code 419 (Purpose Declined): the server is refusing a request because of the purpose it declared in its `Sec-Purpose` header. Today the only purpose that header carries is `prefetch`, so in practice this is a way for a server to say "I will serve this page when someone navigates to it, but not speculatively". The response is meant to be empty and uncacheable, since no one is supposed to see it. It is an HTTP Working Group document — adopted in April 2026 and revised on 9 September — intended for Proposed Standard. + +It is too early on three counts. First, it is a draft: 419 is still unassigned in the IANA status-code registry. Second, no client acts on it. A browser already discards a speculative response that is not a success, so a 419 today does exactly what a 503 or a 403 does, and no browser, CDN or crawler documents treating it any differently. Third, the header it hangs off is itself limited: `Sec-Purpose` is sent by Chromium for speculation-rules prefetches and by Firefox for ``, and not by Safari except behind a flag. The number carries baggage too. Laravel has long answered a failed CSRF check with an unofficial "419 Page Expired", so most 419s on the web today mean something else entirely, and the draft does not yet address that. + +A site that wants to refuse speculative loads can do it now, without waiting: `Sec-Purpose` lets it tell those requests apart, and any non-success status declines them. This site reads the header for exactly that reason, to keep prefetches out of its crawler statistics (see [speculation rules](/spec/performance/speculation-rules/)). The entry is the reference case for a narrower rule than "is it final": a status code earns a recommendation only when some client behaves differently on receiving it. A new code that every client treats like an existing one gives the refusal a name, but nothing yet responds to that name. From 70ae9e39d255e873ded54218125f907c99072589 Mon Sep 17 00:00:00 2001 From: Joost de Valk Date: Fri, 11 Sep 2026 19:03:22 +0200 Subject: [PATCH 2/2] Explain the operational value of Purpose Declined --- src/content/considered/purpose-declined-419.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/content/considered/purpose-declined-419.md b/src/content/considered/purpose-declined-419.md index c0494e1c..73b78fc1 100644 --- a/src/content/considered/purpose-declined-419.md +++ b/src/content/considered/purpose-declined-419.md @@ -2,7 +2,7 @@ title: "419 Purpose Declined (draft-ietf-httpbis-pre-denied)" date: "2026-09-11" reason: too-early -revisit: "The draft reaching RFC with 419 registered at IANA, and a client — a browser, or a declared-purpose crawler — treating a 419 differently from any other refusal. `Sec-Purpose` gaining a purpose beyond prefetch that sites have real reason to decline would make that far more likely." +revisit: "Registration of 419 at IANA and documented deployments using it to distinguish deliberate refusals of speculative requests in logs and monitoring. Operational adoption can establish its usefulness without new browser behaviour." sources: - title: "draft-ietf-httpbis-pre-denied — the 419 (Purpose Declined) status code" url: "https://datatracker.ietf.org/doc/draft-ietf-httpbis-pre-denied/" @@ -13,10 +13,13 @@ sources: - title: "MDN — Sec-Purpose" url: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-Purpose" publisher: "MDN" + - title: "HTTP Status Code Registry" + url: "https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml" + publisher: "IANA" --- -The draft defines status code 419 (Purpose Declined): the server is refusing a request because of the purpose it declared in its `Sec-Purpose` header. Today the only purpose that header carries is `prefetch`, so in practice this is a way for a server to say "I will serve this page when someone navigates to it, but not speculatively". The response is meant to be empty and uncacheable, since no one is supposed to see it. It is an HTTP Working Group document — adopted in April 2026 and revised on 9 September — intended for Proposed Standard. +The draft defines status code 419 (Purpose Declined): the server is refusing a request because of the purpose it declared in its `Sec-Purpose` header. Today that purpose is `prefetch`, so in practice it means "I am declining this speculative request". The draft recommends empty responses that cannot be reused from a cache, since no one is supposed to see them. It is an HTTP Working Group document, adopted in April 2026 and revised on 9 September, intended for Proposed Standard. -It is too early on three counts. First, it is a draft: 419 is still unassigned in the IANA status-code registry. Second, no client acts on it. A browser already discards a speculative response that is not a success, so a 419 today does exactly what a 503 or a 403 does, and no browser, CDN or crawler documents treating it any differently. Third, the header it hangs off is itself limited: `Sec-Purpose` is sent by Chromium for speculation-rules prefetches and by Firefox for ``, and not by Safari except behind a flag. The number carries baggage too. Laravel has long answered a failed CSRF check with an unofficial "419 Page Expired", so most 419s on the web today mean something else entirely, and the draft does not yet address that. +The intended benefit is operational. Servers already refuse speculative requests with codes such as 503 or 403, but those responses can look like service failures or access errors in logs and monitoring. A dedicated code lets operators distinguish deliberate refusals. The draft explicitly introduces no new client capability: its usefulness does not depend on a browser handling 419 differently. Clearer diagnostics are a valid benefit in their own right. -A site that wants to refuse speculative loads can do it now, without waiting: `Sec-Purpose` lets it tell those requests apart, and any non-success status declines them. This site reads the header for exactly that reason, to keep prefetches out of its crawler statistics (see [speculation rules](/spec/performance/speculation-rules/)). The entry is the reference case for a narrower rule than "is it final": a status code earns a recommendation only when some client behaves differently on receiving it. A new code that every client treats like an existing one gives the refusal a name, but nothing yet responds to that name. +The reason for `too-early` is its status and limited deployment evidence. It remains a draft, 419 is unassigned in the IANA registry, and we have not found documented deployments using it to make that operational distinction. The request signal also has support limits: Chromium sends `Sec-Purpose` for speculation-rules prefetches, Firefox for ``, and Safari only behind a flag. This site reads the header to keep prefetches out of its crawler statistics (see [speculation rules](/spec/performance/speculation-rules/)). Registration and operational adoption would justify revisiting a recommendation.