Skip to content

docs(protocols): cite the extension-header registry in ESP/AH, not protocol-numbers-1.csv - #938

Merged
JarryShaw merged 1 commit into
mainfrom
docs/931-esp-ah-registry-citation
Sep 30, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
docs/931-esp-ah-registry-citation

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • docs — documentation only

Description of your pull request and other information

Fixes #931. ESP and AH justified their double inheritance by citing protocol-numbers-1.csv's IPv6 Extension Header column — the derived signal #926 repointed the const generator away from because it disagreed with the authoritative registry (it flagged BIT-EMU/147, which the real registry omits).

Both docstrings now cite IANA's IPv6 Extension Header Types registry plus the per-header RFC section (RFC 4303 §3.1.1 for ESP, RFC 4302 §3.1.1 for AH) that places each header after an IPv4 header — the same test conventions.rst's extension-header-subclassing section uses. The "package's own ExtensionHeader registry agrees" clause is kept, now as a check against the authoritative source rather than corroboration of the wrong one. hip.py already cites the correct registry and RFC 7401, so it needed no change.

Added one regression test per protocol asserting the docstring names the new registry/RFC section, not protocol-numbers-1.csv; both fail against 382375811 and pass with this change.

@JarryShaw JarryShaw added docs Pull requests that change documentation only (docs: subject prefix) test Pull requests that add or correct tests (test: subject prefix) review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES at 5af1576e8 — one defect, in the part that matters most here: the citation points at the right section but summarises the wrong half of it, so the evidence does not support the claim it is attached to.

Both docstrings now read (ESP shown; AH is identical in shape):

IANA's IPv6 Extension Header Types registry lists ESP at 50 (:rfc:4303#section-3.1.1 places it directly after an IPv4 header)

The sentence asserts IPv6 extension-header membership. The parenthetical offers an IPv4 placement as evidence. That is a non-sequitur — an IPv4 fact cannot support an IPv6 claim — and it is the same failure mode as quoting RFC 8200 §4.5 unscoped, which was corrected on #895.

The section is the right one; it contains the sentence you actually want. Fetched verbatim from rfc-editor.org:

RFC 4303 §3.1.1 — "In the IPv6 context, ESP is viewed as an end-to-end payload, and thus should appear after hop-by-hop, routing, and fragmentation extension headers."

RFC 4302 §3.1.1 — "In the IPv6 context, AH is viewed as an end-to-end payload, and thus should appear after hop-by-hop, routing, and fragmentation extension headers."

That is direct primary-source support for treating each as an IPv6 extension header: it places them among the extension headers, ordered after hop-by-hop, routing and fragmentation. Cite that, not the IPv4 diagram.

Verified and good otherwise: the registry figures are right — pcapkit/const/ipv6/extension_header.py:33 ESP = 50 and :36 AH = 51, generated from extension-header.csv per pcapkit/vendor/ipv6/extension_header.py:102 post-#926. One commit, correct author, MERGEABLE, +46/-6 across four files, and the Note: block carrying the #895 ruling was rightly left untouched. Both new tests were proven to fail against 382375811.

Separately, and not for this PR: pcapkit/protocols/internet/ipv6_ext.py:41 still cites protocol-numbers-1.csv, for its length-exception table. Different claim, different file, out of #931's scope — I will track it rather than widen this.

@JarryShaw
JarryShaw force-pushed the docs/931-esp-ah-registry-citation branch from 5af1576 to 097c3cb Compare September 30, 2026 00:51
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES at 097c3cb3e — Opus cross-review (author was Sonnet). Two findings, both re-derived by me, and the first one means my own round-1 correction was incomplete.

1. The new parenthetical is now an overstatement, and it contradicts the docstring it sits in. esp.py:980-982 / ah.py:56-58 say §3.1.1 "places it among the IPv6 extension headers". The RFC says "is viewed as an end-to-end payload, and thus should appear after hop-by-hop, routing, and fragmentation extension headers" — a placement recommendation, not a membership statement. Three problems: it converts "end-to-end payload" into extension-header membership, which is the framing the RFC declines; it turns "should appear" into "places"; and it drops §3.1.1's transport-mode scoping (§3.1.2 puts ESP after a new IP header).

Worse, and decisive — esp.py's own Note: eleven lines below now says the opposite: ":rfc:8200#section-4.5`` says outright that ESP 'is not considered an extension header'." One docstring, two contradictory claims.

conventions.rst:829 settles which is right: "Being in that registry is what makes something an extension header; it is not evidence about whether the same header is also a protocol in its own right." Registry membership is the basis — not an RFC sentence. hip.py:269-271 shows the honest pattern, quoting RFC 7401 §5.1's real "the HIP header is logically an IPv6 extension header" for the one header where an RFC does say it.

