Summary

  • AFRINIC's public Routinator 0.14.2 reported 39,059 valid input VRPs, 8,212 duplicates and 30,847 final VRPs at validation serial 23421.
  • At serial 23422 it reported 39,058 inputs, 8,211 duplicates and the same 30,847 final VRPs; the one-count movement was entirely in IPv4.
  • Routinator defines duplicates as VRPs produced by ROAs containing the same authorisation and warns that duplicate attribution can vary with processing order.
  • The captures do not identify the changed tuple, ROA or holder and do not show a BGP or router decision. A useful public receipt would join source-object lineage to final-set and router evidence without inventing causation.

One subtraction survived a moving input

At validation serial 23421, completed at 06:37:53 UTC on 29 August, the AFRINIC column of a public Routinator service contained three numbers that fit exactly: 39,059 valid input VRPs, minus 8,212 duplicates, equalled 30,847 final VRPs. Unsafe and locally filtered counts were both zero.

The next completed validation, serial 23422 at 06:57:08 UTC, changed the first two terms and preserved the result. There were 39,058 valid inputs and 8,211 duplicates. The final count was still 30,847. The IPv4 line supplied the whole movement: total fell from 37,804 to 37,803, duplicate fell from 8,136 to 8,135, and final stayed at 29,668. IPv6 remained 1,255 total, 76 duplicate and 1,179 final.

This is a modest observation. It is also a useful test of language. It would be easy to say that AFRINIC “lost a route”, “removed a bad ROA” or “fixed a duplicate”. None of those statements follows from the record. The endpoint reports the state of one validator after a run. It does not name the VRP occurrence that disappeared from the input count, the source object that supplied it or an operator whose action explains the change.

The later run did report 12,170 valid ROAs and one invalid ROA, where the earlier run reported 12,171 valid and none invalid. That is another state difference, not a published join. Without the source object identifier, it cannot safely be connected to the one-count duplicate movement. An attractive arithmetic story is not the same thing as object-level evidence.

What the two runs do establish is narrower and cleaner. The input population changed. The duplicate population changed by the same amount. The number of AFRINIC-attributed unique VRPs contributed to the final set did not. Anyone claiming a router-facing authorisation change must therefore bring evidence from a layer the two counts do not provide.

A ROA, a VRP occurrence and a route are not synonyms

The vocabulary matters because each noun has a different owner and evidentiary weight.

A Route Origin Authorisation is a signed RPKI object. In simplified terms, it names one origin AS and contains one or more address-prefix authorisations, each with a prefix and an optional maximum length. One ROA object can therefore produce more than one validated payload. Different objects—or different publication paths—can also yield the same authorisation.

A Validated ROA Payload is the tuple the validation process derives for origin validation: IP address, prefix length, maximum length and origin AS number. That tuple is not the ROA file, its certificate or the BGP route. It is the compact authorisation a cache can make available to routing systems.

A duplicate, in Routinator's documented metric, is an occurrence of a VRP whose authorisation is already represented. Deduplication removes multiplicity from the final set. It does not declare that the remaining authorisation is false, insecure or operationally unused. If two valid source paths yield the same tuple, a router does not need two copies of the same instruction in order to evaluate a route.

A route is yet another object: a prefix learned through BGP with an origin derived from its AS path. Origin validation compares that route with the available VRPs. A route may be Valid when at least one VRP matches, Invalid when a covering VRP exists but none matches, or NotFound when no VRP covers it. None of those route states can be read directly from a trust-anchor duplicate count.

These distinctions are not technical pedantry. They stop four actors from being collapsed into one: a resource holder can publish an authorisation; repositories distribute signed objects; a validator evaluates and attributes them under its configuration and processing order; a router or operator decides how to consume the resulting set. AFRINIC hosts the observed validator and operates its trust anchor, but that does not mean it authored every ROA below the anchor or controlled every router that might use the cache.

“Duplicate” describes multiplicity, not guilt

The ordinary meaning of duplicate carries a whiff of error. In data systems, duplication may indeed result from a mistaken reissue or stale copy. It may also result from intentional overlap, repository layout, migration, redundant publication or nothing more dramatic than how equivalent authorisations arrive at a particular validator. The status count alone does not choose among those explanations.

Routinator's own warning is decisive here. If a VRP appears through multiple trust anchors or repositories, the occurrence counted as the duplicate depends on processing order. That order can change between validation runs, so attribution and even the number can move unexpectedly. The warning is not an admission that the final set is unreliable. It is a reminder that a per-source duplicate statistic contains local accounting choices.

