FEAT: 51Did four platform and browser factors, usageIsIndirect and refusing usage bits 000 - #202
Merged
Merged
Conversation
…ect and refuse usage bits 000 Cloud release 4.4.38 replaced the single browser factor of the creator context with platformname, platformversion, browsername and browserversion. RedeemResult.factors now carries only the nine factor names in the new Factor constant, in the order the cloud lists them, so the old browser key is no longer read into it. The body as sent stays in raw. The flags byte rules in specifications pull request 30 are applied. FodId.usageFromConsent is renamed to FodId.usageIsIndirect with no alias, and its documentation now says direct against indirect, with a consent string as the only indirect signal today. Usage.NONE is removed, and a payload whose usage bits are all clear is refused with the new ParseStatus.NO_USAGE, thrown as a RangeError naming the bits by the throwing surfaces. The patterns 010, 100, 101 and 110 read as before. The readme, the example and the generated types follow.
RedeemResult.factors and toJSON pass every factor name through unchanged again, as the other 51Did packages do, so a factor the cloud adds later reaches callers without a package release and an older service's browser key stays under its own name. The Factor constant still lists the nine names in the cloud's order.
…t export it The 51Did readme's usage example destructured Terms from the package, which index.js has never exported, so the line as written gives undefined and misleads anyone copying it. The example only ever reads fodId.terms, so nothing else changes.
jwrosewell
marked this pull request as ready for review
September 17, 2026 20:10
jwrosewell
marked this pull request as draft
September 17, 2026 20:39
jwrosewell
marked this pull request as ready for review
September 18, 2026 06:44
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.
Summary
This brings the 51Did package (
fiftyone.pipeline.did) up to cloud release 4.4.38 and to the flags byte rules in specifications pull request 30, which is still a draft. This is a breaking change with no alias, so the next release of these packages is a minor version rather than a patch. The latest published version on npm is 4.5.47, so the next one is 4.6.0. The version comes from GitVersion, which reads the commit messages since the last tag, so this branch carries an empty commit whose message is+semver: minorand nothing else needs changing.browsercreator context factor withplatformname,platformversion,browsernameandbrowserversion. A new frozenFactorconstant (exported from the package) lists the nine factor names in the order the cloud lists them.RedeemResult.factorsandtoJSON()keep every factor name exactly as the cloud sends it, as before and as the other 51Did packages do, so a factor the cloud adds later reaches callers without a package release, and an older service'sbrowserkey stays under its own name rather than filling any of the four.usageFromConsentis renamed tousageIsIndirect, with no alias. The documentation now describes bit 3 as direct against indirect, with a consent string as the only indirect signal today.000are refused at parse.Usage.NONEis removed, soUsagehas exactly three values. A payload whose usage bits are all clear is refused with the newFodId.ParseStatus.NO_USAGE('NoUsage'). The throwing surfaces throw aRangeErrorcarrying thatstatus, with a message naming the bits (51Did payload carries usage bits 000, which is not a usage.), which follows the pattern already used for an unknown payload version. The version is still checked first, so a later version with usage bits000is still reported asUNSUPPORTED_PAYLOAD_VERSION.Usage.fromFlagsthrows aRangeErrorfor000, andUsage.nameandUsage.idUsageanswernullfor a value that is not aUsage. The patterns010,100,101and110read as before, and the payload version stays 0.The creator context section is now 28 bytes. The reader applies only a lower bound to the payload length, so reading is unchanged. No fixture in this package builds a context section of a fixed size, and the live identifiers below have 66 byte payloads (37 + 1 terms byte + 28) and read correctly. No file in this package emits the PMP script tag, so nothing needed changing for the path-only PMP tag.
Files changed
fiftyone.pipeline.did/fodId.jsusageFromConsentrenamed tousageIsIndirectwith new documentation.ParseStatus.NO_USAGEadded, and the payload walk refuses usage bits000after the version check. TheRangeErrormessage names the bitsfiftyone.pipeline.did/usage.jsNONEremoved.fromFlagsthrows for000.nameandidUsageanswernullfor a value that is not aUsagefiftyone.pipeline.did/didClient.jsFactorconstant.RedeemResult.factorsdocumented with the nine names, and still passes every name through unchangedfiftyone.pipeline.did/index.jsFactorfiftyone.pipeline.did/fodIdParseError.jsfiftyone.pipeline.did/types/*.d.tstscfrom the changed sourcefiftyone.pipeline.did/readme.mdNONE, the refusal explained,usageIsIndirectdescribed,NO_USAGEadded to the status and thrown tables, the factors list updated and a paragraph on the four factors saying names pass through unchangedfiftyone.pipeline.did/examples/fodIdExample.jsusageIsIndirectfiftyone.pipeline.did/tests/fodId.test.js000by accident (Reserved type fixtures, the zero flags byte test) now set bit 0, and the version test expectsNO_USAGEfor000under version 0fiftyone.pipeline.did/tests/didClient.test.jsfiftyone.pipeline.did/tests/didClient.integration.test.jsusageIsIndirectTests added
usage bits 000 are refused for the <type> type, and the refusal names them, for all four types, with bit 3 clear and set, throughtryParse,tryFromByteArrayandfromBase64.Usage has exactly the three usages.usage is indirect is bit three, andflags <n> answer usage is indirect <bool>, and only from bit threefor bits 3 set and clear on each usage.the old usage from consent name is gone, with no alias.the four platform and browser factors are read into their names.the factor names are the nine the cloud lists, in its order, which tests theFactorconstant.an old browser factor populates none of the four, and is kept, which checks that none of the four new names is set and thatbrowseris still present under its own name.a factor name this package does not list is passed through.In the first commit, with only the source files stashed (
usage.js,fodId.js,didClient.js,index.js,fodIdParseError.js), all 16 new test cases then present failed (Tests: 16 failed, 161 skipped, 177 total), and with the source change all 16 passed (Tests: 161 skipped, 16 passed, 177 total). The second commit restores the pass-through of factor names, asmainalready did, and adds the pass-through test.Unit tests (
fiftyone.pipeline.didonly, live tests skipped)Before, on
main:After:
ESLint on the changed files reports 0 errors. The warnings it reports are the same JSDoc style warnings as the rest of the package.
Live check against https://cloud.51degrees.com
I created a probabilistic identifier with
id.usage=standard(both the global and the licensed one) and read each one with this branch.tryParsestatusParsedParsedtypeusagestandard)standard)usageIsIndirecttermshttps://m4ow.uk/mtm/2.txthttps://m4ow.uk/mtm/2.txtverifySignature(published keys, offline)verify(cloudid/verify)verify-fullresultresultredeemcontextunreadable, nofactorscontextunreadable, nofactorsThe redeem answered
unreadablebecause the account holds licence keys and the check sent none. The redeem endpoint answersunreadablein that case by design, so the four live factors were not seen in this run. They are covered by the unit tests above.The live integration test file also passes against the service with this branch (
Tests: 4 passed, 4 total), includingTerms checked on 4 marketing identifier(s).andUsage is indirect read on 4 identifier(s)., which shows that identifiers created from a consent string readusageIsIndirectas true.Outstanding
ContextResult.NOT_CHECKABLE('notcheckable') is still listed indidClient.jsand in the readme'sredeemed.contextcomment, and that comment does not listmisconfiguredorinvaliddate. Release 4.4.38 lists onlyverified,mismatch,nocontext,misconfiguredandinvaliddatefor redeem. This pull request leaves that alone.The readme usage example destructuresFixed by the third commit,Termsfrom the package, which the package does not export.DOC: Drop Terms from the readme usage example, as the package does not export it. The example only ever readfodId.terms, so nothing else changed.The same change in the other ports
The Java port of this change is
pipeline-java#140,
which makes the same rename, refuses the same usage bits and reads the same
four factors.
Overlap with other work in this repository
#208 changes the same
demo (
examples/creator-context-web/). The two were merged locally in bothdirections and both merges are clean.
CI evidence for the head commit
mainhas been merged into this branch and the+semver: minorcommit sits ontop, so the head is
5e67566. The "Pull Requests" workflow was dispatched onthat head with
dryrun=true, which builds the branch and merges nothing. Run35267773922
concluded success with all 13 jobs green. In the
Ubuntu_Node_24job theunit tests give
Test Suites: 25 passed, Tests: 361 passedand the integrationtests
Test Suites: 2 passed, Tests: 6 passed, with no error lines anywhere inthe log. The four 51Did suites,
didClient.test.js,fodId.test.js,creatorContextServer.test.jsanddidClient.integration.test.js, all pass.