Rename the usage is indirect accessor, refuse usage bits 000, and read the four browser factors - #140
Conversation
…nd read the four browser factors Following specifications pull request 30, bit 3 of the Flags byte records whether the usage is indirect, so isUsageFromConsent() becomes isUsageIndirect() with no alias. Usage loses NONE, and a payload whose usage bits are all clear is refused with the new status NO_USAGE, whose throwing message says the bits are 000. The other usage patterns keep their reading. Cloud release 4.4.38 reports platformname, platformversion, browsername and browserversion in place of the single browser factor, so the redeem result lists them in the documented order. The creator context example now relays misconfigured as itself rather than as a mismatch.
The live tests created a 51Did, verified its signature and redeemed a result that was deliberately unreadable, so nothing ever read a genuine creator context verdict. This adds the whole round trip with no browser in it: a marketing 51Did is created, the sealed verdict is fetched the way a page fetches it, and the licence key redeems it, which has to report the signature as genuine and the context as verified because one process made both calls.
|
Added one live test, Why. The live tests created a 51Did, verified its signature offline and through How it was checked, against with The same flow by hand, for the record: creating with Two things worth knowing that are not this branch's fault.
|
The factor breakdown comes only with a mismatch, because a verified verdict matched everywhere and has nothing to diagnose, so nothing read the factors at all. This creates the identifier for a stated address rather than for the connection that asked, which makes the address the identifier carries differ from the one presenting it, and then reads all nine factors back by name off the redeemed verdict. Checked against the live cloud, where the answer is a mismatch with browserip and asn differing and the other seven verified. Creating without the stated address gives a verified verdict and the test fails, which is how the arrangement was proved.
|
Second live test added, Why. The factor breakdown only comes with a mismatch, since a verified verdict What the live service answers, 17 September 2026: So the nine names this branch reads are the nine the service sends, including How it was checked: with |
What this changes
This is a breaking rename with no alias, so the next release of these
packages is a minor version rather than a patch. The latest published
version on Maven Central is 4.5.36, 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. The
pom.xmlversion is not the sourceand is left alone.
Three changes reach the 51Did module (
pipeline.did) and its example(
pipeline.developer-examples.fodid). Two come from cloud release 4.4.38and one from the flags byte decision in
specifications pull request 30,
whose
did-specification/identifier-layout.mdanddid-specification/package-surface.mdon the branchdoc/usage-indirect-and-no-empty-usageare the authority.FodId.isUsageFromConsent()is nowFodId.isUsageIndirect(), with no alias and no deprecated forwarder.The documentation says direct against indirect, with a consent string
as the only indirect signal today.
000are refused.Usage.NONEis removed, soUsagehas exactly three values.
FodIdrefuses a payload whose bits 0 to 2are all clear with the new status
FodIdParseStatus.NO_USAGE, addedafter
UNSUPPORTED_PAYLOAD_VERSION. The check comes straight after thepayload version check. The throwing readers (
fromBase64,fromByteArray,fromOwid) throwIllegalArgumentExceptionwith amessage saying the usage bits are 000.
Usage.fromFlagsnow throws for000rather than answering a value. The patterns010,100,101and
110keep their current reading. The payload version stays 0.RedeemResultlists the factors in the ordertransport, device, browserip, connectionip, asn, platformname,
platformversion, browsername, browserversion.
browseris no longer adocumented name. A response that still carries only
browserkeeps itunder that name (as for any name the client does not know) and fills
none of the four new names.
The PMP script tag does not appear anywhere in this repository, so the
change to how it takes the resource key needed no change here.
Files
pipeline.did/src/main/java/fiftyone/pipeline/did/FodId.javaisUsageIndirect()replacesisUsageFromConsent(). Refuses usage bits 000 withNO_USAGEand names it in the thrown message. Adds the package-private masks. Throws documentation updated. A misplaced doc comment onvalueOrThrowis moved back to that method.pipeline.did/src/main/java/fiftyone/pipeline/did/FodIdParseStatus.javaNO_USAGEafterUNSUPPORTED_PAYLOAD_VERSION. Class documentation no longer says there are exactly two payload statuses.pipeline.did/src/main/java/fiftyone/pipeline/did/Usage.javaNONEremoved.fromFlagsthrows for 000.pipeline.did/src/main/java/fiftyone/pipeline/did/RedeemResult.javagetFactors()documentation describes the four new factors,misconfigured, and the oldbrowsername.pipeline.did/README.mdNONErow), refusal paragraph,isUsageIndirect()section, status table (addsUNSUPPORTED_PAYLOAD_VERSIONandNO_USAGE), and the redeem section, which now lists the current context values and has a table of the nine factors.pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdParseTests.javaUsage, the other usage patterns, bit 3 set and clear, and the refusal of 000 with its message. Fixtures that used usage bits 000 for an unrelated purpose now set the non-marketing bit.pipeline.did/src/test/java/fiftyone/pipeline/did/FodIdTests.javapipeline.did/src/test/java/fiftyone/pipeline/did/DidClientTests.javabrowserkey. The Reserved fixture sets a usage bit.pipeline.did/src/test/java/fiftyone/pipeline/did/DidClientLiveTests.javapipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/Main.javaIndirectfromisUsageIndirect().pipeline.developer-examples/pipeline.developer-examples.fodid/src/main/java/pipeline/developerexamples/fodid/CreatorContextDemoServer.javamisconfiguredis no longer turned intomismatch.pipeline.developer-examples/pipeline.developer-examples.fodid/src/test/java/pipeline/developerexamples/fodid/ExampleTests.javamisconfiguredis passed through unchanged.How it was checked
51Did module unit tests (
mvn -pl pipeline.did test, run without aresource key, which is why the four live tests were skipped):
main:Tests run: 146, Failures: 0, Errors: 0, Skipped: 4Tests run: 152, Failures: 0, Errors: 0, Skipped: 4Example module:
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, bothbefore and after.
Each new test fails without the source change and passes with it:
src/mainchanges stashed, the test sources do not compile(
cannot find symbolforisUsageIndirectandNO_USAGE).usageBitsAllClear_*tests fail(
expected java.lang.IllegalArgumentException to be thrown, but nothing was thrown).redeem_FactorsIterateInTheDocumentedOrderfails, because the four newnames come back in the JSON parser's order
(
[... asn, browsername, platformversion, browserversion, platformname]).redeem_OldBrowserFactor_FillsNoneOfTheFourpasses either way, becauseit pins behaviour the client already had.
Redeem_Route_Relays_Factors_On_A_Mismatchfails(
expected: <misconfigured> but was: <mismatch>).Against
https://cloud.51degrees.com, the four live tests inDidClientLiveTestsran and passed (Tests run: 4, Failures: 0, Errors: 0, Skipped: 0). A separate check created an identifier withid.usage=standardand read it with this package:getUsage()STANDARD(standard)isUsageIndirect()falsegetTerms()https://m4ow.uk/mtm/2.txtgetType()PROBABILISTICgetVersion()VERSION3verifySignatureDetailedVERIFIEDverifytrueverify-fullthenredeemverify-fullreturned a sealedresult.redeemwithout a licence key answered 200{"context":"unreadable"}, which parsed asUNREADABLEwith no factors, so the four factors could not be seen live from this check.Outstanding
org.jsonserialises them,not the documented order, because
CreatorContextDemoServer.toJsonbuilds a
JSONObject, which keeps no order.RedeemResult.Context.NOT_CHECKABLEis still public and documented asno longer sent by the service.
factorsneeds a licence key matched to theresource key, which this check did not use.
The same change in the other ports
The Node port of this change is
pipeline-node#202,
which makes the same rename, refuses the same usage bits and reads the same
four factors.
Overlap with other work in this repository
#146 changes the same
demo (
CreatorContextDemoServer.javaand the demo page). The two were mergedlocally in both directions and both merges are clean.
CI on this branch, 17 September 2026
mainhas been merged into this branch and the+semver: minorcommit sits ontop, so the head is
66e034f. The "Pull Requests" workflow was dispatched onthat head with
dryrun=true, which builds the branch and merges nothing. Run35267769781
concluded success with all 15 jobs green across the 11 Java and operating
system configurations. In the
Ubuntu_Java_21job the Maven totals are 635 testsrun, 0 failures, 0 errors and 10 skipped, and there are no error lines in the
log.
Six of those ten skips are the whole of
DidClientLiveTests, which asks for the_51DEGREES_RESOURCE_KEYenvironment variable and skips itself when it isabsent. The pull request workflow passes its key to Maven as
-DTestResourceKey, a different name, so these tests never run in that workflowand never have. They were run on this machine against
https://cloud.51degrees.cominstead, as set out above. The other four skips areLogbackHelperTest, one case inShareUsageElementTestsand two runs of thecloud engine example test, all of which skip on
mainas well.This branch merges cleanly with each of #143, #144, #145 and #146. The nightly
checks out the pull request, merges
maininto it and builds that before itmerges anything, so the combination is tested there as well.