Repository navigation
Name the evidence usage sharing never shares, and the Cookie header - #89
Merged
Merged
Conversation
The accepted evidence section now says that the prefix of a key is everything before its first dot, and that id.email, id.salt, request-query and request-path are never shared, in any mode, as the .NET packages already do. It names the HTTP header that carries cookies as Cookie, which RFC 6265 section 5.4 defines, where it said "cookies", which matches no header, so the raw header no longer undoes the cookie rule. It also gives the session. rule every package already applies.
This was referenced Nov 6, 2026
Merged
Merged
jwrosewell
marked this pull request as ready for review
November 6, 2026 23:14
This was referenced Nov 7, 2026
Merged
jwrosewell
added a commit
that referenced
this pull request
Nov 11, 2026
* Link the Node package to 51degrees-node
* Name the Rust package repository 51degrees-rust (#59)
The rust repository is now 51degrees-rust (51Degrees/51degrees-rust#206).
The list of packages that implement the 51Did specification links
the new name.
* Link the Java references to 51degrees-java (#64)
* Check that only rc merges into the default branch (#67)
* Link the monorepos in place of the old .NET, Python and PHP repositories (#71)
Every link to pipeline-dotnet, device-detection-dotnet,
device-detection-dotnet-examples, ip-intelligence-dotnet, location-dotnet
and caching-dotnet now points at the same file or folder in
51degrees-dotnet, and the 51Did package list names 51degrees-dotnet,
51degrees-python and 51degrees-php. Line numbers that had drifted from
the code their links name point at that code again.
The link to an issue in pipeline-dotnet stays, as issues stayed there.
* Point the IP Intelligence component types at the public property dictionary (#73)
* Drop the JSON builder's SetProperties option (#85)
Neither the .NET nor the Java packages have the option, so the
Configuration options section of the JSON builder now reads None, as the
Sequence element's does.
* Give IP Intelligence latitude and longitude to 3 decimal places (#86)
A value converted from Azimuth or Declination is given rounded to 3
decimal places as a number, a string or a WKT point, because the
locations are rough and more places only lengthen the strings and WKT
shapes. A package may offer a setting for a different number, with 3 as
the default.
* Refuse white space inside a 51Did's base64 text (#88)
A package ignores white space before and after the text and refuses any
other character outside the alphabet, white space inside included, as RFC
4648 section 3.3 requires when the referring specification says nothing
else.
* Refuse a 51Did base64 text that mixes the two alphabets (#90)
* Refuse a 51Did base64 text that mixes the two alphabets
A text uses one alphabet, so a package refuses one holding + or / beside
- or _. RFC 4648 section 5 says the URL-safe encoding should not be
regarded as the same as base64.
* Rest the one alphabet rule on what base64 libraries do
Base64 libraries write one alphabet or the other and never a mix, and
most of their decoders refuse a mixed text. The paragraph now says so
first, keeps RFC 4648 section 5 as agreement, and has a package that
maps one alphabet onto the other check for a mix before mapping.
* Allow a Flow Element to add Evidence values during processing (#91)
The Evidence and thread safety pages said Evidence never changes once
created, while the Sequence Element page said the reference
implementations write the session id and sequence back to Evidence.
The .NET and Java implementations agree that a Flow Element adds values
through the Flow Data during processing, replacing any value held under
the same key, with no check against the accepted Evidence. The pages
now say what they do, and the Sequence Element adds both values to
Evidence as part of its process rather than as a deviation.
* Add query.accept-language to the Translation Engine's evidence keys (#92)
The Translation Engine page listed query.translation then
header.accept-language. The .NET and Java implementations both read
query.accept-language between the two, in that order of precedence, so
the page now lists all three as they do.
* Give lists of strings in configuration examples as comma-separated text (#93)
The pipeline configuration page says a list of strings in a
configuration file is a comma-separated string, which is also the only
form .NET reads. The Derived Property Element example gave Scripts and
ScriptFiles as JSON arrays, and the Translation Engine example gave
Sources as JSON arrays, one with a trailing comma that made the example
invalid JSON. Each is now a comma-separated string, with a sentence
saying so beside each example.
* Name the evidence usage sharing never shares, and the Cookie header (#89)
The accepted evidence section now says that the prefix of a key is
everything before its first dot, and that id.email, id.salt,
request-query and request-path are never shared, in any mode, as the .NET
packages already do. It names the HTTP header that carries cookies as
Cookie, which RFC 6265 section 5.4 defines, where it said "cookies", which
matches no header, so the raw header no longer undoes the cookie rule. It
also gives the session. rule every package already applies.
* Run every example on the free data files, and show what needs the Enterprise file (#79)
* Keep Translation Engine sources and translations in code (#94)
No package reads Sources or Translations from a configuration file. A
translation is a pair of values and AddSource has a two value overload,
so the configuration example now sets only the single value options and
the page says sources and translations are added in code, or by a
builder made for one translation. The example also spells
MissingTranslationBehavior as the builder method does.
* Say that Update Matched User Agent is enabled by default (#95)
The row said the native default applies and then that the option is not
enabled by default. The C library's default configuration sets it to
true, and the .NET builder leaves it at that native default, so the row
and the UserAgents match metric now say it is on by default.
* Define Concurrency as threads, with file handles and cache parts following it (#96)
* Hold the Hash engine's concurrency at what its caches allow
The native code refuses a cache whose parts hold fewer entries than
there are parts, so a profile with a cache read from the file allows at
most the whole square root of its smallest cache's capacity. The
Concurrency row now says the default is held at that number and a
larger named value is refused when the Engine is built.
* Say what Concurrency does in the native code, for both engines
Concurrency is the number of file handles in the pool as well as the
number of parts each cache is split into. An operation that finds no free
handle fails with INSUFFICIENT_HANDLES, and a cache part smaller than
the number of parts stops the Engine building with CORRUPT_DATA, so a
profile that reads through a cache serves at most the whole square root
of its smallest cache's capacity at once. The default is the native 10,
not the processor count. The device detection and IP Intelligence rows
now say this, replacing the earlier wording on this branch.
* Wait for a free file handle rather than fail
James Rosewell decided the file handle pool waits for a handle to be
released instead of failing with INSUFFICIENT_HANDLES. Both Concurrency
rows now say an operation waits, so a low Concurrency slows operations
that read from the file rather than failing them.
* Split caches so any Concurrency builds, defaulting to the processor count
James Rosewell decided how Concurrency works in the native code.
Concurrency is the expected number of operations at once and defaults to
the processor count. It is the number of file handles, and an operation
waits for a free one. Each cache is split into Concurrency parts, or
fewer so that every part holds at least Concurrency items, and a cache
smaller than Concurrency grows to fit, so no value stops the Engine
building.
* Cap the file handles at 64
A process can only have so many files open, 512 through fopen by default
on Windows, shared by every engine. James Rosewell chose a fixed maximum,
so the pool holds Concurrency handles up to 64 and operations beyond that
wait for a free one.
* Usage sharing accepts no Evidence, and reads the web request instead
The Usage Sharing Element accepted every header except Cookie, which made
the Pipeline accept every header, so the ETag and Vary of the client-side
endpoints covered If-None-Match and every other header. It now accepts no
Evidence and shares what it finds in the Flow Data and in the web request,
which the web integration adds as server.http-request.
* Name the client IP address, protocol and request line among what usage sharing reads from the web request
* Say that a Flow Element in a parallel group does not add Evidence (#98)
Thread safety asks only for Evidence that is safe to read from several threads, and the .NET Evidence is a plain dictionary written with no lock, so a member of a parallel group cannot add Evidence while the other members read it.
* Let a package set Translation Engine sources and translations from a configuration file (#100)
* Let a package set Translation Engine sources and translations from a configuration file
The page said a configuration file cannot set sources or translations, on
the understanding that no package read them from one. Go, Node and Python
all do in released versions, so removing the route would break customer
configuration files. A package MAY now offer it, choosing the form for
the two pairs, a translation and a source given as file contents, using
the names it uses in code and documenting the form with an example.
* Leave the file form of sources and translations to pipeline configuration
The paragraph let each package choose how sources and translations are
written in a configuration file. That works against pipeline configuration,
which asks for configuration files that are consistent between languages and
for the same names in the file as in code. The paragraph now keeps the MAY,
what the two pairs hold, and the route in code for a package that does not
offer the MAY, so the existing pipeline configuration rules govern the form.
* Say that PHP's start-up Engine always uses MaxPerformance, for both on-premise engines (#102)
* Say that PHP always uses MaxPerformance, for both on-premise engines
PHP serves requests from worker processes forked from the process that
built the Engine, and a fork copies the open file handles with one shared
read position, so a profile that reads from the file corrupts reads.
PHP device detection already enforces MaxPerformance for this reason and
PHP IP Intelligence is moving to the same rule. The Performance Profile
row on both on-premise pages now gives Balanced as the default except in
PHP, with a footnote saying why.
* Limit PHP's MaxPerformance rule to the Engine built at start-up
Only an Engine built before PHP forks its workers shares file handles
between processes. An Engine built after the fork, or in a process that
never forks, opens its own handles, so it may use any profile.
* Have the PHP footnote's last sentence cover any other Engine
The footnote's first sentence says the Engine built when PHP starts always
uses MaxPerformance. Its last sentence let an Engine in a process that never
forks use any profile, and a start-up Engine in the PHP command line, which
never forks, fitted both sentences. The last sentence now covers any other
Engine, such as one built after the fork or in a process that never forks,
so the start-up Engine always uses MaxPerformance.
* Keep the ETag the same in every process, and send none on a failed response (#53)
* Keep the ETag the same in every process, and send none on a failed response
The ETag of the client-side endpoints is a hash of the Evidence, and a browser
revalidates with the one it kept. The web integration feature now says the
same Evidence gives the same ETag in every process running the same build, so
a restarted server or another one behind a load balancer can match it, and
that a response to a request whose processing recorded errors has no-cache
and no ETag, so a browser does not keep the faulty response once processing
works again.
* Keep a failed client-side response out of shared caches
A response to a request whose processing recorded errors carried bare
no-cache, which lets a shared cache store a response made for one visitor
(RFC 9111 sections 3 and 5.2.2.7), where every other response from the
JSON and JavaScript endpoints is private. Make it private, no-cache.
* Answer a matching If-None-Match with 304 or 412 as RFC 9110 says
RFC 9110 section 13.1.2 gives a 304 to a GET or HEAD request whose
If-None-Match matches and a 412 to any other method, so the rule that a
matching request is answered while processing is failing now says the
same, and agrees with the 412 for a POST to the JSON endpoint. Say that
a failed response differs from the table in two rows, link the Flow
Data errors collection, and name what the paragraph on stale values
is about.
* Say a matching request gets the same status code when processing records errors
The 304 sent while processing records errors carries private, no-cache and
no ETag, so the whole answer is not the same as at other times, only its
status code. When processing throws there is no 304 at all, so the rule now
names the case where processing records errors, and says the header matches
the ETag rather than "it".
* Give each missing Property message as the .NET packages write it (#76)
* Give each missing Property message as the .NET packages write it
The missing Properties table differed from the messages in the .NET
packages' Messages.resx, and had no row for an unknown reason or for a
failed request to the remote server. Bring each message into line with
.NET, name each reason as MissingPropertyReason does, and say how the
reason is decided, as MissingPropertyService and
MissingPropertyServiceCloud do.
* Apply the typed accessor step only to a Property the metadata does not list
A Property the metadata listed, with the Engine's own data file tier and as
available, reached step 3.3 and could be given an upgrade message naming
the tier the customer already has. The .NET packages cannot produce that
case, because their on-premise Engines find no typed accessor and a Cloud
Engine with a listed Property stops at step 3.2. Also say that the type name
in the upgrade message differs between languages.
* Give each missing Property one reason that does not mislead
Decided at review on 5 November 2026. The typed accessor step applies to
On-premise Engines only and counts inherited accessors. A Cloud Engine
without its Property metadata gives CloudRequestFailed when its request for
the property list failed, and Unknown otherwise, and one that read its
Resource Key's product list and found no entry for its element has loaded
metadata with no Properties. The upgrade message leaves out the sentence
naming the data tiers when they are not known. Names are compared ignoring
case, as the Element Data compares them when a value is read.
* Say that .NET is to change to match the missing Property rules
The page called the .NET packages the reference implementation, but
Messages.resx has no text for the second row, and .NET differs from
the section in the five places decided at review. Say which rows .NET's
text gives and what .NET is to change. Make row 6's parameters easier
to read.
* Record the Reuse Operational File option for the IP Intelligence on-premise Engine (#111)
* Check the callback URL before the JavaScript builder writes it (#74)
* Check the callback URL before the JavaScript builder writes it
The protocol and host of the callback URL can come from Evidence, and the
template writes the URL inside a single-quoted JavaScript string. Step 6
now points to a new Callback URL section with the rules every
implementation applies to the scheme, the host, the port, letter case and
percent-encoding. A URL that fails them is left out and logged once.
* Allow only ASCII in a callback URL's host name
A Host header's syntax allows only ASCII, and RFC 3986 asks for an
internationalized name in its IDNA form, so a host name label holds only
ASCII letters, digits, hyphens and underscores, and a configured
internationalized host is given as A-labels. This removes the need for a
Unicode letter test, whose meaning differs between languages. Step 6 now
says what one slash between host and endpoint means, and that a part that
is empty or only whitespace is not set.
* Allow only http and https as a callback URL's protocol
The script uses the callback URL only with fetch and XMLHttpRequest, and
the Fetch Standard's scheme fetch gives a network error for every scheme
but about, blob, data, file, http and https, of which only http and https
reach a server. A callback with any other protocol, such as ftp, gave a
script whose update always failed, with nothing logged on the server.
Refuse it as rule 6 says, and refuse a configured protocol that is neither
when the element is built, as the .NET and Rust builders already do.
* Compare a callback URL's protocol ignoring ASCII case only
Comparing ignoring case in general lets a letter outside ASCII match one
inside it. Java's String.equalsIgnoreCase treats the long s (U+017F) as s,
so httpſ would pass as https and then fail in the browser. Compare
ignoring ASCII case only, as the Rust check's eq_ignore_ascii_case does.
* Refuse a zone identifier, user information, and ? or # in the callback host
RFC 9844 obsoletes RFC 6874, so RFC 3986's IPv6 literal has no zone
identifier again, and the URL Standard's IPv6 parser fails on a %. The
Fetch Standard's Request constructor throws a TypeError for a URL with
credentials, and a ? or # in the host value put the endpoint into the
query or fragment. Refuse all three.
Say that every host the rules accept is one RFC 3986 allows. Define white
space as the Unicode White_Space characters. Say that a configured
protocol of only white space is refused, while an empty one means none
is configured. Log a failed URL the first time for each instance of the
element.
* Refuse a callback host that ends in a number unless it is an IPv4 address
The URL Standard's host parser reads a name whose last label, ignoring a
final dot, is all digits or 0x followed by hex digits as an IPv4 address,
and fails if it is not one, so a browser cannot parse a callback holding
example.123 or 1.2.3.999. Such a name must now be an IPv4 address in RFC
3986's IPv4address form. That also refuses 127.1, 0x7f.0.0.1, 01.2.3.4 and
1.2.3.4., which the URL Standard reads as addresses, so a callback host has
one written form.
Rule 3 now says why all user information is refused. fetch refuses
credentials, but XMLHttpRequest, which the script uses otherwise, accepts
them, and an empty user name is not credentials. Rule 6 now keeps the user
information out of the logged error, so a configured password is never
logged.
* Leave everything before the host value's last @ out of the logged error
Rule 6 left out of the log only what came before the authority's last @,
but a password can hold a / that is not encoded, so the configured host
user:pa/ss@example.com has the authority user:pa, which holds no @, and
the log carried the password. An authority ending at ? or # fails the
same way for user:pa?ss@example.com. The error now shows *** in place of
everything in the host value before its last @, which can leave part of
a refused host out of the log, as exa mple.com/a@b is logged as
https://***@b/51dpipeline/json.
Rule 4 said each part of an IPv4 address has no leading zero, which
could be read as refusing 0.0.0.0. It now says each dec-octet has no
zero before another digit, with examples.
* Refuse an @ anywhere in the callback host value
A password can hold a / that is not encoded, so the configured host
user:12/ss@example.com has the authority user:12, which holds no @ and
passed rules 4 and 5 as the host user and the port 12. Every script
served then carried the password and called back to the host user. Rule
3 now refuses an @ anywhere in the host value, so example.com/a@b is
refused too. Rule 6's example names rule 3 as one that refuses it.
Rule 4 said each dec-octet has no zero before another digit, which by
its words refuses 101. It now says a dec-octet starts with 0 only when
it is 0 alone. RFC 3986 section 7.4 is now cited only for 127.1,
0x7f.0.0.1 and 01.2.3.4, as RFC 3986 reads 1.2.3.4. as a registered
name.
* Define the Hashed Email match key exactly (#87)
* Define the Hashed Email match key exactly
The match key is the SHA-256 of the salt length as one byte, the salt,
then the lowercased address part of the email as UTF-8. The address part
is the addr-spec of an RFC 5322 mailbox, so a display name, angle brackets
and comments do not change the key.
* Say exactly which bytes the Hashed Email match key hashes
Existing keys depend on how the email is read and lowercased, which the
draft did not fix exactly. .NET's MailAddress refuses some obsolete
forms and three current ones, keeps the quote characters and
backslashes of a quoted local part, and puts the address in
Normalization Form C, and ToLowerInvariant uses the Unicode simple
lowercase mapping except for U+0130. Say each of these, define the
white space that is ignored, and add a worked example with a quoted
local part.
* Refuse a Hashed Email that is not a current-syntax RFC 5322 mailbox
The issuer must now refuse every email that is not a mailbox in RFC 5322
section 3's syntax without the obs- rules, such as user name@example.com, a
list of addresses or the obsolete john . smith@example.com, where before it
could accept one when it could read an address part from it. RFC 5322's
syntax is ASCII only, so an email holding a character outside ASCII is
refused too. The issuer may still refuse the three current forms that hold
a line break, a quoted-pair of a space or a tab, or a display name holding a
quoted-string and another word.
* Accept a Hashed Email mailbox that holds UTF-8, as RFC 6532 allows
A mailbox is now one in RFC 5322 section 3's current syntax as RFC 6532
section 3.2 extends it, where VCHAR, ctext, atext, qtext and dtext each
also allow any character outside ASCII written as UTF-8. So an email such
as Üser@Exämple.com is accepted again rather than refused, and a worked
example gives its bytes and Match Key, which do not depend on whether Ü
and ä are written as one character or as a letter and a combining mark.
The issuer may also refuse a domain literal holding a character outside
ASCII, and U+FFFE, as .NET's MailAddress refuses both.
* Remove white space around a Hashed Email before reading it as a mailbox
The page said white space around the email is ignored, but not when.
Since RFC 6532, U+00A0 and the other White_Space characters outside
ASCII are atext, so U+00A0 followed by user@example.com is itself a
mailbox whose address part keeps the U+00A0, and user@example.com
followed by U+000B is not a mailbox at all. Removing the white space
first gives user@example.com for both. The page now says the white
space is removed before the email is read as a mailbox, and that every
rule below applies to what remains. The first use of mailbox now says
it is the one defined below, which RFC 6532 extends.
* Refuse an empty port in the JavaScript builder's callback URL (#112)
* Refuse an empty port in the JavaScript builder's callback URL
Rule 5 allowed a port of `:` followed by nothing. The authority is the
host value up to its first `/`, so the configured host
`https://example.com` has the authority `https:`, which passed rules 4
and 5 as the host `https` with an empty port. The script then carried
the callback `https://https://example.com/51dpipeline/json`, which a
browser reads as the host `https`, and nothing was logged on the server.
A port now needs at least one digit, so `example.com:` and every host
value that starts with a scheme and `://` are refused. RFC 3986 section
3.2.3 allows an empty port in its syntax but says URI producers should
omit an empty port and its `:`.
* Mark the cut in the RFC 3986 section 3.2.3 quote
* Never share the Cookie header, and define the request view by named parts
* Say that an element which declares no evidence accepts none (#103)
* Usage sharing accepts no Evidence, and reads the web request instead
The Usage Sharing Element accepted every header except Cookie, which made
the Pipeline accept every header, so the ETag and Vary of the client-side
endpoints covered If-None-Match and every other header. It now accepts no
Evidence and shares what it finds in the Flow Data and in the web request,
which the web integration adds as server.http-request.
* Say that an element which declares no evidence accepts none
* Name the client IP address, protocol and request line among what usage sharing reads from the web request
* Never share the Cookie header, and define the request view by named parts
* Agent signature accepts only the Evidence the page names (#104)
* Agent signature accepts only the Evidence the page names
The Agent Signature Element asked for every header.* Evidence key, so the
Pipeline's accepted Evidence, and with it the cache keys, the ETag and the
Vary header, took in every header the request carried.
The element now accepts the three signature headers, header.host,
header.protocol and the three server.request- keys. Any other header a
signature covers is read from the web request supplied as
server.http-request, which no Flow Element accepts. The Rebuilding the
signature base list says the same.
* Read other covered headers from the Evidence first, then the web request
A covered header that is not one of the eight accepted keys is now taken
from the Evidence where the Flow Data holds it, and otherwise from the web
request supplied as server.http-request. The Usage Sharing Element reads
the same two places and uses the Evidence value for a key found in both.
Only where neither holds the header does the signature report Unverified
with ComponentUnavailable, so callers who pass headers in directly keep
working.
* Describe the trust forwarded Evidence option
"The Element accepts these eight Evidence keys and no others" was false
when forwarded Evidence is trusted. With the option on, the element also
accepts the same eight names under the query. prefix and no other query.
key. A forwarded signature is read from the query. keys, and its other
covered headers from the Evidence first and otherwise from the web request
supplied as server.http-request, whose query string values carry the
query. prefix. The option is off by default because a visitor could
otherwise put a captured signature in a query string and have it reported
as Verified. The option is added to the configuration table.
* Refuse a covered header the Element does not accept
A signature that covers a header outside the accepted Evidence reports
Unverified with reason ComponentUnavailable. The Element no longer reads
such a header from other Evidence or from server.http-request, with or
without trusted forwarded Evidence, because a header outside the cache
keys, the ETag and the Vary header could otherwise give a cached Verified
answer for a request that differs only in that header. Step 1 names the
query. forms of the two signature headers where forwarded Evidence is
trusted.
* Refuse eval, arguments and nine browser globals as the JavaScript object name (#113)
* Refuse eval, arguments and eight browser globals as the object name
The script declares its object with a top level var that is not strict
mode code, so the object name eval replaces the page's own eval
function. Strict mode code cannot declare eval or arguments, in the
same way as the words reserved in strict mode, which the list already
refuses.
In a browser a top level var cannot replace window, document, top,
name, status, history, navigator or closed, so the object is never
created. That is the reason the page already gives for Infinity, NaN
and undefined, so the same list item now carries all eleven. name and
status keep only the text [object Object].
* Refuse location as the object name
The Window object declares location with [PutForwards=href], so in a
browser a top level var location sets location.href to the object's
text, [object Object], and the page navigates away. Chrome 156 took a
test page holding var location = {fod: 1}; to [object%20Object].
* Agree the high entropy decoder page with the Evidence page (#116)
* Agree the high entropy decoder page with the Evidence page on adding values
* Keep the Engine requirement unconditional and exclude parallel groups
* Limit tilde paths to .NET web applications (#117)
* Limit tilde paths to .NET web applications and state how relative paths resolve
* Align the conceptual overview with the file paths page and name the .NET tilde roots
* Note that .NET still writes its own usage sharing record (#118)
* Note that .NET still writes its own usage sharing record
* Describe the .NET record accurately and say other languages follow the specification
* Say what available means in the high entropy decoder (#119)
* Say what available means in the high entropy decoder, and name the second key
* Say an available value gives at least one header, and that one key wins
* Name the Sequence Element's Element Data key (#120)
* State how invalid characters and long values are written in the usage sharing record (#122)
* State how invalid characters and long values are written in the usage sharing record
* Say the length limit counts code points and quote the escaped attribute in the snippet
* Say the limit applies before escaping, add the length difference to the .NET note and explain surrogate pair
* Refuse nineteen more read-only Window properties as the JavaScript object name (#114)
* Refuse twelve more read-only Window properties as the object name
frameElement, isSecureContext, crossOriginIsolated, trustedTypes,
crypto, indexedDB, localStorage, sessionStorage, caches, cookieStore,
speechSynthesis and styleMedia are read-only properties of the Window
object, so a top level var cannot replace any of them and the object
would never be created, which is the reason the list already gives for
window, document and the other browser names. They join that item,
which now lists its names by the specification that defines them.
caches and cookieStore exist only in a secure context, and styleMedia
is defined by Chrome and by no standard.
* Refuse seven more read-only Window properties as the object name
crashReport, credentialless, customElements, documentPictureInPicture,
fence, launchQueue and originAgentCluster are read-only properties of
the Window object, so a top level var cannot replace any of them and the
object would never be created. customElements and originAgentCluster
join the HTML Standard's names, and the other five are listed with the
Web Platform Incubator Community Group drafts that define them.
documentPictureInPicture exists only in a secure context.
* Say the Window names fail in a secure context, and the three secure-context names are refused everywhere
* Keep license keys out of log entries and error messages (#55)
* Keep license keys out of log entries and error messages
The data update request's URL carries the license keys in its query, and the
data update logging section names that URL in its messages, so following the
specification wrote the keys to the log. The logging feature now says a
license key never appears in a log entry or an error message, and that a
message naming a URL that carries one names it with the key removed or
replaced. The data update logging section says the same of its URL.
* Mask a license key to its last 4 characters in logs and error messages
* Mask a license key to its last 4 characters in logs and error messages
* Replace a short license key entirely, and rewrap the license key section
* Say the Cloud Request Engine's License Key is masked in logs
* Describe usage sharing's session tracking, back-off and repeat interval (#97)
* Describe usage sharing's session tracking options, as .NET has them
.NET's usage sharing builder has SetTrackSession, false by default, and
SetAspSessionCookieName, which names the session cookie and has no
effect unless session tracking is on. The configuration options listed
neither, and the session tracking section did not say how the session
cookie is used.
The session tracking section now says how the session cookie is
compared, and the accepted Evidence section says the filter accepts
it so the tracker can read it, without sharing it. The table lists
both options, and the five recovery settings the .NET builder still
accepts, with .NET's defaults. The recovery settings have no effect,
because usage sharing no longer has a back-off, and the text says so.
The maximum queue size default is now the one .NET uses, 1000 or ten
times the minimum entries per message if that is larger.
* Make the usage sharing back-off and the repeat window normative
The five recovery options now set a back-off that every usage sharing
element MUST have, in place of the rows that said they have no effect.
Repeated failed sends pause sending, never processing. Evidence is still
queued during a pause, the first send after a pause is a trial that
lengthens the pause if it fails, a success ends the back-off, and the
queue drains as soon as a pause ends without waiting for more requests.
Cleanup does not wait for a pause or send during one, and nothing is
logged for each entry dropped from a full queue.
The repeat Evidence interval is a sliding window that starts again each
time Evidence is shared, so identical Evidence is shared at most once in
each interval. The old text reset the lifetime each time matching
Evidence was processed, which would stop Evidence seen continuously from
ever being shared again, and .NET and Java followed neither.
* Read the session cookie from the web request, as usage sharing accepts no Evidence
The paragraph let the filter accept the session cookie, and required it
when session tracking is on. rc now says the Usage Sharing Element MUST
NOT accept any Evidence, and reads what it shares from the Evidence in
the Flow Data and the web request supplied as server.http-request, with
the Evidence value used for a key found in both. The paragraph now says
the element accepts no session cookie, and with track session on reads
the cookie from those same two places, so the session tracking can
compare it. The session cookie is still not shared unless all Evidence
is shared.
* Describe the repeat interval and the session cookie hash exactly
* Say that a lookup of profiles by property value matches exactly, through the native code (#101)
The on-premise engine gives the profiles holding a value of a property,
such as a TAC or native model name, through
EngineHash::getProfileIdsForPropertyValue, which matches the name and the
value exactly as the data file holds them. A language uses that function
rather than an index of its own, so every language gives the same answers.
The Indexed Properties option names the properties the native code indexes.
* Specify the hardware profile lookup on premise (#62)
* Describe the on-premise hardware profile lookup
The new page describes finding the hardware profiles holding a TAC or a
native model name without a remote server, which the native component gains
in 51degrees-cxx#66. The native data set builds an index of the profiles
holding each value when it is initialized, and builds it again with the new
data set when the data is refreshed. A value returns every matching profile
in the order of the data file. The page lists what each language exposes.
The cloud lookup, the on-premise Device Detection page and the required
examples link to it, and the on-premise page lists the property value index
option.
* Name the Properties to index in the on-premise lookup
The native index of profiles by value is now built only for the
Properties the caller names, whatever the performance profile, as
51degrees-cxx#66 now does. A named Property is indexed whether or not it
is required, and a refresh indexes the same Properties again. The page
says how each language names them.
The on-premise Device Detection page lists the Indexed Properties option
in place of the property value index option, which the lookup no longer
depends on.
* Keep the ids and read the profiles when profiles is first read
Process steps 3 and 4 said to populate a device data for every id during
Process and set them as profiles. The .NET Engines keep the ids alone
during Process and read the profiles the first time Profiles is read, so a
value held by many profiles costs only the lookup. James Rosewell decided
to follow .NET here, with no limit on the number of ids.
Checked at 51degrees-dotnet 4d7152bfcb7c9bcb17d14cb512025b65a3307313.
PropertyKeyedDeviceBaseEngine.ProcessProfileMatch calls AddProfileId alone
(device-detection/PropertyKeyed/FlowElements/PropertyKeyedDeviceBaseEngine.cs
lines 164 to 170). MultiDeviceData keeps the ids, resolves them on the
first read of Profiles and keeps that list until another id is added
(device-detection/PropertyKeyed/Data/MultiDeviceData.cs lines 58 to 107
and 122 to 184).
Follows https://github.com/51Degrees/51degrees-rust/pull/333.
* Say that the JSON writes the on-premise profiles as an empty list
The .NET on-premise JSON writes hardware.profiles as an empty list however
many profiles match. MultiDeviceData stores an empty list under Profiles
when it is made (device-detection/PropertyKeyed/Data/MultiDeviceData.cs
line 98 at 51degrees-dotnet 4d7152bfcb7c9bcb17d14cb512025b65a3307313),
only AddProfile adds to that list (lines 113 to 117), and nothing on
premise calls AddProfile. The JSON builder reads the Element Data through
AsDictionary (pipeline/JsonBuilderElement/FlowElement/JsonBuilderElement.cs
lines 591 to 609), so it reads that list and never the ids.
The Element Data section now says so, linking the JSON Builder's Process,
where the matching exception is proposed separately into rc.
Follows https://github.com/51Degrees/51degrees-rust/pull/333.
* Follow the profiles for a property value section, and update the .NET and issue links
Leaves the Indexed Properties row to the profiles for a property value
change, which adds the same row and merges first, so the page carries one.
The lookup now matches, orders and finds profiles as that section requires,
each profile once, and an Engine of this kind MUST use the native lookup.
The .NET paragraph says what the TAC and native model engines do now, and
the issue links point at 51degrees-dotnet#30 and 51degrees-java#17.
* Name the cxx commit, say the empty profiles list is .NET behaviour and claim only what the data README shows
* Never cache a result that holds a value created for one request (#48)
* Never cache a result that holds a value created for one request
A 51Did is created for the one request that asked for it, so a cache that
stores the Cloud Request Engine's response hands it to the next request
with the same Evidence. The caching feature now says a cache must neither
store nor serve such a result.
* Match fodid in any case and keep the process flow in step with the cache exclusion
* Count only service trouble towards a recovery period (#54)
* Count only service trouble towards a recovery period
The Cloud Request Engine's recovery period is shared by every request it
handles, but the recovery mode section did not say which failures count. It
now says a failure counts only when it says the cloud service is in trouble,
being a request that did not complete, a status of 500 or more, a 429 or an
unusable success response, and that any other 4xx answer, which is about the
one request's own content, does not count. One visitor's requests can then
no longer stop every visitor's cloud requests.
* Say that 408, 401 and 403 do not count towards the recovery period
* Say that the JSON builder writes element and property keys in lower case (#83)
The .NET and Java JSON builders write each Element Data's key and each
Property's key in lower case, suffixes included, and keep the capital P of
javascriptProperties. The specification did not say, and its suffix table
showed EvidenceProperties with capitals where both write evidenceproperties.
* Mask a license key with one * for each hidden character (#123)
* Say the ETag is calculated from the Evidence as the request supplied it (#121)
* Say the ETag is calculated from the Evidence as the request supplied it
The web integration page says the ETag covers all the Evidence values in the Pipeline's Evidence filter, without saying whether that is the Evidence supplied or the Evidence after processing.
* Make the ETag table row and the Evidence page agree with the ETag paragraph
* Say what the verification outcomes are, and what to do with one a package does not know (#33)
* Say what the verification outcomes are, and what to do with one a package does not know
The page covered the parsed identifier fields and said nothing about the
Signature outcome, the Context outcome or the per-factor block, although
all six packages expose them. A fourth factor outcome is being added for
a factor the issuer recorded no value for, and there was nowhere to say
what it means or why it is not a mismatch.
The new section states the three answers in a verification response, the
factor outcomes and their meanings, and the rule that a word a package
does not know is exposed distinguishably and never reported as a
mismatch. It also records that the factor block keeps no raw word where
the context outcome does, and that the packages differ over an unknown
word, as a gap to close across all six together.
* Report a factor word a package does not know as a Mismatch
The subsection required an unknown factor word to be exposed apart from
the known values and never as a Mismatch, and called the packages'
differences a gap. The .NET and Rust packages both read verified,
misconfigured and notrecorded each from its own word and every other
word as a Mismatch, so an unexpected value never reads as a pass. The
subsection now says the same, states the cost for a package that
predates a new word, and keeps the note that the Context outcome carries
the word the server sent.
* Run the pull request checks against rc, now the base
* Give the words the server sends, report an unknown Context word as Unreadable and compare ignoring case
* Never fail the Pipeline build for a Cloud Aspect Engine's missing product (#75)
* Never fail the Pipeline build for a Cloud Aspect Engine's missing product
What a Resource Key includes can change while the application runs, and
the remote server reports on each request what that request can have. A
missing product is logged once when the Pipeline is built rather than
failing it, and Properties absent from the Property metadata are not
logged on every response.
* Say only that a missing product builds, logs once and warns on no response
A Cloud Aspect Engine whose Resource Key includes no product for it now
builds with empty Property metadata, logs the missing product once, and
logs no warning on each response because of it. The reasons and the
description of what the remote server returns are left out of the page,
and the SHOULD on the log becomes a MUST.
* Say when the missing product is logged, how often and at what level, and what Processing does
* Send the client-side ETag as a weak entity tag (#115)
The ETag is a hash of the Evidence alone, so a data file update that
changes the JSON or JavaScript for the same Evidence leaves it as it
was. RFC 9110 section 8.8.1 defines a strong validator as one that
changes whenever the content of a 200 response to GET changes, so this
ETag is not one, and section 8.8.3 says an origin server MUST then mark
it weak with the prefix W/. The table row now gives the weak form, and a
new paragraph says why, with the weak comparison section 13.1.2 requires
for If-None-Match, so a revalidation still matches.
* Say that the JSON builder fails when the Evidence holds no sequence number (#80)
* Say that the JSON builder fails when the Evidence holds no sequence number
The JSON Builder Element reads the sequence number from the query.sequence
Evidence that the Sequence Element writes back as an integer. The .NET and
Java packages fail the Element and set no JSON when that value is missing,
which happens when no Sequence Element ran before the JSON builder. The
specification was silent on that case and said the Element used no Evidence,
so it now says what .NET and Java do.
* Define the sequence number as the Sequence Element's output
Evidence is immutable in the specification, so the sequence number is the
Sequence Element's Element Data, and the .NET and Java reading of the value
written back to query.sequence is described as how those implementations get
it. A caller's integer in query.sequence MAY be accepted only where Evidence
holds typed values, because where it holds only text it cannot be told apart
from a query string value.
* Say that .NET and Java read the number the Sequence Element adds to Evidence
A Flow Element may now add values to Evidence, and the Sequence Element
page says it adds the session id and sequence there. Reading the
sequence number from query.sequence is therefore reading the same number
the Sequence Element produced, as the specification allows, rather than
a different reading.
* Read the sequence number from the integer in query.sequence and drop the Rust-only rule
* Say that a web integration response after the Element fails is not the Element's JSON value
* Say that a batch whose send failed is dropped and not queued again (#124)
* Say which client IP values the IP Intelligence Engine reads (#110)
* Say which client IP values the IP Intelligence Engine reads
The Engine reads a client IP value only when all of it is one IPv4 or
IPv6 address, with a port and brackets allowed. Any other value is not
read and the next key in the order of precedence is tried. A zone index
is not read.
* Refuse a client IP value with a zone index or a leading zero
* Say which credential keys the cloud service advertises and reads, and leave out licence (#125)
* Say that the cloud service advertises query.values, not the credential keys
The live evidencekeys list holds query.values but neither query.resource
nor query.license, so the reason for leaving out Evidence that strips to
values, resource or license now names only query.values, and says the rule
keeps resource and license so the credentials are never sent twice.
* Leave out Evidence that strips to licence too, as the cloud reads the License Key from it
The cloud service reads the License Key from licence where license is absent, in the route, the query and the form, so Evidence stripping to licence is a second License Key field in the same way as license, and is left out with it.
* Leave out the credential and values fields in any letter case, and say the Engine always sends license
Evidence keys are compared without regard to case elsewhere, so a package that compared licence exactly would miss Licence. The License Key section now says the server also reads licence and the Engine always sends license, to keep the two places in step.
* Name the License Key in its MAY sentence, and shorten the rule's last sentence
The MAY sentence followed one about the Engine, so its it read as the Engine. The rule's last sentence repeated the paragraph and now says only that it does not depend on which keys the server advertises.
* Say how a usage sharing message is filled, from the minimum to twice it (#56)
* Say how a usage sharing message is filled, from the minimum to twice it
The processing section said the number of items per batch is the minimum
entries per message, while the take timeout setting described waiting for
items to add to the next payload, and the .NET and Java elements use it to
fill a message up to twice the minimum. The section now describes that rule,
so a message holds from the minimum entries to twice the minimum, the take
timeout applies only while a message is being filled, and the final message
on disposal holds whatever is left.
* Say the back-off pauses starting a message, and bring disposal and the other descriptions in line
A message is started at the minimum only while sending is not paused by
the back-off. Disposal sends the remaining data even below the minimum, as
the Cleanup section says, without saying it is one message. The processing
overview and the minimum entries and take timeout rows now describe the
same fill rule as the numbered steps.
* Weighted values show the serialized keys in lower case (#72)
* Weighted values show the serialized keys in lower case
The example showed RawWeighting and Value. The 51Degrees JSON Builder Element
writes them in lower case, and the Cloud Engines read them in lower case.
* Make the lower-case weighted value keys a MUST, and correct the IP Intelligence cloud page
.NET writes rawweighting and value, the remote server sends them, and both
readers expect them, so the keys MUST be lower case, as the JSON Builder's
other keys are, and a reader MUST accept them. The IP Intelligence cloud
page said the objects had value and weight fields, and now names
rawweighting and value with a link to the serializing section.
* Write the on-premise hardware profiles as an empty list, and a record's nulls with their reasons (#107)
* Write the on-premise hardware profiles as an empty list
The Process said every Element Data is written with a sub-entry for each
Property and its value. The on-premise hardware profile lookup keeps the
ids it finds and reads the profiles only when profiles is first read, and
.NET writes its profiles as an empty list however many profiles match.
James Rosewell decided to follow .NET.
Checked at 51degrees-dotnet 4d7152bfcb7c9bcb17d14cb512025b65a3307313.
MultiDeviceData stores an empty list under Profiles when it is made
(device-detection/PropertyKeyed/Data/MultiDeviceData.cs line 98), only
AddProfile adds to it (lines 113 to 117), and the on-premise Engine calls
AddProfileId alone
(device-detection/PropertyKeyed/FlowElements/PropertyKeyedDeviceBaseEngine.cs
lines 164 to 170). The JSON builder reads each Element Data through
AsDictionary (pipeline/JsonBuilderElement/FlowElement/JsonBuilderElement.cs
lines 591 to 609).
The Process now names that exception, and the TAC example says it is
from the cloud service, as only the cloud's profiles are written.
Follows https://github.com/51Degrees/51degrees-rust/pull/333.
* Write a null with its reason inside each record of a list
The Process said nothing of a Property whose value is a list of Element
Data, such as profiles in the cloud hardware profile lookup. James Rosewell
decided that a record writes a Property with no value as null with its
nullreason, as the top level does and as the cloud sends.
The .NET JSON builder writes each item of such a list through the same
method as a top-level Element Data, which writes null and the nullreason
for a Property with no value
(pipeline/JsonBuilderElement/FlowElement/JsonBuilderElement.cs lines 742
to 752 and 764 to 773, at 51degrees-dotnet
4d7152bfcb7c9bcb17d14cb512025b65a3307313).
The wording asks for the nullreason to be added, not for it to follow the
null, because RFC 8259 section 1 says a JSON object is an unordered
collection of name/value pairs, and the nullreason row of the table asks
for no order either.
Follows https://github.com/51Degrees/51degrees-rust/pull/333.
* Write a Property with no value as null, and leave out one that is only null
The .NET and Go JSON builders write a Property that has been assigned 'no
value' as null with its nullreason, and give no entry to a Property whose
value is null without having been assigned 'no value', so the page now says
the same, at the top level and in each record of a list.
* Narrow the left-out null to its own entry and nullreason, and state the empty profiles list as a rule
A Property whose value is null without 'no value' now has no entry of its own and no nullreason, which leaves the delayexecution and evidenceproperties rows to say when they are written, as .NET writes evidenceproperties outside its null check. Records follow the same two rules. The on-premise hardware profile lookup page now states the empty profiles list as the MUST the JSON builder page gives, rather than as .NET behaviour.
* Word the empty profiles rule the same way on both pages
* Allow Element Data to be read from several threads by a parallel group (#78)
* Allow Element Data to be read from several threads by a parallel group
The Element Data section said instances are only ever accessed from a
single thread. The Flow Data section already says Element Data is added in
parallel when the Pipeline has a group, and every member of a group
processes the same Flow Data at once, so data written before the group is
read by all of them together, as .NET's ParallelElements does. Say so,
require reading a finished instance to be safe from several threads, and
keep writing to a single thread.
* Say that Element Data whose reads write into its results locks each read
Finished Element Data must be safe to read from several threads, which
Aspect Data reading from native results meets only by letting one thread at
a time make each read, as .NET's DeviceDataBaseOnPremise does with a lock,
or by being a type the language does not share between threads. Aspect Data
is Element Data, so the Aspect data section now follows that rule rather
than leaving thread safety as a SHOULD.
* Use the same rule sentence as the on-premise pages, and end the lock's line range where it closes
One thread at a time reads from the results, in the words the on-premise pages use, and the Element Data, not an ambiguous it, is the type the language may not share. The .NET lock closes on line 589.
* Say how on-premise engines find properties, read graphs and use results on threads (#61)
* Say that on-premise engines find properties through the results
The position of a property in a data set's required properties depends on
that data set, so an index a language keeps of its own goes wrong after a
reload. The IP Intelligence and Device Detection on-premise pages now say an
implementation keeps no such index and finds properties through the results,
and that the data set builds what is needed when it loads and frees it with
itself. The performance guidance about storing values until a refresh now
says it does not apply to the positions of properties.
* Read by name with the existing methods, and keep the UTF-8 copy by position
The copy that reads a value by position is for the fastest read, so it has no
form taking a name, and the position must come from the data set of the same
results. The rule for naming Properties to process is removed, as process takes
no names.
* Follow the names the Engine was created with for positions, and say how graphs are read
A position is now the index of a Property's name in the names the Engine was
created with, so a data refresh keeps it and no language keeps a map of its own.
Reading graphs says a graph is walked on the first read of a Property of its
component. Results and threads says a results instance is used by one thread at
a time, and how Aspect Data keeps to the thread safety rules.
* Walk graphs in process when Properties are named, and at first read when none are
Reading graphs and the reason in Results and threads follow the rule the
native code's main branch implements. An Engine created with names walks
the graphs of the named Properties' components in process, and one created
with no names walks each component's graph at the first read of one of its
Properties.
* Require Aspect Data to lock each read of its results, as finished data is read by several threads
Thread safety now requires finished Element Data to be safe to read from
several threads at once, because a parallel group reads it together, so
Aspect Data that reads from a ResultsHash or ResultsIpi instance MUST let
one thread at a time read it, as .NET does, unless the language does not let
threads share it. The cache sentence for unlocked Aspect Data goes, as no
such Aspect Data is allowed.
* Use the same rule sentence as the thread safety page
One thread at a time reads from the results, in the words the thread safety page uses, and the Aspect Data, not an ambiguous it, is the type the language may not share.
* Say how a WKT value is written to JSON (#106)
* Say how a WKT value is written to JSON
The value types page said what a WKT value is but not how it is written
to JSON. It is written as an object holding the WKT text under `value`,
as the .NET JSON builder writes it and the .NET IP Intelligence Cloud
Engine reads it, which reads no other form.
List WKT among the types the JSON encode and decode logic adds, in the
Value types section of the Properties page.
Point the IP Intelligence data model's WKT link at the WKT section of
the value types page, because the anchor it used does not exist.
* Fix the null values link in value-types.md
The link in Property Details went up a folder and back into
pipeline-specification, so it pointed at a page that does not exist.
properties.md sits beside value-types.md.
* Name Java as well as .NET for the WKT JSON form, and let a reader also accept a plain string
Java writes and reads {"value": ...} too. Java's reader also accepts the WKT text as a plain string where .NET returns null, so a reader MUST accept the object and MAY accept the string.
* Name the reader in the MAY sentence
It MAY read as this form, so the sentence now says A reader MAY.
* Say that an unusable session id or sequence counts as not present (#127)
* Say that an unusable session id or sequence counts as not present
* Pin down the digits allowed, leading zeros and the sequence of 0
* Fetch the accessible Properties under a License Key alone, with the key in a POST body (#128)
* Fetch the accessible Properties under a License Key alone, with the key in a POST body
The accessibleproperties endpoint answered 401 to a License Key alone when measured in September, so the page said to skip the request. It now answers with every Property the License Key entitles, for GET and POST, so an Engine on a License Key alone makes the request, with the key in the body to keep it out of request logs, as the Python and Rust engines do, and its Cloud Aspect Engines take their metadata from the answer.
* Bring the aspect engine page and the resilience note into line, and date the measurement
The Cloud Aspect Engine page said a License Key alone cannot resolve accessible Properties. It now points at Discovery under a License Key and keeps the rule that an engine works with empty metadata. The persisted discovery results depend on the configured credentials, not the Resource Key alone. The discovery section records the 10 November measurement as the old text recorded its own.
* Drop the note that no implementation persists the discovery results (#129)
The Go Cloud Request Engine now reads back and accepts its discovery results through its builder, so the sentence is no longer true, and a list of implementations would go out of date as others follow.
* Add delayexecution only for a Property that has a value (#130)
James Rosewell decided on 10 November 2026 to relax the rule to Properties with a value, as .NET and Java already write it, adding delayexecution only inside their check that the value is not null.
* Honor Requested Properties beside a Resource Key when a License Key is sent (#131)
* Honor Requested Properties beside a Resource Key when a License Key is sent
James Rosewell decided on 10 November 2026 that with both keys the remote server uses the Resource Key's licence and the License Key given, and the response holds the Resource Key's Properties plus the Requested Properties the License Key grants. The live service already answers that way. A Resource Key with Requested Properties and no License Key is still refused, as the list is ignored.
* Say exactly what Requested Properties do beside a Resource Key with no License Key
The list is not simply ignored. A requested Property the Resource Key carries changes nothing, and one it lacks comes back null with the paid feature nullreason, so the list adds no data. Records the five measured cases, and why the server answers so: it merges the Resource Key's licence and Properties with the request's before checking entitlement.
* Accept Requested Properties with a Resource Key and no License Key
James Rosewell corrected the table on 10 November 2026. The requested Properties are added to those the Resource Key carries, one no licence grants is answered as null with the paid feature nullreason, and a name that is not a Property is not returned, so the combination is valid and no Engine refuses it.
* Say that usage sharing always shares the Resource Key and License Key (#132)
James Rosewell decided on 10 November 2026 that the keys are always shared. A Pipeline that authenticates holds them as fiftyone.resource-key and fiftyone.license-key, and the filter shares both whatever its configuration, because usage is counted against them.
* Say that a Resource Key may carry Requested Properties in the Properties not returned section and the configuration table, and correct the reading of the 21 September measurement (#133)
* Say how a Device Detection Engine gives each data file property's value (#105)
* Say how a Device Detection Engine gives each data file property's value
Adds a Property values section to the on-premise Device Detection page.
It says where a data file Property's value comes from, what a List, a
string, a Boolean and a number give, and how JavascriptHardwareProfile
values are wrapped. It also says the match metric Properties come after
the data file Properties, in the order of their table.
Adds a paragraph to value-types.md saying how a typed accessor reads a
Boolean or number stored as a string.
Gives the cloud example response a string null reason for
javascripthardwareprofile, as json-builder.md asks.
* Number the Property value rules, say the Profile holds the values, and use the native no-value message
The Property values paragraph chained conditions with "Otherwise", each
referring to a different earlier one, and is now five numbered rules. The
value types text says the Profile, not the result, holds more than one
value. The cloud example's null reason is now the C library's message for a
Property no result holds a value for (hash.c, NO_RESULT_FOR_PROPERTY),
rather than wording that no implementation produces.
* Show the cloud example's null reason as the cloud returns it
No code path gives the message the example used. The live cloud service answers javascripthardwareprofile with null and javascripthardwareprofilenullreason with null for a phone and a desktop whose Profile holds no value, so the example keeps that.
* Limit the match metric order to the Property metadata
A JSON object is an unordered collection of name/value pairs (RFC 8259 section 1), and Element Data is a map in several languages, so the order of the table applies to the Engine's Property metadata, which every language keeps as a list.
* Show the null reason the C++ results give once they report a Profile holding no value
The C++ results gave no reason when the matched Profile holds no value for a Property, so the cloud answered null, which the JSON Builder page does not allow. The C++ fix reports NO_RESULT_FOR_PROPERTY with its message, so the example shows that message.
* Say what the endpoints answer to a matching If-None-Match (#81)
* Say what the endpoints answer to a matching If-None-Match
A GET or HEAD gets a 304 and any other method a 412, as RFC 9110 section 13.1.2 requires, and a 304 carries the headers a 200 would, as section 15.4.5 requires.
* State the 304 or 412 rule once, and give the 304 headers after it
rc now states the 304 or 412 rule, with the RFC 9110 section 13.1.2
citation, in the paragraph on a matching If-None-Match while processing
records errors. This branch's own statement of the same rule is removed,
and the earlier sentence that said the endpoint can just return a 304
now says only that the content is not sent again and that the status
code depends on the method, as described below.
The paragraph on the headers a 304 carries, from RFC 9110 section
15.4.5, now follows the rule it depends on.
* Say that usage sharing cleanup should complete within 5 seconds (#135)
* Say that the endpoints answer a matching If-None-Match without processing (#136)
* Say that the endpoints answer a matching If-None-Match without processing
* Make comparing If-None-Match before processing a MUST, as RFC 9110 requires
* Say a matching request would record errors, as it is not processed
* Leave the session id and sequence out of the JavaScript builder's parameters (#84)
The .NET and Java JavaScript builders leave query.session-id and
query.sequence out of the parameters passed to the template, because the
template adds both to each callback itself. The specification said to take
every query. Evidence value.
* Say that the JSON builder leaves its own Element Data out of the JSON (#82)
The .NET and Java JSON builders add their own Element Data to the Flow Data
before building the JSON, and leave it out with an exclusion list of
set-headers, cloud-response and json-builder. The specification's list named
the usage sharing element, which adds no Element Data, and did not name the
JSON builder itself.
* Log once when a derived property's source Element runs too late (#77)
* Log once when a derived property's source Element runs too late
The specification said nothing about the error the .NET packages log when
a request carries no Element Data…
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.
Problem
The accepted evidence section of the usage sharing element left three things open, and the packages answered them differently.
.and applied its rules only to keys with exactly two parts, soquery.id.emailwas shared whatever the allow list said (51degrees-java#50).id.email,id.salt,request-queryorrequest-path, in any mode (EvidenceKeyFilterShareUsage.cs), and the other languages shared them.cookiesHTTP header". HTTP has no header calledCookies. The request header that carries cookies isCookie(RFC 6265 section 5.4), and every web integration adds it asheader.cookiewith every cookie in it. The packages blockedcookiesor nothing, so the raw header was shared and undid the rule that only51D_cookies are shared.Change
.and the field is everything after it. Keys are compared without regard to case.id.email,id.salt,request-queryandrequest-pathMUST NOT be shared, matched as the whole key or after a., even when all Evidence is shared. The section gives the reason for each and an example thatquery.valid.emailis not caught.header.cookieMUST NOT be shared. The51D_cookies are still shared as their owncookie.Evidence.session.rule, which every package already applies, is written down.Cookieis shared.The packages
cookiesrather thancookie, so they shared the Cookie header.specifications#65 changes the Processing section of the same file, not this one.