<!-- HEADER:START - Do not remove or modify this section -->
<div align="center">
  <img src="https://raw.githubusercontent.com/thymianofficial/thymian/main/astro-docs/src/assets/logo.svg" alt="Thymian Logo" width="200"/>

# Thymian

**Add resilience and HTTP conformance to your API development workflow**

[![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-green.svg)](https://github.com/thymianofficial/thymian/blob/main/LICENSE)
[![CI](https://github.com/thymianofficial/thymian/actions/workflows/ci.yaml/badge.svg)](https://github.com/thymianofficial/thymian/actions/workflows/ci.yaml)
[![Documentation](https://img.shields.io/badge/docs-thymian.dev-green.svg)](https://thymian.dev)
[![Discord](https://img.shields.io/discord/1440702693768429791?logo=discord&label=Discord&color=5865F2)](https://discord.gg/TRSwCxbz9f)
[![Reddit](https://img.shields.io/badge/Reddit-ThymianOfficial-FF4500?logo=reddit)](https://www.reddit.com/r/ThymianOfficial/)
[![Twitter](https://img.shields.io/badge/Twitter-@thymiandev-1DA1F2?logo=x)](https://x.com/thymiandev)

</div>
<!-- HEADER:END -->

## @thymian/rules-rfc-9110

A rule set that enforces HTTP semantics defined in RFC 9110 (HTTP Semantics). Validates that API requests and responses conform to standards for methods, status codes, headers, content negotiation, and caching directives — the same rules work across `lint`, `test`, and `analyze`.

## Installation

```bash
npm install @thymian/rules-rfc-9110
```

> **Getting started with Thymian?** See the [main Thymian package](https://www.npmjs.com/package/thymian) for quick installation and first-run instructions.

<!-- COVERAGE:START - Generated by `nx run rules-rfc-9110:generate-coverage`. Do not edit by hand. -->

## Coverage

**120 of 138** units covered, by **397** rule(s).

- Source: RFC 9110 (June 2022)
- Counting rule: One unit per numbered section carrying at least one BCP 14 requirement-level keyword (MUST, MUST NOT, SHALL, SHALL NOT, SHOULD, SHOULD NOT, MAY, REQUIRED, RECOMMENDED, NOT RECOMMENDED, OPTIONAL) addressed to an HTTP participant.
- Substitute: section

Not yet covered:

- `14` — Range Requests
- `2.2` — Requirements Notation
- `2.3` — Length Requirements
- `2.4` — Error Handling
- `3.3` — Connections, Clients, and Servers
- `3.8` — Caches
- `4.3.3` — https Origins
- `8.3.1` — Media Type
- `12.4.2` — Quality Values
- `16.1.1` — Method Registry
- `16.2.1` — Status Code Registry
- `16.3.1` — Field Name Registry
- `16.3.2.1` — Considerations for New Field Names
- `16.4.1` — Authentication Scheme Registry
- `16.4.2` — Considerations for New Authentication Schemes
- `16.5.1` — Range Unit Registry
- `16.6.1` — Content Coding Registry
- `16.7` — Upgrade Token Registry

## Severity map

| Severity | Keyword | recommended | strict | minimal |
| -------- | ------- | ----------- | ------ | ------- |
| error    | MUST    | 174         | 174    | 88      |
| warn     | SHOULD  | 105         | 108    | 0       |
| hint     | MAY     | 101         | 110    | 0       |
| off      | (off)   | 22          | 10     | 314     |

## Conventions

None.

## Rule verdicts

### authentication

| Rule                                                                         | static                         | analytics                      | test                                   |
| ---------------------------------------------------------------------------- | ------------------------------ | ------------------------------ | -------------------------------------- |
| rfc9110/origin-server-should-send-401-for-invalid-credentials                | impossible (only-origin-knows) | impossible (only-origin-knows) | impossible (only-origin-knows)         |
| rfc9110/proxy-should-send-407-for-invalid-proxy-credentials                  | impossible (only-origin-knows) | impossible (only-origin-knows) | impossible (only-origin-knows)         |
| rfc9110/proxy-must-not-modify-authentication-info                            | impossible (not-representable) | observable                     | impossible (participant-not-reachable) |
| rfc9110/proxy-must-not-modify-authorization                                  | impossible (not-representable) | observable                     | impossible (participant-not-reachable) |
| rfc9110/proxy-must-not-modify-www-authenticate                               | impossible (not-representable) | observable                     | impossible (participant-not-reachable) |
| rfc9110/server-may-send-www-authenticate-in-other-responses                  | observable                     | observable                     | observable                             |
| rfc9110/authentication-parameter-name-must-occur-once-per-challenge          | impossible (not-representable) | observable                     | observable                             |
| rfc9110/authentication-scheme-must-accept-token-and-quoted-string            | impossible (nothing-to-check)  | impossible (nothing-to-check)  | impossible (nothing-to-check)          |
| rfc9110/proxy-authenticate-applies-to-next-client                            | impossible (nothing-to-check)  | impossible (nothing-to-check)  | impossible (nothing-to-check)          |
| rfc9110/proxy-may-relay-credentials                                          | impossible (tool-limitation)   | impossible (tool-limitation)   | impossible (tool-limitation)           |
| rfc9110/realm-parameter-must-use-quoted-string-syntax                        | impossible (not-representable) | observable                     | observable                             |
| rfc9110/user-agent-may-reuse-same-credentials-for-identical-protection-space | impossible (tool-limitation)   | impossible (tool-limitation)   | impossible (tool-limitation)           |

### conditional-requests

| Rule                                                                                                 | static                           | analytics                              | test                                   |
| ---------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------------- | -------------------------------------- |
| rfc9110/non-origin-server-must-not-evaluate-conditional-headers                                      | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/server-must-evaluate-preconditions-after-normal-checks                                       | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/server-must-evaluate-preconditions-in-correct-order                                          | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/server-must-ignore-conditionals-for-connect-options-trace                                    | observable                       | observable                             | impossible (condition-not-producible)  |
| rfc9110/server-must-ignore-preconditions-for-non-2xx-412-responses                                   | impossible (not-representable)   | impossible (requires-controlled-input) | observable                             |
| rfc9110/cache-or-intermediary-may-ignore-if-match                                                    | impossible (not-representable)   | observable                             | impossible (participant-not-reachable) |
| rfc9110/client-may-send-if-match-header                                                              | impossible (not-representable)   | observable                             | impossible (condition-not-producible)  |
| rfc9110/origin-server-may-respond-with-2xx-response-even-condition-failed                            | observable                       | observable                             | observable                             |
| rfc9110/origin-server-may-respond-with-412-response-to-conditional-request                           | observable                       | impossible (requires-controlled-input) | observable                             |
| rfc9110/origin-server-must-evaluate-if-match-before-method                                           | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-must-not-perform-method-when-if-match-fails                                    | impossible (not-representable)   | impossible (requires-controlled-input) | observable                             |
| rfc9110/origin-server-must-use-strong-comparison-for-if-match                                        | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-should-evaluate-if-modified-since                                              | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-should-respond-304-when-if-modified-since-false                                | observable                       | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-must-ignore-if-modified-since-for-non-get-head                                     | observable                       | observable                             | impossible (condition-not-producible)  |
| rfc9110/recipient-must-ignore-if-modified-since-header-if-no-date-available                          | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)         |
| rfc9110/recipient-must-ignore-if-modified-since-when-if-none-match-present                           | observable                       | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-must-interpret-if-modified-since-value-in-terms-of-servers-clock                   | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/client-should-generate-if-none-match-for-cache-updates                                       | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-must-evaluate-if-none-match-before-method                                      | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-must-respond-304-or-412-when-if-none-match-fails                               | observable                       | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-must-use-weak-comparison-for-if-none-match                                         | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/client-must-not-generate-if-range-header-containing-http-date                                | impossible (not-representable)   | observable                             | impossible (condition-not-producible)  |
| rfc9110/client-must-not-generate-if-range-with-weak-etag                                             | impossible (not-representable)   | observable                             | impossible (condition-not-producible)  |
| rfc9110/client-must-not-generate-if-range-without-range                                              | observable                       | observable                             | impossible (condition-not-producible)  |
| rfc9110/origin-server-must-ignore-if-range-header-if-target-resource-does-not-support-range-requests | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)         |
| rfc9110/recipient-must-ignore-range-when-if-range-false                                              | impossible (not-representable)   | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-should-process-range-header-if-if-range-matches                                    | impossible (nothing-to-check)    | impossible (nothing-to-check)          | impossible (nothing-to-check)          |
| rfc9110/server-must-evaluate-if-range                                                                | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/server-must-ignore-if-range-without-range                                                    | observable                       | observable                             | observable                             |
| rfc9110/cache-or-intermediary-may-ignore-if-unmodified-since                                         | impossible (not-representable)   | observable                             | impossible (participant-not-reachable) |
| rfc9110/client-may-send-if-unmodified-since-header                                                   | observable                       | observable                             | impossible (condition-not-producible)  |
| rfc9110/origin-server-may-respond-with-2xx-response-even-condition-failed-for-unmodified-since       | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)         |
| rfc9110/origin-server-may-respond-with-412-response-to-unmodified-since                              | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)         |
| rfc9110/origin-server-must-evaluate-if-unmodified-since                                              | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |
| rfc9110/origin-server-must-not-perform-method-when-if-unmodified-since-fails                         | impossible (not-representable)   | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-must-ignore-if-unmodified-since-header-if-no-date-available                        | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)         |
| rfc9110/recipient-must-ignore-if-unmodified-since-when-if-match-present                              | impossible (not-representable)   | impossible (requires-controlled-input) | observable                             |
| rfc9110/recipient-must-interpret-if-unmodified-since-value-in-terms-of-servers-clock                 | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)       |

### content-negotiation

| Rule                                                                              | static                           | analytics                        | test                                   |
| --------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------- |
| rfc9110/user-agent-may-associate-quality-value-with-charset                       | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/codings-value-may-be-given-quality-value                                  | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/origin-server-should-send-response-without-content-coding                 | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/server-must-not-include-accept-encoding-for-non-content-coding-415-errors | observable                       | observable                       | observable                             |
| rfc9110/user-agent-must-not-send-accept-language-without-user-control             | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/recipient-should-process-q-parameter-as-weight                            | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-should-send-q-parameter-last                                       | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/cache-must-not-use-response-without-matching-vary-headers                 | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/origin-server-should-generate-vary-header                                 | observable                       | observable                       | observable                             |
| rfc9110/proxy-must-not-generate-vary-wildcard                                     | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/user-agent-may-send-preference-headers-for-proactive-negotiation          | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |

### fields

| Rule                                                                                    | static                           | analytics                        | test                                   |
| --------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------- |
| rfc9110/recipient-must-accept-all-http-date-formats                                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/recipient-must-interpret-two-digit-years-correctly                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-must-generate-timestamps-in-imf-fixdate-format                           | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/sender-must-not-generate-additional-whitespace-in-http-date                     | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/recipient-must-accept-lists-with-empty-elements                                 | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/recipient-must-parse-and-ignore-empty-list-elements                             | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-must-not-generate-empty-list-elements                                    | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/recipient-must-handle-quoted-pairs-correctly                                    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-should-not-generate-quoted-pairs-except-for-dquote-backslash             | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-should-not-generate-quoted-pairs-in-comments-except-for-parens-backslash | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/implementation-may-remove-bws-before-processing                                 | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/implementation-may-replace-ows-or-rws-with-single-sp                            | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/recipient-must-parse-and-remove-bws                                             | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-must-not-generate-bws                                                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-should-generate-ows-as-single-sp-when-readable                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-should-generate-rws-as-single-sp                                         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-should-not-generate-ows-except-when-needed                               | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-may-discard-oversized-field-lines                                        | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-must-respond-4xx-for-oversized-fields                                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-must-forward-unrecognized-header-fields                                   | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/recipient-should-ignore-unrecognized-fields                                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/proxy-must-not-change-field-line-order                                          | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/recipient-may-combine-field-lines-with-same-name                                | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-must-not-generate-multiple-field-lines-unless-allowed                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-not-apply-request-until-entire-header-received                      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/new-fields-should-limit-values-to-visible-ascii                                 | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)          |
| rfc9110/parser-must-exclude-whitespace-from-field-values                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/recipient-may-retain-ctl-characters-in-safe-contexts                            | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/recipient-must-reject-or-replace-invalid-characters                             | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/recipient-should-treat-obs-text-as-opaque-data                                  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |

### identifiers

| Rule                                                                          | static                           | analytics                        | test                                  |
| ----------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | ------------------------------------- |
| rfc9110/automated-client-must-log-error-to-audit-log-for-bad-certificate      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/automated-client-should-terminate-connection-for-bad-certificate      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/automated-clients-may-provide-setting-to-disable-certificate-check    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/automated-clients-must-provide-setting-to-enable-certificate-check    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-may-access-by-resolving-host-to-ip-address                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-must-construct-reference-identity                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-must-not-use-cn-id-reference-identity                          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-must-use-rfc6125-verification                                  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-must-verify-service-identity                                   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-must-handle-bad-certificate                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/recipient-must-reject-http-uri-without-host                           | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-must-not-generate-http-uri-with-empty-host                     | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/client-must-secure-https-requests-and-responses                       | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/recipient-must-reject-https-uri-without-host                          | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-must-not-generate-https-uri-with-empty-host                    | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/authority-should-not-use-equivalent-uris-for-distinct-resources       | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)        |
| rfc9110/http-component-may-perform-normalization                              | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/sender-recipient-should-support-8000-octet-uris                       | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/recipient-should-treat-userinfo-in-uri-from-untrusted-source-as-error | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-must-not-generate-userinfo-in-uri                              | observable                       | observable                       | impossible (condition-not-producible) |

### message-abstraction

| Rule                                                                               | static                           | analytics                        | test                                  |
| ---------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | ------------------------------------- |
| rfc9110/client-must-retain-knowledge-of-request                                    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-may-send-lower-version-for-broken-servers                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/client-must-not-send-non-conformant-version                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-should-send-highest-conformant-version                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/recipient-should-process-higher-minor-version-as-highest-known             | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/server-must-not-send-non-conformant-version                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/server-should-send-response-version-equal-to-highest-conformant            | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/each-http-version-defines-own-framing                                      | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/implicit-framing-allowed-for-backwards-compatibility                       | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/message-complete-when-framed-octets-available                              | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/header-field-term-for-header-section-only-fields                           | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/header-fields-sent-before-content                                          | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/header-section-consists-of-field-lines                                     | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/origin-server-may-generate-date-for-1xx-5xx                                | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/origin-server-with-clock-must-generate-date-for-2xx-3xx-4xx                | observable                       | observable                       | observable                            |
| rfc9110/origin-server-without-clock-must-not-generate-date                         | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)        |
| rfc9110/recipient-may-replace-invalid-date                                         | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/recipient-with-clock-must-add-date-if-missing                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/sender-should-generate-date-at-message-generation                          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-may-send-date-header-in-request                                 | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-should-generate-trailer-header-when-sending-trailers                | impossible (not-representable)   | observable                       | observable                            |
| rfc9110/recipient-may-treat-the-set-of-received-trailer-fields-as-name-value-pairs | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/recipient-must-not-merge-trailers-unsafely                                 | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/sender-must-not-generate-trailer-unless-permitted                          | impossible (tool-limitation)     | observable                       | impossible (condition-not-producible) |
| rfc9110/server-should-not-generate-necessary-trailers                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/trailer-fields-must-be-defined-as-list-if-repeatable                       | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |

### message-context

| Rule                                                                                                         | static                           | analytics                        | test                                  |
| ------------------------------------------------------------------------------------------------------------ | -------------------------------- | -------------------------------- | ------------------------------------- |
| rfc9110/client-may-proceed-to-send-content-without-receiving-100-response                                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/client-must-not-generate-100-continue-without-content                                                | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/client-must-send-expect-header-for-100-response                                                      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-should-not-wait-for-an-indefinite-period-for-100-response                                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/client-should-repeat-request-without-expect-for-417                                                  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/origin-server-must-not-wait-for-content-before-100-continue                                          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/origin-server-must-respond-immediately-to-100-continue-request                                       | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/proxy-may-generate-immediate-100-response                                                            | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/proxy-must-handle-100-continue-expectation                                                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/server-may-omit-sending-100-response-if-already-received-content                                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/server-may-respond-with-417-response-for-other-expect-than-100-continue                              | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/server-must-ignore-100-continue-in-http-1.0                                                          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/server-must-send-final-status-after-100-continue                                                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/server-should-indicate-if-closing-the-connection-when-sending-final-status-code-without-full-request | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/robotic-user-agent-should-send-valid-from-header                                                     | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/server-should-not-use-from-for-authentication                                                        | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-should-not-send-from-without-configuration                                                | observable                       | observable                       | impossible (condition-not-producible) |
| rfc9110/intermediary-should-not-modify-referer-for-same-scheme-and-host                                      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-may-truncate-parts-other-than-referring-origin                                            | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/user-agent-must-exclude-referer-or-send-about-blank-for-no-source                                    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-must-not-include-fragment-or-userinfo-in-referer                                          | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/user-agent-must-not-send-referer-in-unsecured-request-from-secure-resource                           | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/user-agent-should-not-send-referer-for-secure-to-insecure                                            | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-must-send-te-connection-option-with-te-header                                                 | observable                       | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-must-not-generate-advertising-in-product-identifier                                           | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/sender-should-limit-generated-product-identifiers-to-necessity                                       | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/sender-should-not-generate-non-version-info-in-product-version                                       | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/user-agent-should-limit-addition-of-subproducts-by-third-parties                                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-should-not-generate-needlessly-fine-grained-detailed-user-agent-field                     | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |
| rfc9110/user-agent-should-send-user-agent-header                                                             | impossible (not-representable)   | observable                       | impossible (condition-not-producible) |
| rfc9110/origin-server-may-send-allow-header                                                                  | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)          |
| rfc9110/proxy-must-not-modify-allow-header                                                                   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/user-agent-must-inherit-fragment-for-3xx-without-fragment                                            | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/origin-server-may-generate-server-header-field                                                       | observable                       | observable                       | observable                            |
| rfc9110/origin-server-should-limit-addition-of-subproducts-by-third-parties                                  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)      |
| rfc9110/origin-server-should-not-generate-needlessly-fine-grained-detail-server-header                       | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)         |

