Supported for subscriber access

RFC 2866 - RADIUS Accounting

Every requirement this repository extracted from RFC 2866, the tests bound to it, and what a reader has verified about them. This summary is enrolled and gated by ./le rfc check.

Overview

Positive

what Ze has

Tested both ways100.0%15 of 15 gated MUSTs

a positive test proves Ze does what the requirement demands and a negative one proves it refuses what the requirement forbids

One polarity plus reason0.0%0 of 15 gated MUSTs

the requirement admits no counter-case, so one polarity plus a recorded reason is the whole proof available for it

One polarity, unexcused0.0%0 of 15 gated MUSTs

one direction is tested, the other is neither tested nor excused, and nothing states which

Partial proof; remaining gap0.0%0 of 15 gated MUSTs

scoped tests exist; the remaining obligation is unmet or unproven, with zero whole-requirement credit

No test at all0.0%0 of 15 gated MUSTs

no test carries the requirement id, whether or not a gap states why

Proven by a recorded break62.5%30 of 48 tagged units

a red was observed once under a recorded procedure, and the unit, the claim and the producer it rested on still hash to what was recorded. The break is not re-run. A test pair is not a proof until one has been observed

Neutral

measures that are neither good news nor bad

Gated MUSTs15of 16 this summary declares

MUST-level requirements the gate HOLDS. A population, not a result: the shares beside it are what says how Ze stands

Out of scope0of 15 gated MUSTs

an obligation that does not bind Ze. A {not-applicable} annotation says it never bound; a {feature-declined} annotation says its condition is an optional feature Ze does not offer, and quotes the RFC sentence that makes it optional. Scope, not coverage: it stays in the denominator every share on this page is taken over

Not applicable0.0%0 of 15 gated MUSTs

a {not-applicable} annotation says the obligation does not bind Ze, so no test is owed for it. It stays in the denominator every share here is taken over

Met below Ze0.0%0 of 15 gated MUSTs

a {lower-layer} annotation says a layer under Ze performs the behavior, on state Ze installs into that layer, and names the producer that installs it. The obligation binds Ze and is met; Ze proves none of it, because its own boundary carries no value the behavior reads

Optional feature declined0.0%0 of 15 gated MUSTs

a {feature-declined} annotation says the obligation is conditional on a feature the RFC makes optional and Ze does not offer, and it quotes the sentence that makes it optional. The condition is false, so nothing is owed and nothing is missing. It stays in the denominator every share here is taken over

The 8 shares marked as a part above are the whole of the 15 gated MUSTs: they add to 100%. Proven by a recorded break is a share of TAGGED UNITS, a different population, so it is not one of them.

How to read the colors

A color names what the measure MEANS, not how well Ze scores on it. Green is a good outcome at any value, red is a bad one, and neither a population nor a scope count is an outcome, so both take no color. The number under the label is what says how far Ze has got.

CardTone hereWhy that color
Gated MUSTs neutral no color: a population is a scale, and a larger one is neither good news nor bad. It is the accounting total
Out of scope neutral no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim
Tested both ways ok green at every value: a test pair is the outcome this gate exists to produce, and the share under the label is what says how far Ze has got
One polarity plus reason ok green at every value: where no counter-case exists, one polarity IS the complete answer, and a recorded reason is what the gate demands beside it
One polarity, unexcused ok green at zero, RED above it: half a proof with no reason for the other half
Partial proof; remaining gap ok green at zero, RED above it: a tested clause cannot prove the whole requirement
No test at all ok green at zero, RED above it: a binding obligation nothing exercises is a claim with nothing behind it, whether or not a reason is stated
Not applicable neutral no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim
Met below Ze neutral no color: an obligation met below Ze is neither a test Ze wrote nor work Ze owes, and the two green shares above are what says how much Ze proves itself
Optional feature declined neutral no color: an obligation whose condition Ze never meets is neither an achievement nor a failure. The absent FEATURE is disclosed on the RFC's own status row, as an implementation gap a later scope decision can revisit
Proven by a recorded break ok green at every value: an observed break is the outcome the discrimination gate exists to produce. The denominator is TAGGED UNITS, not obligations, so this share is not one of the parts above
Audit verdicts warn RED on the first weak, wrong or unimplemented verdict, amber while a verdict is no longer current or a gated MUST is unjudged, green when every one is judged sound and current

At a glance

FieldValue
Public status Supported for subscriber access
Enrolment Enrolled
Requirements 16
Gated MUST-level 15
Not applicable, so out of scope 0
Declared gaps 0
Declared gaps a test demonstrates 0
Gated with no test 0
Nightly-only evidence 0
Test tags 48
Tagged units 48
Recorded audit verdicts 12
Discrimination records 30
Summary rfc/short/rfc2866.md
Requirement shard rfc/requirements/rfc2866.md
RFC text rfc/full/rfc2866.txt

Enrolment

