Repository navigation
Release candidate - #134
Merged
Merged
Conversation
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.
…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.
…e sharing reads from the web 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.
jwrosewell
marked this pull request as ready for review
November 11, 2026 15:07
This was referenced Nov 11, 2026
Closed
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.
Brings
rcat ba07942 intomain, so that the specification onmainmatches the packages released on 11 November 2026.Why it goes first
The packages link the specification on
mainfrom their code comments and documentation. Untilrcreachesmain, those links lead to text the new code no longer follows. For example,mainhas 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
rcmerges intomain.Last release
The last release into
mainwas #70, merged on 4 November 2026 at 06:35 UTC.What it brings
75 pull requests merged into
rcsince then:Left out
One draft into
rcis still open and is not part of this release: #34.Merging
#70 was squashed, and
mainwas then merged back intorc. Create a merge commit this time leavesrcandmainwith the same history, so no merge back is needed.