### methods

| Rule                                                                                                             | static                           | analytics                        | test                                   |
| ---------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------- |
| rfc9110/general-purpose-servers-must-support-get-and-head                                                        | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/client-must-ignore-content-length-or-transfer-encoding-headers-in-response-to-connect                    | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-send-port-number-for-connect-request                                                         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/intermediary-must-attempt-to-send-outstanding-data-coming-from-closed-side-for-connect-request           | impossible (unknown)             | impossible (unknown)             | impossible (unknown)                   |
| rfc9110/origin-server-may-accept-connect-request                                                                 | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/server-must-not-send-transfer-encoding-or-content-length-headers-in-2xx-response-to-connect-request      | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-must-reject-connect-request-with-empty-or-invalid-port-number                                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-should-not-generate-content-for-delete-request                                                    | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/origin-server-should-not-rely-on-private-agreements-to-receive-content-in-delete-request                 | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/origin-server-should-send-correct-successful-status-code-to-delete-request                               | observable                       | observable                       | observable                             |
| rfc9110/cache-may-use-responses-to-get-for-satisfy-subsequent-get-and-head-requests                              | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-should-not-generate-content-in-get-request                                                        | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/origin-server-should-not-rely-on-private-agreements                                                      | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/cache-may-use-responses-to-head-for-satisfy-subsequent-head-requests                                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-should-not-generate-content-in-head-request                                                       | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/origin-server-should-not-rely-on-private-agreements-for-head-requests                                    | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/server-may-omit-header-fields-for-head-response                                                          | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-not-send-content-in-response-to-head                                                         | observable                       | observable                       | observable                             |
| rfc9110/server-should-send-same-header-fields-in-response-to-head                                                | observable                       | observable                       | observable                             |
| rfc9110/client-may-send-max-forwards-header-in-option-request                                                    | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/client-must-send-content-type-header-for-content-in-options-request                                      | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/proxy-must-not-generate-new-max-forwards-header                                                          | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/server-should-send-headers-indicating-optional-features-in-2xx-response-to-options-request               | observable                       | observable                       | observable                             |
| rfc9110/origin-server-may-redirect-for-existing-resource-for-201-response                                        | observable                       | observable                       | observable                             |
| rfc9110/origin-server-should-send-location-header-for-201-response                                               | observable                       | observable                       | observable                             |
| rfc9110/origin-server-must-not-sent-validator-field-in-response-to-put-request                                   | observable                       | observable                       | observable                             |
| rfc9110/origin-server-must-respond-with-correct-response-code-for-put-request                                    | observable                       | observable                       | observable                             |
| rfc9110/origin-server-must-send-3xx-response-if-state-change-should-be-applied-to-other-resource                 | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/origin-server-should-ingore-unrecognized-header-and-trailer-fields-received-in-put-request               | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/origin-server-should-response-with-409-or-415-status-code-to-put-request-for-inconsistent-representation | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/origin-server-should-verify-constraints-for-target-resource-for-put-request                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/service-that-selects-uri-for-client-should-use-post-instead-of-put                                       | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/user-agent-may-make-own-decision-to-redirect-request-for-3xx-response-to-put-request                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-must-not-generate-fields-containing-sensitive-data-in-trace-request                               | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/client-must-not-send-content-in-trace-request                                                            | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/final-recipient-of-trace-request-should-reflect-received-message                                         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/final-recipient-should-exclude-sensitive-request-data-from-response-to-trace                             | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/client-should-not-automatically-retry-a-failed-automatic-retry                                           | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-should-not-automatically-retry-request-with-non-idempotent-method                                 | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/origin-server-must-disable-safe-methods-for-unsafe-resources                                             | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/proxy-must-not-automatically-retry-non-idempontent-requests                                              | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/user-agent-distinguish-between-safe-and-unsafe-methods                                                   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/origin-server-should-send-405-response-for-unallowed-method                                              | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/origin-server-should-send-501-response-for-unrecognized-method                                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/other-methods-than-get-and-head-are-optional                                                             | impossible (nothing-to-check)    | impossible (nothing-to-check)    | impossible (nothing-to-check)          |