Enrolled: ze is a RADIUS accounting client (NAS); the four gated MUST requirements the checklist held before 2026-08-31 are tested with positive+negative pairs. A fifth, that an accounting failure must not tear a session down, was retired on 2026-09-27 because RFC 2866 states no such rule (rfc/corrections/rfc2866.md). RFC2866-3-2 (authenticator = MD5(Code+ID+Length+16 zero octets+Attributes+Secret)): TestRFC2866AccountingRequestAuthFormula positive (equals an independent MD5 reference; producer radius/packet.go:252 AccountingRequestAuth, applied radius/client.go:127-132), TestRFC2866AccountingRequestAuthRejectsTampering negative (authenticator changes when secret/attribute/Code changes). RFC2866-3-3 (a retransmission whose contents are identical reuses the Identifier, and one whose Acct-Delay-Time was updated takes a new one): TestRFC2866AccountingRetransmitTakesANewIdentifier positive (ze stamps Acct-Delay-Time on an Accounting-Request by default, so its attributes move on every attempt and each attempt carries a distinct Identifier; producer radius/client.go Exchange, encodeRequest and setAcctDelayTime), TestRFC2866AccountingDistinctRequestsDifferIdentifier negative. The identical-contents half is proven on the Access-Request path by TestAccessRequestRetransmitIsByteIdentical, and on the accounting path by TestRFC2866AccountingRetransmitWithoutDelayTimeKeepsIdentifier, which is the record of an operator who wrote `attributes exclude acct-delay-time`: producer radius/client.go stampsAcctDelayTime, whose false branch re-sends the first buffer under its original Identifier. The delay value itself is proven by TestAcctDelayTimeUpdatesOnRetransmit. RFC2866-5-1 (the §5.13 legend line for 1: exactly one Acct-Status-Type and one Acct-Session-Id; until 2026-09-30 the row quoted the whole table): TestRFC2866AcctStatusTypePresent and TestRFC2866EveryRecordCarriesOneOfEachOneMarkedAttribute positive (each lifecycle event yields exactly one of each on the wire; producer authradius/acct.go buildAcctPacket), TestRFC2866AcctStatusTypeNeverOmitted and TestRFC2866ExclusionsCannotRemoveAOneMarkedAttribute negative (the `attributes exclude` container refuses both names, and excluding every accepted name leaves both present exactly once; producer authradius/exclude.go parseAttributeExclusions). RFC2866-5.13-1 (the legend line for 0: User-Password, CHAP-Password, Reply-Message, State and CHAP-Challenge never present, split out of RFC2866-5-1 on 2026-09-30): TestRFC2866AccountingRequestOnTheWireCarriesNoZeroMarkedAttribute positive, TestRFC2866SubscriberTextNeverBecomesAZeroMarkedAttribute negative (attribute-shaped relayed text stays inside its own attribute). RFC2866-5.5-1 (Acct-Session-Id unique across the NAS): TestRFC2866AcctSessionIDUnique positive (1600 concurrent ids all distinct; producer authradius/acct.go genSessionID, an atomic counter), TestRFC2866AcctSessionIDNoCollisionOnReusedKey negative. Across a restart, which resets the counter, the id carries a boot tag minted at the accountant's first genSessionID (authradius/acct.go mintBootTag: the Unix seconds then 64 random bits): TestRFC2866AcctSessionIDUniqueAcrossRestart and TestRFC2866AcctSessionIDUniqueWhenClockRepeats positive (two accountants built in turn, the second at the same clock second, give the same tunnel and session two different ids). No SHOULD/MAY requirements are gated. The extraction walk of 2026-08-31 (rfc/extraction/rfc2866.json) added ten obligations the checklist never declared, each with a positive+negative pair. One of them, RFC2866-4.2-1, was retired on 2026-09-29 because it binds the accounting server (rfc/corrections/rfc2866.md); the other nine: RFC2866-3-4 and RFC2866-3-5 (octets outside the Length are padding, a datagram shorter than its Length is discarded; producers radius/packet.go Decode and radius/client.go readLoop), RFC2866-4.1-2 (User-Password, CHAP-Password, Reply-Message and State never present), RFC2866-4.1-3 (either NAS-IP-Address or NAS-Identifier present; producer authradius/nasidentity.go appendNASIdentity, which fixed a config setting neither leaf), RFC2866-4.1-4 (a new request takes a new Identifier; producer radius/client.go SendToServers), RFC2866-5-2 (embedded nulls survive an attribute value), RFC2866-5-3 (text of length zero omitted; producer authradius/acct.go buildAcctPacket, which fixed an empty User-Name reaching the wire), RFC2866-5.5-2 and RFC2866-5.5-3 (every record carries an Acct-Session-Id, and the records of one session carry the same one).

What the public ledger says

Status: Supported for subscriber access

What the ledger says is covered Start, Stop, and Interim-Update accounting records, each carrying Event-Timestamp, Calling-Station-Id and Acct-Delay-Time, and the Stop record carrying the §5.10 Acct-Terminate-Cause (authradius/acct.go buildAcctPacket, radius/client.go setAcctDelayTime). An operator holds any of those four back per record type with l2tp auth radius attributes exclude, which never reaches Acct-Status-Type, Acct-Session-Id or the NAS identity (authradius/exclude.go excludableAttributes, attributeExclusions.filter).

What the ledger says remains:

Admin/operator RADIUS accounting is not wired; the admin backend is authentication-only.

Coverage

BucketCountWhat it counts
Positive and negative tests 15 one part of the gated population
Annotated (including scoped evidence) 0 one part of the gated population
One polarity only 0 one part of the gated population
No test and no annotation 0 one part of the gated population
Partial proof; remaining gap (subset of annotated; zero whole-requirement credit) 0 an overlay: each of these is also counted by the part it falls in
Evidence that runs nightly only 0 an overlay: each of these is also counted by the part it falls in
Derived from other rows 0 outside the gated population: each asserts nothing and derives its state from the rows it names, which the parts above already count
Gated MUST-level requirements15every gated MUST falls in exactly one bucket above

Positive and negative tests (15): RFC2866-3-2, RFC2866-5.5-1, RFC2866-4.1-1, RFC2866-5-1, RFC2866-5.13-1, RFC2866-3-3, RFC2866-3-4, RFC2866-3-5, RFC2866-4.1-2, RFC2866-4.1-3, RFC2866-4.1-4, RFC2866-5-2, RFC2866-5-3, RFC2866-5.5-2, RFC2866-5.5-3

