Skip to content

Release candidate - #134

Merged
jwrosewell merged 86 commits into
mainfrom
rc
Nov 11, 2026
Merged

jwrosewell merged 86 commits into
mainfrom
rc

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Brings rc at ba07942 into main, so that the specification on main matches the packages released on 11 November 2026.

Why it goes first

The packages link the specification on main from their code comments and documentation. Until rc reaches main, those links lead to text the new code no longer follows. For example, main has no rounding section in value-types.md (#86), no License keys section in logging.md (#55 and #123), and says the engine must skip the accessible properties request under a License Key alone, the opposite of #128.

So this should merge before any language's rc merges into main.

Last release

The last release into main was #70, merged on 4 November 2026 at 06:35 UTC.

What it brings

75 pull requests merged into rc since then:

Left out

One draft into rc is still open and is not part of this release: #34.

Merging

#70 was squashed, and main was then merged back into rc. Create a merge commit this time leaves rc and main with the same history, so no merge back is needed.

justadreamer and others added 30 commits November 3, 2026 15:32
The rust repository is now 51degrees-rust (51Degrees/51degrees-rust#206).
The list of packages that implement the 51Did specification links
the new name.
Keeps the 51degrees-java link from #64 next to it.
…ies (#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.
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.
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.
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

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.
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.
)

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.
…xt (#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.
)

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.
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.
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.
…owing 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.
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.
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.
…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.
…n-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.
…sponse (#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

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.
* 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

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.
…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.
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.
…s 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.
…#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.
…ies not returned section and the configuration table, and correct the reading of the 21 September measurement (#133)
…ue (#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

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.
…sing (#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
…ameters (#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.
…#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

The specification said nothing about the error the .NET packages log when
a request carries no Element Data at all under a key a script reads, which
happens when the Element supplying that key runs after the derived
property Element. It also said that nothing is shared between requests,
which rules out the flag .NET keeps so that the error is logged once per
script. Describe the error, and allow one flag per script, set once
without a lock.

* Name both causes of missing source Element Data, and add the one-time error to the late Element paragraph

A supplier that ran first but failed before adding its Element Data also leaves no Element Data under the key, because exception-handling.md has every Flow Element run after one fails. The paragraph on an Element placed too late now also says the Element logs the error once.
…es needs no decoder (#108)

* Say an Engine whose native code converts the values needs no decoder

The page said Device Detection Engines MUST be able to use the decoder's
Element Data, and that the Element is implemented for .NET. Neither holds
for an on-premise Engine built on the native code in 51degrees-cxx.

- The native code turns 51D_GetHighEntropyValues evidence, from the query
  string or a cookie, into sec-ch-ua headers before it matches
  (setGetHighEntropyValuesHeader, src/dd/hash/hash.c lines 3540 to 3556,
  called from resultsHashFromEvidence_setSpecialHeaders at line 4313), while
  special evidence processing is on, which is the default
  (src/dd/config-dd.h line 90), all at 51degrees-cxx
  e866f6d3cea936587790f87967eff7863778b30e. The C++ Engine accepts both
  keys (src/dd/EngineDeviceDetection.cpp lines 39 and 41).
- 51degrees-dotnet at 4d7152bfcb7c9bcb17d14cb512025b65a3307313, whose cxx
  submodule is e866f6d3, has no decoder element. Its examples say the engine
  consumes the values as query or cookie parameters
  (examples/device-detection/ExampleBase/ExampleUtils.cs lines 620 to 624).
- 51degrees-java at f69da52e52104687206d1ca1c3595d2935790f34, with the same
  cxx submodule, has no decoder element either.

The page now says an on-premise Engine whose native code converts the
values itself need not read the Element's data, and that a Pipeline built
around one does not need the Element. The precedence rule under Process is
unchanged.

Follows 51Degrees/51degrees-rust#350.

* Say which one value the native code converts
* Say how each form of IP address is looked up

An IPv4-mapped IPv6 address is its IPv4 address under RFC 4291 and RFC 4038, an IPv4-compatible address is deprecated, and an IPv4-embedded address under RFC 6052 stays an IPv6 address. Recording this here gives every language one rule and code comments one URL to point at.

* Pad the runtime table and clear the .NET row's wording
…om the reserved names (#138)

* Say that the Cloud Request Engine sends every Evidence value apart from the reserved names

Processing said the Engine filters the Evidence down to the keys the server needs, and then that it adds all the values from the Flow Data Evidence. James Rosewell decided on 10 November that the Engine sends everything but the reserved names, because what the server uses changes and knowing about other Evidence is important to continued optimization. Accepted Evidence now says it does not limit what is sent.

* Leave the web request view out of the cloud request

web-integration.md has every web integration add a read-only view of the request under server.http-request. .NET and Java leave it out of the cloud request, as it is an object and not a value, so Processing now names it with the reserved names.

* Say letter case is ignored when the web request view is left out of the cloud request

* Restore the line endings that the previous commit changed in six files
* Say what happens when a data file refresh fails

A refresh whose new data cannot be used fails and leaves the Engine on the data it had, the failure is logged and reported as a failure, and polling and the file watcher carry on, so a later good file is still applied.

* Report every data update check, a skipped or not-needed one as not needed

James Rosewell decided on 10 November that the specification follows .NET's DataUpdateService.cs, which reports each polled check, each programmatic check of a configured data file and each file watcher event to its CheckForUpdateComplete event with a success, not needed or failure status. A new section, Reporting each check, says so, and the polling, newFileAvailable and programmatic update paths point to it.

* Follow .NET exactly for data update reporting and errors, and exempt one-request packages

James Rosewell decided on 10 November that data-updates.md follows the .NET data update service exactly. A programmatic check for a data file with no configuration and an update from memory report nothing, a watcher event that waited for another event for the same file is reported as in progress, and a programmatic failure is passed to the caller without being logged. The polling branch of Programmatic update reports not needed. The Errors table takes .NET's messages, levels and statuses. A package whose processes last for one request, such as PHP's, has no data update service.

* Add the update callback error, end the memory refresh message with a full stop, and widen In progress

* Give the callback and integrity check rows exactly as .NET writes them

* Say how a callback's data update error is logged and that later callbacks are skipped
…ry Property by position (#137)

* Scope the read-by-name rule for an Engine created with no names to the C++ Results classes

In C, each property's index is its own place when no names are given (src/common/properties.c lines 479 to 491 in 51degrees-cxx at cfad8978), so an implementation that calls C may read such an Engine by position. The C++ ResultsHash and ResultsIpi classes refuse every position without names (ResultsBase.cpp lines 481 to 484), so the MUST read by name stays for them. The native code still gives each position. Also point the Cloud Request Engine's JSON Builder link at #process, the heading json-builder.md has.

* Say which data set a read by name asks for the position

C resolves a position against the data set the results were populated from (51degrees-cxx cfad8978 src/dd/hash/hash.c lines 5896 to 5901, src/ipi/ipi.c line 3342), so a position taken from the current data set after a refresh can name a different Property.

* Write the property index rule into Finding Properties

James Rosewell decided on 10 November that a property's index is its place in the list of names the engine was built with, fixed at build. An engine configured with no names takes every property name in the data set at build as that list, every read uses the index, and a read by name uses a table built once from the build-time names, never from the data set. This replaces the earlier text that let C read an engine with no names by its data set position. The C quote, the C++ scoping and the json-builder anchor fix stay.

* Say the native code keeps the first data file's names for an Engine created with no names

* Say an Engine with no names has every Property of its first data file, and that getProperties can list one with no position

* Say the no-names Engine's names are sorted by name, and that its metadata reports a Property with no position as not available

* Say a Property only a later data file has is excluded from a no-names Engine's configuration

* Link the C code at the commit that merged it into rc

* Link the C code at the commit that merged it into rc
…139)

* Give the exact error text for a JSON Builder with no sequence number

Every implementation gives the same message when no Sequence Element has produced a sequence number, with JSON Bundler in place of JSON Builder in PHP. Where the error is wrapped, the error the caller reads carries the message.

* Say that the JSON Builder error message is the whole text

Nothing is added to the message, such as a documentation link. A prefix that a language's error type writes in front of every error of that type is not part of the message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants