Release Notes
PhoenixmlDb version history and changelog
#Unreleased: database server
#Breaking: the REST server requires authentication
Since phoenixml main 0d46e91 (issue #45), the REST server is secure by default:
-
Every endpoint requires an API key (
X-Api-Keyheader) or a JWT (Authorization: Bearer). Anonymous requests get401. Only/health,/health/liveand/health/readystay open, plus the Swagger UI in Development. -
A production host running the shipped
appsettings.jsonrefuses to start until an operator configures a key. -
Settings moved to the
Authsection. A configuration that still has anAuthenticationsection fails at startup, with a message saying what to rename. -
Outside Development, API keys must be at least 32 characters, and development keys are refused.
See Server Mode: Authentication for every setting and startup check.
The gRPC server authenticates with API keys too, and refuses to start on a network address without one; see Server Mode: gRPC server.
#API keys are stored as hashes and can be rotated
Since phoenixml main 58e4b5b (issue #50), both servers take a list of key entries, each with
an Id, an optional Expires, and either the key's SHA-256 or the key supplied as a secret value:
Auth:ApiKey:Clients on the REST server, PhoenixmlDb:Auth:ApiKeys on the gRPC server. Several
entries can share a Name, which is how a key is rotated.
-
Deprecated: the REST server's
Auth:ApiKey:Keys:<key>shape still works for one release, with a startup warning. gRPC entries without anIduse theirName, with a warning. -
Breaking for operators:
"Key": ""(for example a missing optional secret) now stops the server from starting; it used to be treated as unset. DuplicateIds and two entries holding the same key also stop startup.
#Breaking: queries and stylesheets can't read files or URLs by default
Since phoenixml main a2b9963 (issue #59), XQuery and XSLT supplied by callers can read only the
stored documents, in the embedded engine and in both servers. Local files, HTTP requests, module
and stylesheet imports by location, xsl:evaluate, and external DTDs and entities are denied
until the operator allows specific directories or origins
(PhoenixmlDb:ResourceAccess:AllowedFileRoots / AllowedHttpOrigins on the servers,
DocumentDatabase.ResourceAccessPolicy embedded). doc() and collection() of stored documents
work as before. An embedded application that relied on the old behaviour for trusted code can set
ResourceAccessPolicy.Unrestricted. See Resource Access.
#Breaking for monitoring: health endpoints are status-only
Since phoenixml main 170adf3 (issue #51), /health, /health/live and /health/ready return
only Healthy / Degraded / Unhealthy as plain text: 200, or 503 when unhealthy. The
detailed JSON report moved to /health/details, which requires an admin credential. Anything
that parsed JSON from /health must call /health/details instead. /health/ready now runs the
database and engine checks; it used to always return 200. See
Server Mode: Health Endpoints.
#Upgrade: full-text indexes are rebuilt once
Since phoenixml main 8d23b02, the database uses PhoenixmlDb.XQuery and PhoenixmlDb.Xslt
2.4.1 (Core stays at 2.0.0), and a full-text index records which text analysis built it.
Existing indexes carry no such record, so the first time a database is opened with indexing
enabled, every full-text index is marked stale and rebuilt once. The gRPC server does this in
the background at startup. Embedded applications must call RebuildIndexesAsync for each
container in ContainersWithStaleIndexes(); until then SearchFullText throws on that container
and other index-backed reads scan. Full-text query behaviour itself is unchanged by this bump;
stemming and position-based phrases are not in 2.4.1. See
Full-Text Search: After an engine upgrade.
#Engines: PhoenixmlDb.Xslt and PhoenixmlDb.XQuery
Since 2.0.0 the two engines release together as one train: the Xslt and XQuery versions match, and each release pins the other at the same version. The full per-version notes live in each repo: Xslt · XQuery. The summaries below lead with each release's measured W3C figures, as recorded when it shipped.
On comparing figures across releases. The test harness was corrected more than once. On 2026-09-04, expected-error tests had been scored as passes on any error, so earlier XSLT figures are overstated. Later corrections changed the case count (denominator). A figure is exact for its own release; subtracting across a harness change compares different measurements.
#2.4.1 (2026-09-28): patch
-
Fixed a 2.4.0 regression that broke XSpec compilation. A string subtype such as
xs:NCNamehad no effective boolean value, and 2.4.0 had madeprefix-from-QNamereturn one. Fixed in both engines, along with string-subtype map keys,fn:translateandfn:collation-key. -
New release gate: every release is now checked against real-world stylesheets (the XSpec compiler, DocBook xslTNG, reported repros) on the previous version and the candidate before it ships.
#2.4.0 (2026-09-28)
W3C XSLT 3.0: 10,397 / 10,839 (95.92%) · W3C QT3: 29,895 / 31,379 (95.27%)
Behaviour changes, read before upgrading:
-
fn:namespace-urireturnsxs:anyURI,fn:prefix-from-QNamereturnsxs:NCName, andfn:default-languagereturnsxs:language, as the spec requires. They previously returned plain strings. -
fn:distinct-valuestreats anxs:anyURIand an equalxs:stringas one value. -
The
xqueryCLI rejects an unknown output method (exit code 1, orSEPM0016in the prolog) instead of silently producing adaptive output. It gainshtmlandxhtml.
Fixed:
-
Streaming:
xsl:messagecontent, templates below unmatched elements, subtree ancestors,has-children(),xsl:strip-space/xml:space, early-closing parent tags, and unrequested child processing. Closes the three streaming sets that had fallen below their 1.6.10 scores. -
fn:transformhonourssource-location, and raw delivery from XQuery returns the nodes a template constructs instead of nothing. -
CLI output is UTF-8 on every platform. On Windows it followed the console code page, which corrupted non-ASCII characters in redirected output.
There is no Xslt 2.3.0. XQuery 2.3.0 (below) was published and then superseded, and both engines moved to 2.4.0 together.
#2.3.0 (2026-09-28): XQuery only, superseded
A lockstep version bump; the library is byte-identical to 2.2.0. Moving from 2.2.0 straight to 2.4.0 is the intended upgrade path.
#2.2.0 (2026-09-24/25)
W3C XSLT 3.0: 10,384 / 10,839 (95.80%) · W3C QT3: 29,803 / 31,379 (94.98%)
-
xs:IDREFS,xs:NMTOKENSandxs:ENTITIESare valid cast and castable targets (+63 QT3). -
xsl:exposeselects components correctly. -
A match pattern with any predicate was O(n²) in sibling count: 12.6× faster at 4,000 siblings.
-
Streamed
group-adjacentkey checks,xsl:sort/xsl:keytemporary output state,regex-group()in patterns, text nodes returned byxsl:function, and static declarations coming into scope in declaration order.
#2.1.0 (2026-09-17)
W3C XSLT 3.0: 10,347 / 10,839 (95.46%) · W3C QT3: 29,822 / 31,379 (95.0%), as recorded in the XQuery 2.1.0 notes.
Breaking: a typed variable whose body produces the wrong number of items raises XTTE0570.
xsl:strip-space / xsl:preserve-space in imported modules are applied, with conflicts resolved
by import precedence. xsl:map-entry keys are atomized.
#2.0.0 (2026-09-15)
W3C QT3: 29,813
Major because the train is: PhoenixmlDb.Core, PhoenixmlDb.XQuery and PhoenixmlDb.Xslt
moved to 2.0.0 together.
-
Breaking: built-in functions apply argument cardinality, and their signatures match F&O 3.1, so some existing queries stop compiling. The extension functions moved.
-
In-scope namespaces survive copies and serialization. Serialization parameters are read properly. The XSLT-side
fn:serializeoverride is retired.
#1.8.0 (2026-09-13)
W3C XSLT 3.0: 10,292 / 10,630 (96.82%) · W3C QT3: 29,534 / 31,414 (94.02%). This is a different denominator from 2.x.
Silent wrong answers fixed: xsl:function cache="yes" returning other calls' results;
accumulators reading a later-declared accumulator one node late; as="item()*" functions losing
element nodes; xsl:merge merging only one of two sources; and xsl:try running its body in the
caller's scope.
#1.7.0 (2026-09-10)
W3C XSLT 3.0: 10,082 / 10,630 (94.8%)
-
fn:sumreturned 0 forxs:integervalues cast from text. -
Aggregates over storage-backed elements atomized to
"". -
map:put/map:remove/map:replacecopied the whole map on every update (O(n²)). -
A caller's timeout could not stop recursion, callbacks or a slow
every. -
Several
contains textdefects.
#1.2 – 1.6 (April – September 2026)
A long run of frequent, often daily, releases: over a hundred versions across both engines. That
cadence has since been replaced by releases that each carry a complete batch. Highlights:
serialization conformance (character maps, HTML/XHTML output methods), streaming, QT3 production
sweeps, and input hardening (parser recursion bounds, XQST0090 on invalid character references,
concurrent namespace interning).
Figures in this period predate the 2026-09-04 harness correction. Each version's notes are in
the Xslt and XQuery repos.
#Version 1.1.0 (March 2026)
Major update focused on standards compliance, streaming, and API completeness.
#XSLT Engine
-
Streaming execution: XmlReader-based forward-only processing for
xsl:source-document streamable="yes"andxsl:mode streamable="yes" -
Stream API:
TransformAsync(TextReader),TransformAsync(Stream),TransformAsync(TextWriter),TransformAsync(Stream, Stream),ResultDocumentHandler -
Serialization:
indent="yes"(XML, HTML, XHTML), DOCTYPE generation,suppress-indentation,byte-order-mark,escape-uri-attributes -
xsl:record: Proper XDM map construction
-
xsl:expose: Full package visibility control (conformance tests enabled)
-
Error handling: Proper XTSE0020 for invalid
on-no-match/on-multiple-matchvalues -
System properties:
supports-streaming=yes,supports-namespace-axis=yes,xpath-version=4.0
#XQuery Engine
-
Direct element constructors:
<element>text {expr}</element>with ANTLR lexer modes -
XQuery Update Facility: Full execution (insert, delete, replace, rename, transform copy-modify-return)
-
Annotations:
%public,%private,%updatingon function/variable declarations -
String constructors:
[Hello{$name}!]backtick interpolation -
Module imports: Parsed with XQST0059 error when resolver not configured
-
UCA collations: Unicode Collation Algorithm with lang/strength/fallback parameters
-
External variables:
SetExternalVariable()API with XPDY0002 for unbound -
JSON serialization: Maps/arrays serialize as JSON,
declare option output:method "json"support -
Node constructors: All constructor types (element, attribute, text, comment, PI, document) fully operational
#CLI Tools
-
xslt CLI:
--streamflag for large file processing, version 1.1.0 -
xquery CLI:
--output jsonflag, auto-detect serialization options, version 1.1.0 -
CLI tools moved into engine repos (same CI, same release)
#Quality
-
843 XQuery tests (including 30 integration tests through XQueryFacade)
-
300 XSLT tests (including 36 integration tests through XsltTransformer)
-
Zero TODOs in source
-
Zero silent exception swallowing
-
All README claims verified by tests
#Version 1.0.0
Release Date: 2025
The initial release of PhoenixmlDb, a modern embedded XML/JSON document database for .NET.
#Features
#Core Database
-
Embedded database with LMDB storage
-
ACID transactions with MVCC
-
Multiple containers per database
-
XML and JSON document storage
-
Document metadata support
#Query Engine
-
Full XQuery 3.1 implementation
-
XQuery 4.0 features (partial)
-
XPath 3.1 support
-
XSLT 3.0/4.0 transformations
-
Query optimization
-
Prepared queries
#Indexing
-
Path indexes for element/attribute lookup
-
Value indexes for range queries
-
Full-text indexes with stemming
-
Structural indexes for navigation
-
Metadata indexes
#Server Mode
-
gRPC-based server
-
TLS support
-
Authentication (basic, API keys)
-
Role-based access control
-
Health monitoring
#Cluster Mode
-
Raft consensus for leader election
-
Automatic failover
-
Sharding with consistent hashing
-
Replication for fault tolerance
-
Distributed transactions (2PC)
#System Requirements
-
.NET 10.0 or later
-
Windows 10+, Linux (Ubuntu 20.04+, RHEL 8+), macOS 12+
#Known Limitations
-
XQuery full-text extension not yet implemented
-
Schema validation is basic (planned for 1.1)
-
XSLT streaming limited to certain patterns
-
Maximum database size limited by LMDB (depends on platform)
#Upgrade Notes
This is the initial release. No upgrade path needed.
#Roadmap
#Version 1.2 (Planned)
-
Full XML Schema validation
-
XQuery Full-Text extension
-
Improved query optimizer
-
GraphQL API
-
More XSLT 4.0 features
#Version 1.3 (Planned)
-
Change data capture (CDC)
-
Event sourcing support
-
Improved cluster rebalancing
-
Admin UI
#Future
-
Geographic replication
-
Column-oriented storage for analytics
-
Machine learning integration
-
Cloud-native deployment options
#Deprecation Policy
-
Major versions supported for 3 years
-
Minor versions supported for 1 year
-
Security patches for supported versions
-
Migration guides provided for breaking changes
#Contributing
We welcome contributions! See our Contributing Guide for details.
#License
PhoenixmlDb is licensed under the Apache 2.0 License.
#Acknowledgments
PhoenixmlDb builds on these excellent projects:
-
LMDB - Lightning Memory-Mapped Database
-
LightningDB - .NET bindings for LMDB
-
ANTLR4 - Parser generator
Special thanks to the W3C for the XQuery, XPath, XSLT, and XDM specifications.