### range-requests

| Rule                                                                    | static                           | analytics                              | test                                  |
| ----------------------------------------------------------------------- | -------------------------------- | -------------------------------------- | ------------------------------------- |
| rfc9110/accept-ranges-may-be-sent-in-trailer                            | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/client-may-generate-range-requests-without-accept-ranges        | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/client-must-not-assume-future-range-support-from-accept-ranges  | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/server-may-send-accept-ranges-none                              | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/proxy-should-forward-206-with-unknown-range-unit                | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/recipient-must-not-recombine-206-with-unknown-range-unit        | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/recipient-must-not-recombine-invalid-content-range              | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/sender-should-indicate-complete-length-for-byte-ranges          | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/server-must-ignore-content-range-for-unsupported-method         | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/server-should-send-content-range-in-416-response                | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/origin-server-should-send-400-for-unsupported-partial-put       | observable                       | impossible (requires-controlled-input) | observable                            |
| rfc9110/recipient-must-anticipate-large-decimal-numerals-for-byte-range | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/client-should-list-multiple-ranges-in-ascending-order           | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/client-should-not-request-inefficient-multiple-ranges           | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/origin-server-must-ignore-range-header-with-unknown-range-unit  | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/proxy-may-discard-range-header-with-unknown-range-unit          | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/server-may-ignore-or-reject-invalid-range-header                | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/server-may-ignore-range-header-for-zero-length-representation   | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/server-may-ignore-range-header                                  | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/server-must-ignore-range-header-for-unrecognized-method         | observable                       | observable                             | impossible (condition-not-producible) |
| rfc9110/server-should-send-206-response-for-satisfiable-range           | impossible (not-representable)   | impossible (requires-controlled-input) | observable                            |
| rfc9110/server-should-send-416-response-for-unsatisfiable-range         | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |

### representation-data-and-metadata

| Rule                                                                                 | static                           | analytics                              | test                                  |
| ------------------------------------------------------------------------------------ | -------------------------------- | -------------------------------------- | ------------------------------------- |
| rfc9110/content-encoding-should-not-include-identity                                 | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/origin-server-may-respond-415-for-unacceptable-content-coding                | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/recipient-should-treat-x-compress-as-compress                                | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/recipient-should-treat-x-gzip-as-gzip                                        | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/sender-must-generate-content-encoding-header-if-encodings-applied            | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/content-language-may-be-applied-to-any-media-type                            | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/multiple-languages-may-be-listed-for-multiple-audiences                      | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/origin-server-should-send-content-length-when-size-known                     | observable                       | observable                             | observable                            |
| rfc9110/recipient-must-handle-large-content-length                                   | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/sender-must-not-forward-incorrect-content-length                             | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/sender-must-not-forward-message-with-incorrect-content-length-header         | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/sender-must-not-forward-message-with-invalid-content-length                  | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/server-may-send-content-length-for-304                                       | impossible (not-representable)   | impossible (requires-controlled-input) | observable                            |
| rfc9110/server-may-send-content-length-for-head-response                             | impossible (not-representable)   | impossible (requires-controlled-input) | observable                            |
| rfc9110/server-must-not-send-content-length-for-1xx-or-204                           | observable                       | observable                             | observable                            |
| rfc9110/server-must-not-send-content-length-for-2xx-connect-response                 | observable                       | observable                             | observable                            |
| rfc9110/user-agent-should-not-send-content-length-without-content                    | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/user-agent-should-send-content-length-for-request-with-defined-content       | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/content-location-201-response-semantics                                      | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)        |
| rfc9110/content-location-semantics-for-2xx-response                                  | impossible (nothing-to-check)    | impossible (nothing-to-check)          | impossible (nothing-to-check)         |
| rfc9110/origin-server-must-treat-content-location-as-transitory-context              | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/recipient-may-assume-media-type-or-determine-its-type                        | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/sender-must-only-generate-crlf-for-line-breaks-between-parts                 | impossible (tool-limitation)     | impossible (tool-limitation)           | impossible (tool-limitation)          |
| rfc9110/sender-should-generate-content-type-for-message-with-content                 | observable                       | observable                             | observable                            |
| rfc9110/etag-must-differ-for-different-content-encodings                             | impossible (not-representable)   | observable                             | impossible (condition-not-producible) |
| rfc9110/etag-strong-comparison-rules                                                 | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/etag-weak-comparison-rules                                                   | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/origin-server-must-mark-weak-entity-tag                                      | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/origin-server-should-avoid-backslash-in-entity-tags                          | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/origin-server-should-send-etag                                               | observable                       | observable                             | observable                            |
| rfc9110/sender-may-send-etag-in-trailer                                              | impossible (tool-limitation)     | observable                             | observable                            |
| rfc9110/origin-server-should-obtain-last-modified-close-to-date-generation           | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/origin-server-should-send-last-modified                                      | observable                       | observable                             | observable                            |
| rfc9110/origin-server-with-clock-must-not-generate-future-last-modified              | impossible (not-representable)   | observable                             | observable                            |
| rfc9110/origin-server-without-clock-must-not-generate-last-modified                  | impossible (peer-not-observable) | impossible (peer-not-observable)       | impossible (peer-not-observable)      |
| rfc9110/origin-server-should-change-weak-entity-tag-for-unacceptable-representations | impossible (only-origin-knows)   | impossible (only-origin-knows)         | impossible (only-origin-knows)        |