That is why cross-RIR comparisons are especially tempting and especially weak. In the first captured run, the service showed very different duplicate counts under different trust anchors. Those values reflect the observed source graph, validator version, configuration, moment and attribution rules. They are not league-table scores for registry competence. A zero does not prove perfect object hygiene; a large number does not prove poor route security.

The stable 30,847 is helpful because it locates the immediate boundary. Whatever changed between these two observed runs, it did not change the count of unique AFRINIC-attributed final VRPs. Yet even that statement has limits. Equality of counts does not prove identity of sets: one tuple could leave while another entered. Here the paired one-count input and duplicate movement strongly fits the arithmetic of lost multiplicity, but only a set diff can prove that every final tuple was identical.

The honest wording is therefore precise: the reported final count did not change. It is not yet safe to say the final set itself was byte-for-byte identical, and still less safe to say every connected router held the same data. Count continuity is evidence, not omniscience.

The status endpoint is a snapshot, not a causal diary

The endpoint is unusually rich. Its documentation says it returns exhaustive JSON information about trust anchors, repositories, RRDP and rsync connections, and RTR and HTTP sessions; it supplies the data shown by the user interface. The captured records include validator version, serial, timing and per-anchor object statistics. This is far more useful than an undated dashboard number.

But “exhaustive” describes the fields for that running service, not a history of why every field changed. The response does not preserve a public object-to-object diff between serials. It does not say which source ROA stopped validating, whether a repository fetch changed, whether duplicate attribution moved, or whether the new invalid ROA was the same object involved in the count difference.

Nor does it prove delivery to, or use by, a particular router. The final set is the set the validator can provide. RTR session statistics can show connections to the cache, but a route-policy decision also depends on which cache a router trusts, which serial it received, local policy and the BGP route present at that moment. A validator receipt and a router receipt are related records, not interchangeable ones.

This is where a small state transition becomes a governance question. Public infrastructure increasingly exposes live metrics while retaining causal detail only in operator logs. The public gets numbers precise enough to invite conclusions but not identifiers sufficient to test them. The answer is not to publish every internal log. It is to make the join between a changed aggregate and its source objects reconstructable.

The missing product is a lineage receipt

A useful receipt would begin with the validation event: validator software and configuration fingerprint, serial, start and completion time, trust-anchor set and repository-set fingerprint. Those fields define the observation rather than pretending it is universal.

For each unique VRP tuple affected by a change, the record would list the origin ASN, prefix and maximum length. It would attach hashes and publication references for the source ROA objects, plus enough certificate-chain identity to distinguish two occurrences without exposing private operational material. Multiplicity would be explicit: two occurrences before, one after; or one source attributed under a different repository after processing order changed.

The change classification must remain bounded. Source withdrawal observed, new object superseded old object, validation failed, repository unavailable and duplicate attribution reassigned are useful only when their evidence exists. Unresolved is preferable to a confident fiction. A later investigation can supersede the initial classification without erasing it.

Next comes the final-set diff. The record should state whether a tuple entered, left or remained, not merely whether the aggregate count changed. It should bind that result to the cache serial. If the institution wants to describe operational effect, it must then cite a separate router or route observation: which client received which serial, which route was evaluated, and what policy action followed. This keeps the validator from speaking on behalf of routers it does not control.

Such a receipt would make the present case almost boring. It might say that one of two equivalent occurrences ceased to validate while the surviving tuple remained in the final set. Or it might say that attribution shifted while the unique set stayed constant. It could reveal a more complicated replacement. The point is not to guess the answer; it is to make the answer possible.

The public version can be compact. VRP tuples and cryptographic hashes are already public-purpose evidence. Sensitive repository diagnostics or client identities can remain protected. What matters is that the count has a path back to a versioned, correctable record.

A quiet final count still carries information

There is a tendency to report only movements that appear operationally dramatic. A stable final count looks like no news. Here it is the most informative fact because it restrains the story.

The two serials show that one layer can change while another aggregate stays still. That is how resilient systems often work: redundant source occurrences collapse into one usable state. It is also how misleading narratives begin, because an observer can attach the movement to the wrong layer.

No affected route, network or holder is identified in the captures. No public evidence shows that a router rejected or accepted anything differently. No evidence shows that AFRINIC corrected a defective authorisation. What exists is a precise pair of validator states and a documented warning about duplicate attribution.

The correct institutional demand is therefore neither alarm nor dismissal. Preserve the lineage. Show which signed objects produced which unique payloads, how attribution changed, whether the final tuples changed and where router evidence begins. A registry's strongest role is not to inflate a counter into a verdict. It is to keep the narrow record through which others can reach one.

Sources