2. assertNotIn('IPv4', doc) is over-fit — and it bans prose this issue explicitly asks for. #931's own body: "RFC 4303 §3.1.1 and RFC 4302 §3.1.1 each place the header after an IPv4 header, which is the operative test under the extension-header subclassing convention — an IPv4-capable header is also a standalone protocol and names a second base." So the IPv4 sentence is the deciding limb for the IPsec-base half of the double inheritance, not junk. hip.py:272-274 already cites its own IPv4 appendix for exactly that. As written, these docstrings can never gain that half without deleting the assertion.

I measured the narrower form and it costs nothing — assertNotIn('directly after an IPv4 header', doc) fails on 5af1576e8 for both classes and passes on 382375811 and 097c3cb3e, identical regression power to the broad ban.

So round 1's diagnosis was right but my prescription was half a fix: the IPv4 citation was attached to the wrong claim, and I let it be replaced by an overstatement of the right one. The accurate framing is registry membership for the extension-header half, RFC §3.1.1's IPv4 sentence for the standalone half — two claims, two sources.

Confirmed otherwise: registry figures right; nothing lost against 382375811; the removed test clause was correctly removed; coverage delta 0 (esp.py 366→366, ah.py 71→71 measurable statements). UNVERIFIED: the full two-file test run — killed at 13 minutes, a pre-existing slowness in test_esp_unit.py, not introduced here; the two new methods pass in isolation.

@JarryShaw
JarryShaw force-pushed the docs/931-esp-ah-registry-citation branch from 097c3cb to e783892 Compare September 30, 2026 01:21
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

NEEDS CHANGES at e783892a9 — Opus round-4 review. It disagreed with the framing I gave it, and it was right to. Two blocking items, both re-derived by me.

First, my framing was wrong. I briefed the reviewer that the new standalone-protocol inference might be round 2's error in a new costume. It is not. conventions.rst:841-848 explicitly makes IPv4-carriage "the limb that decides" and cites exactly RFC 4302/4303 §3.1.1, "the same sentence and the same diagram". Round 2 asserted an RFC membership claim the RFC does not make; round 3 asserts an RFC placement fact it does make. The syllogism is licensed. The overreach is in two clauses bolted onto it.

A. esp.py:988-989 — "and names IPsec as the second base" is positionally false. Measured: ESP.__bases__ = ['IPsec', 'IPv6_Ext'] — IPsec is __bases__[0], the first base. And the sibling AH docstring added in this same commit says so (ah.py:64): "IPsec is first in the bases so that its id keeps precedence." One commit, two contradictory statements about the same base order.

"Second base" is also a docs term of art, not a code idiom: 0 hits in pcapkit/, 3 in docs/. It is positionally true for HIP (HIP(IPv6_Ext, Internet)) and false for ESP, which is exactly why importing it here traps a reader. Separately, the subject of "names" is "the primary-source test" — i.e. the RFC — which says nothing about IPsec versus Internet; what selects IPsec is the owner's ruling at conventions.rst:799-803. hip.py:262-267 does this correctly, attributing base-naming to the convention and listing RFC grounds separately as evidence.

B. esp.py:987-988 and ah.py:62-63 — "the primary-source test that makes it a standalone protocol in its own right" reverses the direction. conventions.rst:867 is explicit: "Own-protocolhood on its own is not sufficient", and MH is the settling case — "a protocol in its own right and still does not qualify". IPv4-carriage does not make something a standalone protocol; it is the limb that qualifies an already-standalone protocol for a second base. Both test files pin this exact phrase, so the assertions move with the prose.

C. A guard gap, and it protects the worse defect. assertIn('hop-by-hop, routing and fragmentation') already passes at round 2, so only 'IPv6 header chain' and 'standalone protocol in its own right' discriminate r2 from r3 — and neither prevents re-adding r2's overstatement, which was the more serious defect since it contradicted the in-file Note:. Add assertNotIn('among the IPv6 extension headers', doc).

Cleared on the rest, with the assertion matrix measured across all four revisions (base fails 6/7, r1 4/7, r2 2/7, r3 passes 7/7, both classes): the paraphrase is faithful and matches how conventions.rst:843-845 itself quotes the sentence; "has it appear" for "should appear" is defensible because §3.1.1 carries an IPv6 diagram; "in the IPv6 header chain" does not smuggle membership back in; the Note: contradiction is genuinely resolved; coverage cannot move, every changed line being inside a class docstring.

UNVERIFIED: no Sphinx build, so the new paragraph's rendering is inferred from the pre-existing line-initial-role pattern rather than confirmed.

