Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/rulesets/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
{
"context": "python (3.13)"
},
{
"context": "python (3.14)"
},
{
"context": "typescript (18)"
},
Expand All @@ -59,6 +62,12 @@
{
"context": "typescript (22)"
},
{
"context": "typescript (24)"
},
{
"context": "typescript (26)"
},
{
"context": "contract"
},
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
# The floor is 3.11 because the code uses `X | None` at runtime in annotations resolved by
# get_type_hints. The ceiling is whatever is current: a canonical encoding that drifts with a
# Python release is exactly the failure the contract exists to prevent, so both ends get run.
python: ["3.11", "3.12", "3.13"]
python: ["3.11", "3.12", "3.13", "3.14"]

services:
postgres:
Expand Down Expand Up @@ -141,14 +141,14 @@ jobs:
strategy:
fail-fast: false
matrix:
node: ["18", "20", "22"]
node: ["18", "20", "22", "24", "26"]

# The same two engines the Python job gets, and for the same reason: this library reached Tier 2
# on 6 September 2026, so "it renders DDL and takes part in a migration" is now a claim about
# real servers. Running the vectors without them would leave the adapters - two of the eight
# integrations requirement 17.5 is about - checked by nothing.
#
# All three Node versions, deliberately. The ClickHouse adapter exists because the official
# All five Node versions, deliberately. The ClickHouse adapter exists because the official
# client requires Node 20, and a matrix that only exercised the engines on one version would be
# unable to notice the day that stops being the reason.
services:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
if ! git merge-base --is-ancestor "$GITHUB_SHA" refs/remotes/origin/main; then
echo "::error::commit $GITHUB_SHA is not an ancestor of main, so it never passed the"
echo "::error::eleven required checks. The ruleset protects main; it does not stop a tag"
echo "::error::required checks. The ruleset protects main; it does not stop a tag"
echo "::error::from being pointed at any commit in the repository, including one on a"
echo "::error::branch that was never reviewed. Merge first, then tag the merge."
exit 1
Expand Down
16 changes: 8 additions & 8 deletions docs/github-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ they differ, the difference is called out rather than left to be noticed.
- **Releasing is a tag and holds no credential** ✅ — both registries authenticate the workflow over
OIDC, so there is no publishing token in this repository, in its Actions secrets or on a laptop.
See §4.2, which was a list of intentions until 12 September.
- **Two languages, so two analyses and eleven required checks**, not four (§1). The count is derived from
- **Two languages, so two analyses and fourteen required checks**, not four (§1). The count is derived from
`main.json` by a test, because it was wrong here by one until 12 September and nothing counted it.
- **The default branch is `main`, not `master`.** The rulesets differ in that one string, and a
ruleset targeting the wrong ref is silently inert.
Expand All @@ -49,13 +49,13 @@ A ruleset named `main` is active on `refs/heads/main` with **no bypass actors**,
- `required_linear_history` — no merge commits, so `git log main` stays readable
- `pull_request` — direct pushes are blocked, with `required_review_thread_resolution: true` so an
unresolved comment cannot be merged past, and `allowed_merge_methods: [squash, rebase]`
- `required_status_checks` with `strict: true` and **eleven contexts**
- `required_status_checks` with `strict: true` and **fourteen contexts**

The eleven are the whole matrix, not a representative sample:
The fourteen are the whole matrix, not a representative sample:

```
python (3.11) python (3.12) python (3.13)
typescript (18) typescript (20) typescript (22)
python (3.11) python (3.12) python (3.13) python (3.14)
typescript (18) typescript (20) typescript (22) typescript (24) typescript (26)
contract
analyze (python) analyze (javascript-typescript) analyze (actions)
CodeQL
Expand All @@ -67,13 +67,13 @@ scanning integration and is the one that fails when the analysis has produced a
Requiring the three without it would require that the scan ran, not that it found nothing. There are
zero open alerts today, so requiring it costs nothing to adopt — which is the only moment it is cheap.

Requiring all six language-version cells rather than one is specific to this repository and worth the
Requiring all nine language-version cells rather than one is specific to this repository and worth the
minute it costs. The product's guarantee is that four implementations encode a model to identical
bytes; a canonical encoding that drifts with a Python release or a Node release is precisely the
failure the byte contract exists to prevent, and a matrix cell that runs but blocks nothing is how
that drift would arrive looking green.

`contract` is the cheapest and most valuable of the eleven: it rebuilds the wheel and checks the PEP 561
`contract` is the cheapest and most valuable of the fourteen: it rebuilds the wheel and checks the PEP 561
marker is inside it, re-derives every committed hashing digest with `openssl`, and refuses a change to
the one hand-written conformance vector without a deliberate edit to the workflow.

Expand Down Expand Up @@ -462,7 +462,7 @@ distribution name is the one an attacker needs no access at all to exploit.
✅ pull_request_template.md and issue templates
✅ rulesets kept as JSON in .github/rulesets/
✅ branch ruleset on main: PR required, no force push, no deletion, linear history, no bypass actors
✅ branch ruleset: all eleven status checks required, strict
✅ branch ruleset: all fourteen status checks required, strict
✅ tag ruleset on refs/tags/v*
✅ secret scanning + push protection
✅ Dependabot alerts + security updates
Expand Down
4 changes: 2 additions & 2 deletions docs/implementations.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ implementation that does not pass the Tier 0 vectors is not an SDE library, whoe

| Library | Language | Tier | Hashing (§2a) | IR contract | Map contract | Engines |
|---|---|---|---|---|---|---|
| `smart-data-engine-sdk` | Python 3.11–3.13 | 2 | yes | 1 | 1–5 | `clickhouse`, `orderbook`, `postgres` |
| `@smart-data-engines/sde` | TypeScript / Node 18–22 | 2 | yes | 1 | 1–5 | `clickhouse`, `postgres` |
| `smart-data-engine-sdk` | Python 3.11–3.14 | 2 | yes | 1 | 1–5 | `clickhouse`, `orderbook`, `postgres` |
| `@smart-data-engines/sde` | TypeScript / Node 18–26 | 2 | yes | 1 | 1–5 | `clickhouse`, `postgres` |

The engines column carries **dialect identifiers**, not product names: they are what a hand-written
layout and `schema_statements(dialect=...)` take, so they are the spelling a client actually types.
Expand Down
12 changes: 6 additions & 6 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ workflow, and fails if the three disagree.

| | |
|---|---|
| Supported | **3.11, 3.12, 3.13** |
| Tested in CI | 3.11, 3.12, 3.13 — every one, on every pull request |
| Declared in `python/pyproject.toml` | `>=3.11,<3.14` |
| Supported | **3.11, 3.12, 3.13, 3.14** |
| Tested in CI | 3.11, 3.12, 3.13, 3.14 — every one, on every pull request |
| Declared in `python/pyproject.toml` | `>=3.11,<3.15` |

The floor is 3.11 because the code uses `X | None` in annotations that are resolved at runtime by
`get_type_hints`.
Expand All @@ -33,9 +33,9 @@ one action instead of two.

| | |
|---|---|
| Supported | **18, 20, 22** |
| Tested in CI | 18, 20, 22 — every one, on every pull request |
| Declared in `typescript/package.json` | `>=18 <23` |
| Supported | **18, 20, 22, 24, 26** |
| Tested in CI | 18, 20, 22, 24, 26 — every one, on every pull request |
| Declared in `typescript/package.json` | `>=18 <27` |

Same reasoning, same closed ceiling. The TypeScript implementation has to agree with the Python one
byte for byte on the shared conformance vectors, so an untested runtime is an untested encoder.
Expand Down
2 changes: 1 addition & 1 deletion docs/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ upload:
|---|---|
| a bare `v0.1.0` tag | A tag that triggers nothing is a release that **looks done**: the tag is in the repository, protected, and nothing was published. The workflow triggers on `v*` purely so this can be said out loud, with both correct forms named. |
| the tag disagrees with the manifest | Publishing the manifest's version under the tag's name. Neither half is correctable: the registry will not reuse a version number and the ruleset will not move the tag. |
| the tagged commit is not on `main` | The ruleset protects `main` with eleven required checks; it does **not** stop a tag being pointed at any commit in the repository, including one on a branch nobody reviewed. Ancestry is what makes "the published artefact passed CI" a fact rather than an assumption. |
| the tagged commit is not on `main` | The ruleset protects `main` with the required checks; it does **not** stop a tag being pointed at any commit in the repository, including one on a branch nobody reviewed. Ancestry is what makes "the published artefact passed CI" a fact rather than an assumption. |
| the artefact is missing a licence, `py.typed`, or `dist/` | All three have actually been missing, on 8 September, and none of it was visible from a green suite — the suite runs the source tree and a user runs the artefact. The worst would have put an importable-looking package with no code in it under our own scope. |
| the artefact records a version other than the tag's | The gate agreeing with the manifest does not prove the *build* used it, and what a user installs is the number inside the file. |

Expand Down
2 changes: 1 addition & 1 deletion docs/test-toolchain.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TypeScript test tools

The SDK supports Node 18, 20 and 22. The test toolchain uses Vitest 3.2.7 and an explicit
The SDK supports Node 18, 20, 22, 24 and 26. The test toolchain uses Vitest 3.2.7 and an explicit
Vite 6.4.3 dependency range so that a new installation does not silently choose Vite 7,
which has a different Node requirement. Both selected packages declare Node 18 support.
This changes development tools only; neither package is an SDK runtime dependency.
Expand Down
2 changes: 1 addition & 1 deletion docs/weather-starter.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ to try the demo. [Publishing](publishing.md) describes the separate release proc

## Install artifacts and obtain trusted metadata

Use Python 3.11-3.13, Node 18-22 and a local POSIX filesystem. An operator supplies the reviewed
Use Python 3.11-3.14, Node 18-26 and a local POSIX filesystem. An operator supplies the reviewed
wheel and npm tarball. In fresh application directories:

```sh
Expand Down
3 changes: 2 additions & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ name = "smart-data-engine-sdk"
dynamic = ["version"]
description = "Smart Data Engine client library: declare a data model, we place it and move it"
readme = "README.md"
requires-python = ">=3.11,<3.14"
requires-python = ">=3.11,<3.15"
license = "Apache-2.0"
# Apache-2.0 section 4 asks that the licence travel with the work, and section 4(d) says the same
# about a NOTICE file where one exists. Both were missing from the wheel and the sdist until this
Expand All @@ -47,6 +47,7 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Database",
# The wheel carries `py.typed`, so this row is a fact the artefact can be checked against.
"Typing :: Typed",
Expand Down
4 changes: 2 additions & 2 deletions typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ check reads a table and a constructor cannot await. You therefore cannot hold a
has not run.

**The ClickHouse adapter has no driver dependency.** There is an official Node client and it requires
Node 20 or newer; this package supports Node 18 to 22 and its CI runs all three. Dropping Node 18
Node 20 or newer; this package supports Node 18 to 26 and its CI runs all five majors. Dropping Node 18
would narrow a published claim to gain a dependency, and pinning a superseded version of the client
is the conflict the zero-dependency rule exists to avoid - so neither. ClickHouse's HTTP interface
needs no client, and this adapter therefore owns both of its timeouts instead of inheriting a
Expand Down Expand Up @@ -146,7 +146,7 @@ It includes local setup, telemetry, operator handoffs and an ownership-checked r

## Test-tool dependencies

The Node 18/20/22 matrix uses the tool versions and supported invocation described in
The Node 18/20/22/24/26 matrix uses the tool versions and supported invocation described in
[the test-toolchain record](../docs/test-toolchain.md). That record distinguishes the SDK runtime
from development dependencies and documents the remaining development-server advisory.

Expand Down
2 changes: 1 addition & 1 deletion typescript/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"bin"
],
"engines": {
"node": ">=18 <23"
"node": ">=18 <27"
},
"scripts": {
"prepack": "npm run build",
Expand Down
Loading