Requirements

RequirementLevelSectionTests
RFC2866-3-2The Request Authenticator field in Accounting-Request packets contains a one- way MD5 hash calculated over a stream of octets consisting of the Code + Identifier + Length + 16 zero octets + request attributes + shared secret (where + indicates concatenation). (§3)
MUST 3 - Packet Format
RFC2866-5.5-1This attribute is a unique Accounting ID to make it easy to match start and stop records in a log file. (§5.5)
MUST 5.5 - Acct-Session-Id
RFC2866-4.1-1If the Accounting-Request packet includes a Framed-IP-Address, that attribute MUST contain the IP address of the user. If the Access-Accept used the special values for Framed-IP-Address telling the NAS to assign or negotiate an IP address for the user, the Framed-IP-Address (if any) in the Accounting-Request MUST contain the actual IP address assigned or negotiated. (§4.1)
MUST 4.1 - Accounting-Request
RFC2866-5-11 Exactly one instance of this attribute MUST be present. (§5.13, the Accounting-Request table legend; the table marks 1 for Acct-Status-Type and Acct-Session-Id)
MUST 5.13 - Table of Attributes
RFC2866-5.13-10 This attribute MUST NOT be present (§5.13, the Accounting-Request table legend; the table marks 0 for User-Password, CHAP-Password, Reply-Message, State and CHAP-Challenge)
MUST NOT 5.13 - Table of Attributes
RFC2866-3-3For retransmissions where the contents are identical, the Identifier MUST remain unchanged. Note that if Acct-Delay-Time is included in the attributes of an Accounting-Request then the Acct-Delay-Time value will be updated when the packet is retransmitted, changing the content of the Attributes field and requiring a new Identifier and Request Authenticator. (§4.1)
MUST 4.1 - Accounting-Request
RFC2866-3-4Octets outside the range of the Length field MUST be treated as padding and ignored on reception (§3)
MUST 3 - Packet Format
RFC2866-3-5If the packet is shorter than the Length field indicates, it MUST be silently discarded. (§3)
MUST 3 - Packet Format
RFC2866-4.1-2Any attribute valid in a RADIUS Access-Request or Access-Accept packet is valid in a RADIUS Accounting-Request packet, except that the following attributes MUST NOT be present in an Accounting- Request: User-Password, CHAP-Password, Reply-Message, State. (§4.1)
MUST NOT 4.1 - Accounting-Request
RFC2866-4.1-3Either NAS-IP-Address or NAS-Identifier MUST be present in a RADIUS Accounting-Request. (§4.1, restated at §5.13 Note 1)
MUST 4.1 - Accounting-Request
RFC2866-4.1-4The Identifier field MUST be changed whenever the content of the Attributes field changes, and whenever a valid reply has been received for a previous request. (§4.1)
MUST 4.1 - Accounting-Request
RFC2866-5-2Servers and servers and clients MUST be able to deal with embedded nulls. (§5)
MUST 5 - Attributes
RFC2866-5-3Text of length zero (0) MUST NOT be sent; omit the entire attribute instead. (§5)
MUST NOT 5 - Attributes
RFC2866-5.5-2The start and stop records for a given session MUST have the same Acct-Session-Id (§5.5)
MUST 5.5 - Acct-Session-Id
RFC2866-5.5-3An Accounting-Request packet MUST have an Acct-Session-Id (§5.5)
MUST 5.5 - Acct-Session-Id
RFC2866-x-1It is recommended that the client continue attempting to send the Accounting-Request packet until it receives an acknowledgement, using some form of backoff. (§2)
SHOULD 2 - Operation
positiveno testno positive test
negativeno testno negative test

Gaps and untested MUSTs

RFC 2866 declares no gap, and every gated MUST it carries has a test bound to it.

Proof state

A tagged unit reads unproven where no discrimination record exists for it: nothing in this tree has been observed to break it, so the claim its tag makes is unproven.

RFC2866-3-2