### routing

| Rule                                                                          | static                           | analytics                        | test                                   |
| ----------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------- |
| rfc9110/client-must-not-use-special-request-target-forms-with-other-methods   | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/client-should-continue-sending-request-when-response-arrives          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/intermediary-must-parse-and-remove-connection-fields                  | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-should-remove-known-hop-by-hop-fields                    | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/sender-must-list-connection-specific-field-in-connection-header       | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/sender-must-not-send-end-to-end-fields-as-connection-options          | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/intermediary-must-implement-connection-header                         | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/intermediary-must-not-forward-message-to-itself                       | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-must-check-and-update-max-forwards                       | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-must-generate-updated-max-forwards-when-forwarding       | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-must-not-forward-when-max-forwards-is-zero               | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-must-respond-as-final-recipient-when-max-forward-is-zero | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/recipient-may-ignore-max-forwards-for-other-methods                   | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/firewall-intermediary-should-not-forward-internal-hosts               | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/firewall-intermediary-should-replace-internal-hosts-with-pseudonyms   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/gateway-may-send-via-header-in-responses                              | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/gateway-must-send-via-header-in-inbound-requests                      | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/intermediary-may-combine-via-entries-with-identical-protocols         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-must-send-via-header                                            | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/recipient-may-interpret-missing-port-as-default                       | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/recipient-may-remove-comments-before-forwarding                       | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-may-generate-comments-to-identify-software                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-may-replace-host-with-pseudonym                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-must-not-combine-via-entries-with-different-protocols          | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-should-not-combine-via-entries-unless-same-organization        | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/proxy-may-add-domain-to-non-fqdn-hostname                             | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-may-transform-content-without-no-transform-directive            | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/proxy-must-not-change-fqdn-hostname                                   | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/proxy-must-not-modify-absolute-path-and-query                         | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/proxy-must-not-transform-content-with-no-transform-directive          | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/proxy-should-not-modify-endpoint-and-representation-headers           | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/origin-server-must-reject-https-requests-without-valid-certificate    | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/origin-server-must-reject-requests-not-meeting-scheme-requirements    | impossible (only-origin-knows)   | impossible (only-origin-knows)   | impossible (only-origin-knows)         |
| rfc9110/client-may-send-upgrade-header                                        | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/recipient-should-use-case-insensitive-comparison-for-protocol-names   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/sender-must-send-upgrade-connection-option                            | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-may-ignore-client-protocol-preference-order                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-may-ignore-upgrade-header                                      | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-may-send-upgrade-header-in-other-responses                     | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-must-ignore-upgrade-in-http-1.0-request                        | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-must-list-protocols-in-layer-ascending-order                   | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-not-switch-to-non-indicated-protocol                      | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-must-not-switch-unless-semantics-can-be-honored                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-must-send-100-before-101-with-expect-header                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-send-upgrade-header-in-101-response                       | impossible (not-representable)   | observable                       | observable                             |
| rfc9110/server-must-send-upgrade-header-in-426-response                       | observable                       | observable                       | observable                             |
| rfc9110/user-agent-must-generate-host-or-authority-header                     | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/user-agent-should-send-host-as-first-header                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |

### status-codes

| Rule                                                                                          | static                           | analytics                        | test                                   |
| --------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------- |
| rfc9110/server-must-send-www-authenticate-header-for-401-response                             | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-repeat-request-with-new-authorization-header                           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-should-present-error-representation-to-user                                | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/402-status-code-is-reserved                                                           | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/client-may-repeat-request-with-new-credentials-for-403-response                       | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-should-not-automatically-repeat-request-for-403-response                       | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/origin-server-may-respond-with-404-instead-of-403                                     | observable                       | observable                       | observable                             |
| rfc9110/origin-server-must-generate-allow-header-for-405-response                             | observable                       | observable                       | observable                             |
| rfc9110/server-should-generate-content-for-406-response                                       | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-select-most-appropriate-choice-for-406-response                        | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-may-repeat-request-with-new-proxy-authenticate-header-for-407-response         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-must-send-proxy-authenticate-header-for-407-response                            | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/client-may-repeat-request-for-408-response                                            | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-content-for-409-response                                       | observable                       | observable                       | observable                             |
| rfc9110/client-may-repeat-request-with-valid-content-length-header-for-411-response           | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/client-may-retry-after-given-time-for-413-response                                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-may-close-connection-for-413-response                                          | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-may-terminate-request-for-413-response                                         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-retry-after-header-for-413-response                            | observable                       | observable                       | observable                             |
| rfc9110/server-should-generate-content-range-header-for-416-response                          | observable                       | observable                       | observable                             |
| rfc9110/client-may-retry-request-over-different-connection                                    | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-must-not-send-421-response                                                      | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/server-must-send-upgrade-header-for-426-response                                      | observable                       | observable                       | observable                             |
| rfc9110/server-should-send-error-representation-for-4xx-responses                             | observable                       | observable                       | observable                             |
| rfc9110/user-agents-should-display-error-representation-to-user                               | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-understand-class-of-any-status-code                                       | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-should-process-invalid-status-code-as-5xx                                      | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-be-able-to-parse-multiple-1xx-responses                                   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/proxy-must-forward-1xx-responses                                                      | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-generate-upgrade-header-field                                             | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-not-send-1xx-response-to-1.0-client                                       | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-content-for-300-response                                       | observable                       | observable                       | observable                             |
| rfc9110/server-should-generate-location-header-for-preferred-choice-for-300-response          | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-select-redirection-from-content                                        | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-may-use-location-field-for-automatic-redirect                              | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-location-header-field-for-301-response                         | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-change-request-method-from-post-to-get-for-301-response                | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-may-use-location-header-for-automatic-redirection-for-301-response         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-location-header-for-302-response                               | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-change-request-method-from-post-to-get-for-302-response                | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-may-use-location-header-for-automatic-redirection-for-302-response         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/proxy-should-forward-304-response-to-outbound-client                                  | impossible (not-representable)   | observable                       | impossible (participant-not-reachable) |
| rfc9110/sender-should-not-generate-additional-representation-metadata-for-304-response        | observable                       | observable                       | observable                             |
| rfc9110/server-must-generate-header-fields-for-304-response                                   | observable                       | observable                       | observable                             |
| rfc9110/status-code-305-is-deprecated                                                         | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/status-code-306-is-reserved                                                           | observable                       | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-should-generate-location-header-for-307-response                               | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-use-location-header-for-automatic-redirection                          | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-must-not-change-request-method-for-automatic-redirection-for-307-response  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-should-generate-location-header-for-308-response                               | observable                       | observable                       | observable                             |
| rfc9110/user-agent-may-use-location-header-for-automatic-redirection-for-308-response         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/clients-should-detect-and-intervene-cyclical-redirections                             | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/user-agent-may-redirect-to-location-header-uri-for-3xx-response                       | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/user-agent-shoud-resend-original-request-with-modifications-for-redirected-requests   | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-may-send-retry-after-header-for-503-response                                   | impossible (not-representable)   | observable                       | impossible (condition-not-producible)  |
| rfc9110/server-should-generate-representation-for-505-response                                | observable                       | observable                       | observable                             |
| rfc9110/server-should-send-error-representation-for-5xx-response                              | observable                       | observable                       | observable                             |
| rfc9110/user-agent-should-display-representation-to-the-user-for-5xx-response                 | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-should-send-validator-fields                                                   | observable                       | observable                       | observable                             |
| rfc9110/server-must-not-generate-content-for-205-response                                     | observable                       | observable                       | observable                             |
| rfc9110/client-must-inspect-206-response-content-type-and-range                               | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-may-combine-multiple-ranges-with-same-strong-validator-to-larger-range         | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-process-combined-response-correct                                         | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-use-other-header-fields-provided-in-new-for-206-response                  | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-inspect-content-range-header-in-multiple-parts-206-response               | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/client-must-not-generate-multiple-ranges-request-if-not-supported                     | impossible (peer-not-observable) | impossible (peer-not-observable) | impossible (peer-not-observable)       |
| rfc9110/server-may-coalesce-overlapping-or-small-gapped-ranges                                | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-may-generate-multiple-parts-response-with-single-body                          | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-generate-content-range-header-in-corresponding-body-part-for-206-response | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-generate-multipart-byteranges-content-for-multi-part-206-response         | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-must-not-generate-content-range-header-for-multi-part-206-response             | observable                       | observable                       | observable                             |
| rfc9110/server-must-not-generate-multipart-response-to-a-single-part-request                  | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-generate-content-type-header-in-body-for-206-response                   | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/server-should-send-parts-in-order-of-range-header                                     | impossible (tool-limitation)     | impossible (tool-limitation)     | impossible (tool-limitation)           |
| rfc9110/sender-should-not-generate-additional-representation-header-fields-for-206-response   | observable                       | observable                       | observable                             |
| rfc9110/server-must-generate-header-fields-for-206-response                                   | observable                       | observable                       | observable                             |
| rfc9110/server-must-generate-content-range-header-for-single-part-206-response                | observable                       | observable                       | observable                             |