…otocol-numbers-1.csv (#931)

`ESP` and `AH` justified their double inheritance by citing
`protocol-numbers-1.csv`'s *IPv6 Extension Header* column -- the
derived signal #926 repointed the const generator away from, precisely
because it disagreed with the authoritative registry (it flagged
BIT-EMU/147 as an extension header; the real registry omits it).

- esp.py:978-993 / ah.py:54-67 -- extension-header *membership* now
  rests on IANA's *IPv6 Extension Header Types* registry and this
  package's own `ExtensionHeader`, per conventions.rst's "being in
  that registry is what makes something an extension header" ruling.
  RFC 4303/4302 section 3.1.1 is quoted too, but only for its actual
  IPv6-context placement sentence, not as membership evidence -- an
  earlier revision rephrased that sentence as "places it among the
  IPv6 extension headers", overstating the RFC and contradicting this
  docstring's own `Note:` on RFC 8200 declining ESP's extension-header
  status; caught in review and reworded to a plain placement
  description.
- Added the standalone-protocol half #931 asks for: the section's
  separate IPv4-context sentence is the primary-source evidence that
  ESP/AH also travel directly as an IPv4 payload, which *qualifies*
  an already-standalone header for a second base -- it does not *make*
  the header standalone (conventions.rst's MH case settles that), and
  the RFC has no say in which base is named. An earlier revision said
  the RFC "makes it a standalone protocol" and "names IPsec as the
  second base"; the latter was positionally false (`ESP.__bases__`
  puts IPsec first, not second) and unsupported by the cited section.
  Caught in review and reworded to match hip.py's own phrasing.
- Checked hip.py for the same stale citation; already correct.

Regression tests assert the registry citation and the corrected
prose, ban the specific wrong phrasings from all three earlier fix
attempts, and pin the registry-membership clause structurally (via a
regex on the parenthetical immediately following "registry lists ...
at <n>") so that a future rewording of the IPv4 evidence, not just
this exact phrase, would still be caught if attached to the wrong
claim. All fail against 3823758 and against the fix's three prior
revisions, before passing here.

Build: mypy 321/38 (unchanged), pylint 8.67/10 exit 30 (unchanged),
isort clean, targeted docstring tests pass (full esp/ah suite not
re-run: test_esp_unit.py's module import alone is ~11 minutes).
@JarryShaw
JarryShaw force-pushed the docs/931-esp-ah-registry-citation branch from e783892 to ec1b902 Compare September 30, 2026 01:59
@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 30, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO at ec1b90269 — after four rounds, every one of which found a real defect.

All three points fixed, verified by me against the tree:

  • A. The IPsec/"second base" clause is gone, not reworded. "second base" in doc is False for both classes — which matters because ESP.__bases__ = ['IPsec', 'IPv6_Ext'] makes IPsec the first base, and the sibling AH docstring in the same commit already said so.
  • B. Direction reversed in both: "the primary-source evidence that it also travels directly as an IPv4 payload, which is what qualifies it for a base besides IPv6_Ext". "makes it a standalone" in doc is False; "qualifies it for a base" is True. That matches conventions.rst:867 — "Own-protocolhood on its own is not sufficient" — and the hip.py:274-276 model.
  • C. assertNotIn('among the IPv6 extension headers', doc) added, closing the guard gap that would have let round 2's overstatement return undetected. The worker also added assertNotIn('second base', doc) unprompted.

And point D was answered better than I asked for. I said to pin the claim rather than the phrase if possible. It did:

membership_clause = re.search(r'registry lists ``ESP`` at 50 \((.*?)\)', doc)
self.assertIsNotNone(membership_clause, 'could not locate the membership clause')
self.assertNotIn('IPv4', membership_clause.group(1))

That extracts exactly the parenthetical attached to the membership sentence and forbids IPv4 evidence inside it, while leaving IPv4 prose free everywhere else — where #931 actually wants it, for the standalone-protocol half. Verified on the tree: the clause is located for both classes and contains no IPv4. Any future rewording that smuggles IPv4 evidence back into the membership claim now fails on structure rather than on a literal string.

The round-4 assertions were proven to fail on all four prior revisions — 382375811, 5af1576e8, 097c3cb3e, e783892a9 — with round 3 specifically failing on second base and on both new positive checks. Targeted run of the two methods: Ran 2 tests in 1.323s — OK. mypy 321/38 and pylint 8.67, exit 30, both at baseline; isort clean on all four files.

I did not spend a fifth review pass on this. The delta is prose plus test assertions, and I verified both of round 4's blocking claims personally before they were fixed and the fix itself after. Flag it if you would rather every round got a fresh reviewer regardless.

Unpublished and awaiting you.

@JarryShaw
JarryShaw merged commit 67b404a into main Sep 30, 2026
63 checks passed
@JarryShaw
JarryShaw deleted the docs/931-esp-ah-registry-citation branch September 30, 2026 02:14
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 30, 2026
@JarryShaw JarryShaw added this to the 1.5 milestone Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Pull requests that change documentation only (docs: subject prefix) test Pull requests that add or correct tests (test: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

docs(protocols): ESP and AH cite the wrong IANA registry for their extension-header status

1 participant