The Request Authenticator field in Accounting-Request packets contains a one- way MD5 hash calculated over a stream of octets consisting of the Code + Identifier + Length + 16 zero octets + request attributes + shared secret (where + indicates concatenation). (§3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. TestRFC2866SentAccountingRequestCarriesTheSection3Authenticator reads the Accounting-Request datagram SendToServers put on the wire and asserts its 16 authenticator octets equal an independent MD5(Code+ID+Length+16 zeros+attributes+secret) over that datagram, and differ from the random authenticator in the Packet. Exact equality over the sent octets fails on any formula or ordering deviation in client.go. The tampering negative stays helper-level (shows secret, attribute and Code feed the hash); the wire positive is what discriminates.

PolarityTestKind and tierProof state
negative TestRFC2866AccountingRequestAuthRejectsTampering unit/verify revert, verified
positive TestRFC2866AccountingRequestAuthFormula unit/verify revert, verified
positive TestRFC2866SentAccountingRequestCarriesTheSection3Authenticator unit/verify revert, verified

RFC2866-5.5-1

This attribute is a unique Accounting ID to make it easy to match start and stop records in a log file. (§5.5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-10-14 by a reader who did not author the tests. Forbidden: two sessions whose records carry the same Acct-Session-Id in the log. Within one process: TestRFC2866AcctSessionIDUnique (1600 concurrent ids distinct) and TestRFC2866AcctSessionIDNoCollisionOnReusedKey. Across a restart: TestRFC2866AcctSessionIDUniqueAcrossRestart (two accountants built in turn give the same tunnel and session two ids on the Accounting-Start) and TestRFC2866AcctSessionIDUniqueWhenClockRepeats (same clock second: time digits equal, random digits differ, ids differ). Producer authradius/acct.go genSessionID, T-S-<boot tag>-N, the boot tag minted once by mintBootTag at first use from Unix seconds and 64 random bits; uniqueness across boots at one clock second is probabilistic over those 64 bits.

PolarityTestKind and tierProof state
negative TestRFC2866AcctSessionIDNoCollisionOnReusedKey unit/verify unproven
positive TestRFC2866AcctSessionIDUnique unit/verify unproven
positive TestRFC2866AcctSessionIDUniqueAcrossRestart unit/verify revert, verified
positive TestRFC2866AcctSessionIDUniqueWhenClockRepeats unit/verify revert, verified

RFC2866-4.1-1

If the Accounting-Request packet includes a Framed-IP-Address, that attribute MUST contain the IP address of the user. If the Access-Accept used the special values for Framed-IP-Address telling the NAS to assign or negotiate an IP address for the user, the Framed-IP-Address (if any) in the Accounting-Request MUST contain the actual IP address assigned or negotiated. (§4.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Judge 2026-09-30 (cont 5). Clause 1 (the attribute holds the user's address): TestAcctFramedIPAddressPresent, TestAcctFramedIPAddressIsSubscriberNotNAS, the unset/IPv6 negative and test/l2tp/radius-acct-wire.ci, unchanged. Clause 2, the gap of the prior weak verdict, is now proven and was a real defect: extractAuthMetadata took Framed-IP-Address 255.255.255.254 as a unicast address, the pool pinned it and accounting reported it. Fix (extract.go framedIPNASSelects) leaves FramedIP unset for 0xFFFFFFFE, and 0xFFFFFFFF stays refused by isValidSubscriberIP (limited broadcast), so the pool assigns; RFC 2865 Section 5.8 text checked; 0.0.0.0 is refused as unspecified. Positive TestRFC2866AccountingReportsTheAddressTheNASAssigned: both special values with a Framed-Pool keep the pool and leave FramedIP unset, and Start/Interim/Stop each carry exactly one Framed-IP-Address equal to the assigned 100.64.0.9. Negative TestRFC2866SpecialFramedIPValueIsNeverTheSubscriberAddress: neither value, alone or beside Session-Timeout, becomes the subscriber address. Both recorded red on extractAuthMetadata. The pool step between extraction and the accounting session (session-ip-assigned) is not driven by these units; the .ci covers IPCP-to-accounting end to end. Note: 0xFFFFFFFF ('the NAS Should allow the user to select') is handled as NAS-selects, journaled in plan/journal/field-carries-two-meanings.md; not this row's clause.

PolarityTestKind and tierProof state
negative TestAcctFramedIPAddressIsSubscriberNotNAS unit/verify revert, verified
negative TestAcctFramedIPAddressOmittedWhenNotIPv4 unit/verify revert, verified
negative TestRFC2866SpecialFramedIPValueIsNeverTheSubscriberAddress unit/verify revert, verified
positive TestAcctFramedIPAddressPresent unit/verify revert, verified
positive TestSessionEventDrivesAddressAndPortID unit/verify revert, verified
positive TestAccountingAddressFamiliesShareLifetime unit/verify revert, verified
positive TestRFC2866AccountingReportsTheAddressTheNASAssigned unit/verify revert, verified
positive radius-acct-wire.ci functional/verify revert, verified

RFC2866-5-1

1 Exactly one instance of this attribute MUST be present. (§5.13, the Accounting-Request table legend; the table marks 1 for Acct-Status-Type and Acct-Session-Id)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Judge 2026-09-30 (cont 6). Row corrected under R5 to the Section 5.13 legend line '1 Exactly one instance of this attribute MUST be present.' (verbatim), binding Acct-Status-Type and Acct-Session-Id; id kept because internal/le/rfc/quote_backfill_test.go pins it and the HEAD tags stay valid, which is honest: the id names the obligation the old span carried, narrowed. Positives: TestRFC2866AcctStatusTypePresent (count 1, right value, per status) and TestRFC2866EveryRecordCarriesOneOfEachOneMarkedAttribute (Start/Interim/Stop encoded and decoded: exactly one non-empty Acct-Status-Type and Acct-Session-Id, same session id). Negative TestRFC2866ExclusionsCannotRemoveAOneMarkedAttribute is genuine: the operator's attributes-exclude control is the only input that could drop either attribute; it refuses both names, and excluding every accepted name (derived from excludableAttributes) still leaves each exactly once. Recorded red on buildAcctPacket and parseAttributeExclusions. TestRFC2866AcctStatusTypeNeverOmitted still repeats the positive's presence check; the pair no longer depends on it.

PolarityTestKind and tierProof state
negative TestRFC2866AcctStatusTypeNeverOmitted unit/verify revert, verified
negative TestRFC2866ExclusionsCannotRemoveAOneMarkedAttribute unit/verify revert, verified
positive TestRFC2866AcctStatusTypePresent unit/verify revert, verified
positive TestRFC2866EveryRecordCarriesOneOfEachOneMarkedAttribute unit/verify revert, verified

RFC2866-5.13-1

0 This attribute MUST NOT be present (§5.13, the Accounting-Request table legend; the table marks 0 for User-Password, CHAP-Password, Reply-Message, State and CHAP-Challenge)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Judge 2026-09-30 (cont 7 re-judge). Row '0 This attribute MUST NOT be present' (Section 5.13 legend; User-Password, CHAP-Password, Reply-Message, State, CHAP-Challenge). Positive TestRFC2866LoggedInSessionAccountsWithoutZeroMarkedAttributes runs the real path: provider configured over plugin RPC, CHAP login through l2tp.GetAuthHandler against a live UDP server, session up/down over the event bus; the server decodes Start and Stop, which name the user and an Acct-Session-Id and carry none of the five. Negative TestRFC2866LoginCredentialsAndAcceptStateNeverReachAccounting is the missing piece of the prior weak verdict (R1(b), inputs forced toward the violation over the real path): a CHAP and a PAP login against an Access-Accept carrying State and Reply-Message; the test first proves CHAP-Challenge, a 17-octet CHAP-Password and User-Password were on the Access-Request wire, then that no Start/Stop of either session carries a 0-marked type or any of those octets (State, Reply-Message, challenge, CHAP response, CHAP-Password, PAP plaintext, hidden User-Password). Producer acct.go buildAcctPacket / acctSession holds only username, calling-station, NAS-Port-Id, peer address, so a copy would be a new input path, which the negative catches on the wire. Both new units observed red under a revert of buildAcctPacket. The builder-level pair in rfc2866_attribute_table_test.go keeps its HEAD tags; its negative (TLV framing) is supplementary.

PolarityTestKind and tierProof state
negative TestRFC2866SubscriberTextNeverBecomesAZeroMarkedAttribute unit/verify revert, verified
negative TestRFC2866LoginCredentialsAndAcceptStateNeverReachAccounting unit/verify revert, verified
positive TestRFC2866AccountingRequestOnTheWireCarriesNoZeroMarkedAttribute unit/verify revert, verified
positive TestRFC2866LoggedInSessionAccountsWithoutZeroMarkedAttributes unit/verify revert, verified

RFC2866-3-3

For retransmissions where the contents are identical, the Identifier MUST remain unchanged. Note that if Acct-Delay-Time is included in the attributes of an Accounting-Request then the Acct-Delay-Time value will be updated when the packet is retransmitted, changing the content of the Attributes field and requiring a new Identifier and Request Authenticator. (§4.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Clause 1: TestRFC2866AccountingRetransmitWithoutDelayTimeKeepsIdentifier goes red on a changed Identifier for identical contents. Clause 2: TestRFC2866AccountingRetransmitTakesANewIdentifierAndRequestAuthenticator forces a retransmit whose Acct-Delay-Time moves 0->1 and asserts a new Identifier, a new Request Authenticator, and each authenticator equal to the Section 3 MD5 of its own datagram. The two clauses are opposite polarities of one rule, so a client that always or never changes the ID goes red. TestRFC2866AccountingDistinctRequestsDifferIdentifier is mislabeled: it proves RFC2866-4.1-4.

PolarityTestKind and tierProof state
negative TestRFC2866AccountingDistinctRequestsDifferIdentifier unit/verify revert, verified
positive TestRFC2866AccountingRetransmitTakesANewIdentifier unit/verify revert, verified
positive TestRFC2866AccountingRetransmitWithoutDelayTimeKeepsIdentifier unit/verify revert, verified
positive TestRFC2866AccountingRetransmitTakesANewIdentifierAndRequestAuthenticator unit/verify revert, verified

RFC2866-3-4

Octets outside the range of the Length field MUST be treated as padding and ignored on reception (§3)

Audit verdict: not audited: no reader has judged these tests

PolarityTestKind and tierProof state
negative TestRFC2866LengthPaddingBoundaryIsTheLengthField unit/verify unproven
positive TestRFC2866LengthPaddingIgnoredOnReception unit/verify unproven

RFC2866-3-5

If the packet is shorter than the Length field indicates, it MUST be silently discarded. (§3)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden behaviour: accepting a datagram shorter than its Length field. TestRFC2866ShortPacketSilentlyDiscarded overstates the Length by 8 and fails if the exchange completes; TestRFC2866HonestLengthIsAccepted shows the same server with an honest Length completes, isolating the length claim.

PolarityTestKind and tierProof state
negative TestRFC2866HonestLengthIsAccepted unit/verify unproven
positive TestRFC2866ShortPacketSilentlyDiscarded unit/verify unproven

RFC2866-4.1-2

Any attribute valid in a RADIUS Access-Request or Access-Accept packet is valid in a RADIUS Accounting-Request packet, except that the following attributes MUST NOT be present in an Accounting- Request: User-Password, CHAP-Password, Reply-Message, State. (§4.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden behaviour: User-Password, CHAP-Password, Reply-Message or State in an Accounting-Request. TestRFC2866AcctForbiddenAttributesAbsent checks each of the four (and CHAP-Challenge) on Start, Interim-Update and Stop from buildAcctPacket; the negative shows the packet still carries User-Name, Acct-Session-Id and Acct-Status-Type, so an empty builder cannot pass. The permissive first clause obliges the sender nothing.

PolarityTestKind and tierProof state
negative TestRFC2866AcctForbiddenAttributesDoNotEmptyTheRequest unit/verify unproven
positive TestRFC2866AcctForbiddenAttributesAbsent unit/verify unproven

RFC2866-4.1-3

Either NAS-IP-Address or NAS-Identifier MUST be present in a RADIUS Accounting-Request. (§4.1, restated at §5.13 Note 1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden behaviour: an Accounting-Request carrying neither NAS-IP-Address nor NAS-Identifier. TestRFC2866AcctNASIdentityAlwaysPresent fails on that for every status and every leaf combination, including neither leaf set; TestRFC2866AcctNASIdentityFallbackIsNarrow shows the fallback does not replace a configured identity.

PolarityTestKind and tierProof state
negative TestRFC2866AcctNASIdentityFallbackIsNarrow unit/verify unproven
positive TestRFC2866AcctNASIdentityAlwaysPresent unit/verify unproven

RFC2866-4.1-4

The Identifier field MUST be changed whenever the content of the Attributes field changes, and whenever a valid reply has been received for a previous request. (§4.1)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Triggers now isolated: the Acct-Delay-Time retransmit (no reply received, attributes changed) asserts a new Identifier; TestRFC2866IdentifierChangesAfterAValidReplyWithUnchangedAttributes sends two records with byte-identical attribute fields, the second after a valid reply, and asserts distinct Identifiers. The rule is one-directional (MUST change on either trigger), so the two positives carry it; the NextID counter negative is a counter property, not a violating input.

PolarityTestKind and tierProof state
negative TestRFC2866IdentifierCounterCoversTheWholeSpace unit/verify revert, verified
positive TestRFC2866IdentifierChangesForANewRequest unit/verify revert, verified
positive TestRFC2866AccountingRetransmitTakesANewIdentifierAndRequestAuthenticator unit/verify revert, verified
positive TestRFC2866IdentifierChangesAfterAValidReplyWithUnchangedAttributes unit/verify revert, verified

RFC2866-5-2

Servers and servers and clients MUST be able to deal with embedded nulls. (§5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden behaviour: a null octet read as a terminator. TestRFC2866EmbeddedNullsSurviveTheWire round-trips a value with interior nulls through EncodeTo and Decode and compares bytes; TestRFC2866AllNullValueKeepsItsLength fails if an all-null value loses length. A strcpy-style cut goes red in both.

PolarityTestKind and tierProof state
negative TestRFC2866AllNullValueKeepsItsLength unit/verify unproven
positive TestRFC2866EmbeddedNullsSurviveTheWire unit/verify unproven

RFC2866-5-3

Text of length zero (0) MUST NOT be sent; omit the entire attribute instead. (§5)

Audit verdict: enforced (the tests do what the requirement demands), fresh. Forbidden behaviour: a text attribute of length zero on the wire. TestRFC2866AcctZeroLengthTextOmitted builds all three records for a session with no username and fails on a User-Name or any zero-length attribute; TestRFC2866AcctNonEmptyTextIsSent shows a non-empty User-Name is still sent.

PolarityTestKind and tierProof state
negative TestRFC2866AcctNonEmptyTextIsSent unit/verify unproven
positive TestRFC2866AcctZeroLengthTextOmitted unit/verify unproven

RFC2866-5.5-2

The start and stop records for a given session MUST have the same Acct-Session-Id (§5.5)

Audit verdict: not audited: no reader has judged these tests

PolarityTestKind and tierProof state
negative TestRFC2866AcctSessionIDDiffersBetweenSessions unit/verify unproven
positive TestAccountingAddressFamiliesShareLifetime unit/verify revert, verified
positive TestRFC2866AcctSessionIDSameAcrossRecords unit/verify unproven

RFC2866-5.5-3

An Accounting-Request packet MUST have an Acct-Session-Id (§5.5)

Audit verdict: not audited: no reader has judged these tests

PolarityTestKind and tierProof state
negative TestRFC2866AcctSessionIDNeverEmpty unit/verify unproven
positive TestRFC2866AcctSessionIDPresentOnEveryRequest unit/verify unproven

Extraction sign-off

FieldValue
Reviewer claude
Signed off 2026-09-29
Register rfc2119
Source rfc/full/rfc2866.txt
Source fingerprint 928686054877a829
Record rfc/extraction/rfc2866.json
Mapped sentences 13
Declined as scope 9
Relocated to a spec, which Ze OWES 0
Unclassified 0

Sections

SectionNameSitesDispositionReason
front not stated 0 skipped (front-matter) Title block, Status of this Memo, copyright notice, Abstract, the Implementation Note on UDP port 1646 against 1813, and the table of contents. The Implementation Note records deployment history and binds no speaker.
1 Introduction 0 walked Introduction. Names the problem RADIUS Accounting answers, and lists the key features: the client/server model, the shared secret that is never sent over the network, and the variable-length Attribute-Length-Value 3-tuples. No obligation.
1.1 Specification of Requirements 0 walked Specification of Requirements. The RFC 2119 key-words paragraph, plus one sentence of its own: 'These key words mean the same thing whether capitalized or not.' That sentence is why this walk reads a lowercase modal as normative wherever it binds a speaker, and it is why site 2.1:1 counts although the source writes 'MUST not'.
1.2 Terminology 0 walked Terminology. Defines service, session and 'silently discard'. The 'silently discard' entry carries two SHOULD clauses, on logging the error and on counting the event; neither is gated and neither is declared in rfc/short/rfc2866.md.
2 Operation 1 walked Operation. Describes the Start and Stop exchange, recommends that the client retry with some form of backoff and can fall back to an alternate server, and states that retry and fallback algorithms are not specified in detail in this document. One capitalised site, binding the accounting server. RFC 2866 nowhere states that an accounting failure must not tear a session down; the row that said so was retired on 2026-09-27 (rfc/corrections/rfc2866.md).
2.1 Proxy 1 walked Proxy. Walks the four steps of a forwarding server and a remote server, and states one obligation binding the forwarding server. The rest is advice to whoever implements a proxy that takes responsibility for retransmissions.
3 Packet Format 2 walked Packet Format. States the encapsulation, UDP port 1813, the field layout, and both authenticator computations in RFC 2866's own voice; it does not defer to RFC 2865. The two capitalised sites are the Length rules. The Request Authenticator formula is stated in indicative prose ('contains a one-way MD5 hash calculated over a stream of octets consisting of the Code + Identifier + Length + 16 zero octets + request attributes + shared secret'), so the site scan sees no keyword there and RFC2866-3-2 is declared unsourced. The Response Authenticator paragraph is indicative in the same way; RFC2866-4.2-1 is instead read from the capitalised sentence in Section 4.2. The section closes with one SHOULD on preserving the order of attributes of the same type.
4 Packet Types 0 walked Packet Types. One sentence: the Code field in the first octet decides the packet type.
4.1 Accounting-Request 7 walked Accounting-Request. The description, the packet diagram, and the field notes for Code, Identifier, Request Authenticator and Attributes. Seven capitalised sites: one binds the accounting server, and six bind the client that builds the record, which is the role ze plays.
4.2 Accounting-Response 2 walked Accounting-Response. Two capitalised sites: the server transmits the response when it recorded the request, and the Response Authenticator holds the correct response for the pending Accounting-Request, which the client checks on reception.
5 Attributes 4 walked Attributes. The attribute format, the type list for 40 to 51, the Length rule, and the five data types. RFC 2866 states this section in its own voice: unlike RFC 2869 Section 5, it carries no sentence saying the format is included from RFC 2865 for ease of reference, so its four capitalised sites are read as RFC 2866's own obligations rather than as citations.
5.1 Acct-Status-Type 0 walked Acct-Status-Type. Defines type 40 and its values: Start, Stop, Interim-Update, Accounting-On, Accounting-Off, the tunnel range and Failed. One MAY, on marking the start and the end of accounting with Accounting-On and Accounting-Off; ze sends neither, and the option is the owner's to take (ai/rules/rfc-compliance.md). No capitalised MUST-level keyword.
5.2 Acct-Delay-Time 0 walked Acct-Delay-Time. Defines type 41, and notes that changing it changes the Attributes field and so requires a new Identifier and Request Authenticator. ze sends no Acct-Delay-Time.
5.3 Acct-Input-Octets 0 walked Acct-Input-Octets. Defines type 42 and says it can only be present where Acct-Status-Type is Stop. Indicative prose, no capitalised keyword.
5.4 Acct-Output-Octets 0 walked Acct-Output-Octets. Defines type 43 in the wording of Section 5.3 with the direction reversed. Indicative prose, no capitalised keyword.
5.5 Acct-Session-Id 3 walked Acct-Session-Id. Defines type 44, states three capitalised obligations, and adds two SHOULDs on UTF-8 encoding. RFC2866-5.5-1 is declared unsourced here: 'unique across all active sessions on the NAS' is the summary's rendering of the indicative opening sentence, 'This attribute is a unique Accounting ID to make it easy to match start and stop records in a log file', which carries no keyword for the site scan to see. genSessionID (authradius/acct.go) is its producer.
5.6 Acct-Authentic 0 walked Acct-Authentic. Defines type 45, how the user was authenticated. Carries one MAY on including it and one SHOULD NOT: 'Users who are delivered service without being authenticated SHOULD NOT generate Accounting records.' Neither is gated and ze sends no Acct-Authentic. The SHOULD NOT is the RFC's own acknowledgement that an unauthenticated session reaches accounting, which is the session whose empty User-Name site 5:3 governs.
5.7 Acct-Session-Time 0 walked Acct-Session-Time. Defines type 46. Indicative prose, no capitalised keyword.
5.8 Acct-Input-Packets 0 walked Acct-Input-Packets. Defines type 47. Indicative prose, no capitalised keyword.
5.9 Acct-Output-Packets 0 walked Acct-Output-Packets. Defines type 48. Indicative prose, no capitalised keyword.
5.10 Acct-Terminate-Cause 0 walked Acct-Terminate-Cause. Defines type 49 and its eighteen values, each with a one-line meaning. ze sends no Acct-Terminate-Cause. No obligation.
5.11 Acct-Multi-Session-Id 0 walked Acct-Multi-Session-Id. Defines type 50 for linking the sessions of one multilink bundle. 'It is strongly recommended that' the value is UTF-8, which is advice and not a keyword. ze sends no Acct-Multi-Session-Id.
5.12 Acct-Link-Count 0 walked Acct-Link-Count. Defines type 51, carries one MAY on including it in an Accounting-Request that might have multiple links, and works an eight-record example. ze runs no multilink bundle and sends no Acct-Link-Count.
5.13 Table of Attributes 2 walked Table of Attributes. The table itself, Note 1, and the legend that defines the 0, 0+, 0-1 and 1 symbols. The two capitalised sites are Note 1 and the legend. The legend's 1 line is RFC2866-5-1 (site 5.13:2); its 0 line states a second obligation in the same site and is RFC2866-5.13-1, declared here as unsourced because a site maps to one row.
6 IANA Considerations 0 skipped (iana) IANA Considerations. Registers the packet type codes, attribute types and attribute values from the RADIUS name spaces of RFC 2865, under BCP 26. Binds IANA, not a speaker.
7 Security Considerations 0 walked Security Considerations. One sentence: the security issues are discussed in the sections about the authenticator and the shared secret. No obligation of its own.
8 Change Log 0 skipped (appendix-non-normative) Change Log. Section 1 calls it an appendix: it lists what changed against RFC 2139, in the past tense. Its 'must' in 'it must be used in the accounting-request for that session' is a report of the change site 5.5:3 carries, not a second obligation.
9 not stated 0 skipped (references) References: RFC 2139, RFC 2865, RFC 2119, RFC 768, RFC 1321, RFC 1700, RFC 2279 and RFC 2434.
10 Acknowledgements 0 skipped (acknowledgements) Acknowledgements. Credits Livingston Enterprises for the original RADIUS Accounting work.
11 Chair's Address 0 skipped (front-matter) Chair's Address. A postal, phone and mail address block, skipped the way rfc/extraction/rfc2869.json skips the same section.
12 Author's Address 0 skipped (front-matter) Author's Address. An address block only.
13 Full Copyright Statement 0 skipped (front-matter) Full Copyright Statement. The ISOC boilerplate, its disclaimer, and the RFC Editor funding acknowledgement.

Excluded sentences

SiteExcluded kindReasonQuote
2:1 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
Binds the RADIUS accounting server, the party that records the packet. ze runs no accounting server: radius/client.go opens a UDP socket to send requests and match the replies to them, and the one listener ze does run (authradius/coa.go) accepts a CoA-Request and a Disconnect-Request under RFC 5176, never an Accounting-Request. If the RADIUS accounting server is unable to successfully record the accounting packet it MUST NOT send an Accounting-Response acknowledgment to the client.
2.1:1 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
Binds a forwarding server: the party that, in the four steps above the sentence, logs an accounting-request, adds its own Proxy-State after any other, updates the Request Authenticator and forwards the request to a remote server. ze proxies no RADIUS. buildAcctPacket (authradius/acct.go) builds the records of ze's own subscriber sessions and adds neither Proxy-State nor Class, and SendToServers (radius/client.go) sends them to the servers the operator configured. A forwarding server MUST not modify existing Proxy-State or Class attributes present in the packet.
4.1:1 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
Binds the RADIUS accounting server, the party that records the packet. ze runs no accounting server: radius/client.go opens a UDP socket to send requests and match the replies to them, and the one listener ze does run (authradius/coa.go) accepts a CoA-Request and a Disconnect-Request under RFC 5176, never an Accounting-Request. Upon receipt of an Accounting-Request, the server MUST transmit an Accounting-Response reply if it successfully records the accounting packet, and MUST NOT transmit any reply if it fails to record the accounting packet.
4.2:1 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
Binds the RADIUS accounting server, the party that records the packet. ze runs no accounting server: radius/client.go opens a UDP socket to send requests and match the replies to them, and the one listener ze does run (authradius/coa.go) accepts a CoA-Request and a Disconnect-Request under RFC 5176, never an Accounting-Request. If the Accounting- Request was recorded successfully then the RADIUS accounting server MUST transmit a packet with the Code field set to 5 (Accounting-Response).
4.2:2 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
Binds the RADIUS accounting server, the party that writes the Response Authenticator of the Accounting-Response it transmits (the sentence before: 'the RADIUS accounting server MUST transmit a packet with the Code field set to 5'). ze runs no accounting server: radius/client.go sends Accounting-Requests and matches the replies, and the one listener ze runs (authradius/coa.go) takes RFC 5176 requests only. ze's verification of the field, dispatchResponse calling VerifyResponseAuth, is the client's reading of the indicative 'Invalid packets are silently discarded', which states no obligation keyword. RFC2866-4.2-1 was retired on 2026-09-29 (rfc/corrections/rfc2866.md). The Response Authenticator field MUST contain the correct response for the pending Accounting-Request.
5:1 binds-another-role
never bound Ze
the obligation is addressed to a role Ze never acts as
Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would.
The sentence scopes itself to an attribute 'received in an Accounting-Request', and only the accounting server receives one. Binds the RADIUS accounting server, the party that records the packet. ze runs no accounting server: radius/client.go opens a UDP socket to send requests and match the replies to them, and the one listener ze does run (authradius/coa.go) accepts a CoA-Request and a Disconnect-Request under RFC 5176, never an Accounting-Request. Decode (radius/packet.go) does refuse an attribute whose Length is below 2 or runs past the packet, for every code it parses, so the rule holds wherever ze could reach it. If an attribute is received in an Accounting-Request with an invalid Length, the entire request MUST be silently discarded.
5:4 duplicate-of
never bound Ze
the same obligation is already captured under another requirement id
The same obligation for the string data type that the sentence before it states for text; the two differ only in the type they name, and site 5:3 maps it. The producer is the same and no attribute ze builds is a zero-length string: an Accounting-Request from ze carries string-typed values only in NAS-Port-Id, appended only when the template resolved to text, and in the NAS identity, which appendNASIdentity never leaves empty. Strings of length zero (0) MUST NOT be sent; omit the entire attribute instead.
5.5:3 advisory-in-context
never bound Ze
the sentence advises on applying a rule stated elsewhere and adds no obligation of its own
The enclosing construction is 'An Access-Request packet MAY have an Acct-Session-Id; if it does, then the NAS MUST use the same Acct-Session-Id in the Accounting-Request packets for that session.' The MUST is conditioned on the MAY, and ze declines the option: buildAuthAttrs (authradius/handler.go) puts no Acct-Session-Id in an Access-Request, and the id does not exist yet at that point, because onSessionIPAssigned generates it when IPCP assigns the address (authradius/acct.go). Whether ze should take the option is a MAY for the owner to answer (ai/rules/rfc-compliance.md), not a requirement this walk can close. An Access-Request packet MAY have an Acct-Session-Id; if it does, then the NAS MUST use the same Acct-Session-Id in the Accounting- Request packets for that session.
5.13:1 duplicate-of
never bound Ze
the same obligation is already captured under another requirement id
Note 1 restates over the Table of Attributes the NAS identity rule Section 4.1 already states; site 4.1:3 maps it, and appendNASIdentity (authradius/nasidentity.go) is the one producer both sentences describe. [Note 1] An Accounting-Request MUST contain either a NAS-IP-Address or a NAS-Identifier (or both).

Superseded

No document obsoletes RFC 2866, so its obligations are stated where they were written.