## Tag status

### security

- `security:transport` — 12 rule(s)
- `security:cors` — ships empty
- `security:cookies` — ships empty
- `security:csp` — ships empty
- `security:content-type` — 2 rule(s)
- `security:authentication` — 9 rule(s)
- `security:authorization` — ships empty
- `security:disclosure` — 11 rule(s)
- `security:dos` — 9 rule(s)
- `security:cache-poisoning` — 2 rule(s)
- `security:request-smuggling` — 21 rule(s)
- `security:clickjacking` — ships empty
- `security:csrf` — 2 rule(s)
- `security:spoofing` — 2 rule(s)

### privacy

- `privacy:tracking` — 1 rule(s)
- `privacy:fingerprinting` — 5 rule(s)
- `privacy:referrer` — 6 rule(s)

<!-- COVERAGE:END -->

<!-- FOOTER:START - Do not remove or modify this section -->

## 📚 Documentation

- **[Getting Started](https://thymian.dev/introduction/getting-started)** - Set up Thymian in minutes
- **[Documentation](https://thymian.dev)** - Comprehensive guides and API reference
- **[CLI Reference](https://thymian.dev/references/cli)** - Complete CLI command documentation
- **[HTTP Rules](https://thymian.dev/guides/http-rules/how-to-use-rules)** - Learn about HTTP conformance validation

## 🏢 Enterprise Support

Get professional consulting and dedicated support from the creators of Thymian. We offer:

- API design and governance strategies
- HTTP standards compliance auditing
- Custom plugin development
- Custom rule development
- Team training and workshops

**[Learn more about Enterprise Support](https://thymian.dev/enterprise)** | **Email: [support@thymian.dev](mailto:support@thymian.dev)**

---

<div align="center">

**Shipped with 🌱 by [qupaya](https://qupaya.com)**

</div>
<!-- FOOTER:END -->
