Specify the 51Did byte structure and the package surface - #25
Open
jwrosewell wants to merge 2 commits into
Open
Conversation
…xposes Six packages read the 51Degrees identifier, one per language, and until now the only account of what the bytes hold was a table repeated in each package's own documentation. There was nowhere to point a reader who asks how a 51Did is actually structured, and nowhere for the six packages to agree, so the six could drift without anyone noticing. Identifier layout gives the OWID envelope fields, the payload header, the flags byte bit by bit, the cumulative usage values and the identifier types, each read from the reference implementation rather than from memory. It states the rule that a reader answers with the highest usage granted, because the values are cumulative and masking for the non-marketing bit alone reads every marketing identifier as non-marketing. Package surface names the accessors every package exposes in all six languages, and records what none of them exposes, being the raw flags byte and the byte offsets, with the reason in each case. The packages link here from their own code rather than repeating the definitions, which is the convention this repository already sets out for implementers.
This was referenced Sep 6, 2026
The page said the Usage value maps to the cloud's id.usage string, which is true of Java, Node, Python, PHP and Rust and not of .NET, so as written it described five packages and claimed six. It now states the mapping as a requirement, which is what a specification is for, and names the .NET gap with the issue that tracks it (pipeline-dotnet 399).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The six 51Did packages (.NET, Java, Node, Python, PHP, Rust) each carry their own table of the payload layout in their own documentation, and there is nowhere to send a reader who asks how a 51Did is actually structured. There is also nowhere for the six to agree, which matters because the removal work raised as pipeline-dotnet 398, pipeline-java 128, pipeline-node 193, pipeline-python 77, pipeline-php-did 15 and rust 39 turns on the six packages exposing the same surface.
This repository already says that code comments should link to fixed URLs here rather than repeat definitions, so the six packages will link to these pages instead of restating the layout.
What was added
did-specification/README.mdintroduces the three levels a 51Did is described at, being the identifier, the Envelope and the Match Key, and links the two pages.did-specification/identifier-layout.mdgives the byte structure: the OWID Envelope fields, the payload header, the flags byte bit by bit, the cumulative Usage values, and the identifier types with the Match Key length each one fixes.did-specification/package-surface.mdnames the accessors every package exposes in all six languages, and records what none of them exposes, being the raw flags byte and the byte offsets, with the reason for each.How the content was checked
Every value was read from source rather than from memory, on 6 September 2026.
Owid.Client/Extensions.csandOwid.Client/Constants.csin owid-dotnet, andOwid.Client/CryptoExtensions.csfor ECDSA with SHA-256.FiftyOne.Did/Model/FodId.cs,Usage.csandIdType.csin pipeline-dotnet, which is the reference implementation.FodIdtype in each of the six packages, read on the branch that adds the usage accessor.Notes
Written with AI assistance on James Rosewell's instruction and needs human review.