← Versions 1.0.0 In progress

1.0.0

Two backlogs: the release scope, and what the work turned up.

Backlog 1 — release scope

Planned work. An item is only here if it loses data, breaks a promise on a public surface, or stops a stranger installing and running the thing. A ticket that reaches Done carries the version it shipped in.

KeySummaryComponentStatusVersionBlocked by
SAPE-1Build identity: version embedded, version command, product version in handshakeserverDone1.0.0
SAPE-2Versioning and compatibility policydocsTo do
SAPE-3Prebuilt binaries and a published container imagereleaseIn progressa tag
SAPE-4Tag-driven release workflow for the serverreleaseIn progressa tag
SAPE-5Install path and quickstartdocsTo doSAPE-3
SAPE-6Upgrade rehearsal: one build writes, the next reads it all backserverTo doISS-4
SAPE-7Config reload, led by partial reloadserverTo do
SAPE-8Read an operation's cost envelope before trusting itserverTo do
SAPE-9Name collision: decide whether namespaces existserverTo do
SAPE-10Sign and verify an operation bundleserverTo do
SAPE-11List the external operations installed on a serverserverTo doSAPE-8
SAPE-12One worked external operation, published as a challengedocsTo doSAPE-7, SAPE-10
SAPE-13An artifact describing the shape of a request bodyprotocolTo do
SAPE-14Declare for collectionsserverDone1.0.0
SAPE-15learn.sapedb.comdocsIn progresshosting and DNS
SAPE-16sapedb.comdocsIn progressSAPE-15, SAPE-5
SAPE-17The on-disk format tag and the key labels say sapedbserverDone1.0.0
SAPE-18Reads share a database instead of queueing behind each otherserverDone1.0.0
SAPE-19Declare an operation against a running daemon — frame 13protocolDone1.0.0
SAPE-20Composed operations, with a ceiling readable at any depthserverDone1.0.0
SAPE-21Scopes travel the wire as a signed grantserverDone1.0.0
SAPE-22A count must declare how far it walksserverDone1.0.0
SAPE-23InvokeVersion, so an older declaration is reachableprotocolDone1.0.0
SAPE-24Three clients, each run against a real daemonclientsDone1.0.0
SAPE-25Desktop workbench: connections, catalogue, run, shell, compose, declaredesktopDone1.0.0
SAPE-26Apply a change: replay a log entry into a databaseserverDone1.0.0
SAPE-27Follower mode: a daemon that subscribes, applies, and refuses writesserverDone1.0.0

13 done, 4 in progress, 10 to do. Replication is complete: a sapedbd can follow another one, survive being killed mid-stream, and refuse writes with a reason. SAPE-14 has landed, so a collection can be declared against a running daemon — from the CLI, all three clients and the desktop workbench — and it no longer blocks SAPE-11 or SAPE-12.

This table said Done for four tickets that are not, and all four were caught the same way: by reading what the ticket asks for.

SAPE-15 and SAPE-16 — the learn site and the front page — have said In progress on their own pages the whole time, while this table said otherwise. Their criteria are plainly unmet: SAPE-16's first one is a person opens the page in a browser and reads it, and its own text answers "nobody has done this". Measured tonight and worse than that: dig A sapedb.com and dig A learn.sapedb.com both return nothing, from two resolvers. The domain is registered; neither name points anywhere. The pages are written, and no stranger can reach either of them.

SAPE-3 and SAPE-4 are waiting on one command nobody here may run. The whole release pipeline has now executed on a real runner, end to end: binaries for four platforms, checksums, every artefact proved to carry its version stamp rather than dev (the linux one by running it), the container image built, started and connected towelcome's productVersion matches the stamp — and then all three publishing steps skipped, because a manual run resolves publish: false. Each of those checks has also been watched fail on purpose. SAPE-4 was briefly marked Done here; four of its five criteria need a tag that has actually been pushed, including the one it calls the bar — an artefact downloaded onto a clean machine and executed there.

Backlog 2 — issues found while working

Opened by the work in Backlog 1, not planned before it. Each one is triaged once: Fix in 1.0.0 only if it loses data, breaks a public promise, or blocks installing and running; otherwise Defer, and it goes to planning for the next version. The triage column is the decision, not a guess at how bad it feels.

KeySummaryFound whileTriageStatusVersion
ISS-1The covering index is built, decoded per entry, then discardedSAPE-20DeferOpen
ISS-2Fixture copies kept identical by hand; nothing compares themSAPE-19DeferOpen
ISS-3The fixture covers 9 of 14 frame typesSAPE-13DeferOpen
ISS-4The ErrFormat refusal path has no test at allSAPE-6Fix in 1.0.0In progress
ISS-5A composed operation's rows come back flat and unlabelledSAPE-20DeferOpen
ISS-6An encryption test is flaky: it searches ciphertext for a 3-character stringSAPE-17DeferOpen
ISS-7internal/cli's open() leaks partition files, as Server.Close didSAPE-19DeferOpen
ISS-8Two write handlers in one file roll back differentlySAPE-19DeferOpen
ISS-9A read-only composed operation takes the write lockSAPE-20DeferOpen
ISS-10A composed operation must name a collection it may never touchSAPE-20DeferOpen
ISS-11A grant has no expiry and cannot be revoked short of rotating the server secretSAPE-21Fix in 1.0.0Open
ISS-12The TypeScript client cannot present a grant, so it cannot reach a scoped operationSAPE-21Fix in 1.0.0Done1.0.0
ISS-13Declaring a collection is not recorded against anybodySAPE-19DeferOpen
ISS-14The old product name survives in three production constants, assembled byte by byteSAPE-17DeferOpen
ISS-15The release plan went stale the same day it was writtenSAPE-2Done1.0.0
ISS-16The TypeScript client ignores the product version the daemon now sendsSAPE-1DeferOpen
ISS-17sapedbd has no version command; it only says so in a log lineSAPE-1DeferOpen
ISS-18A linker stamp aimed at a symbol that does not exist is accepted in silenceSAPE-1DeferOpen
ISS-19The worked example declares no projection, so it teaches the untyped pathSAPE-13DeferOpen
ISS-20A client derives shapes from a schema file on disk, not from the server's catalogueSAPE-13DeferDone1.0.0
ISS-21The most declaration-shaped refusal of all reads as "failed"SAPE-14Fix in 1.0.0In progress
ISS-22Anyone holding a connection string can read the entire change logSAPE-26Needs a decisionOpen
ISS-23No operator can cap log retention; the disk fills while everything looks healthySAPE-26DeferOpen
ISS-24The PHP client's pinned fixture predated the wire it speaks, and its refresh command 404sSAPE-24Fix in 1.0.0Done1.0.0
ISS-25The PHP client had no CI, so a skipped test and a passing test read the sameSAPE-24Fix in 1.0.0Done1.0.0
ISS-26Reading the catalogue is a write, so the operator shell cannot be pointed at a followerSAPE-27DeferOpen
ISS-27A valid signature for a database that never existed brings it into existenceSAPE-14DeferOpen
ISS-28Both clients have CI; the database at the centre of them does notSAPE-3Fix in 1.0.0Done1.0.0
ISS-29SAPE-18's gate measures how many cores the machine has, not whether reads shareISS-28Fix in 1.0.0Done1.0.0
ISS-30The workbench cannot run the reads a follower would allowSAPE-27DeferOpen

How an issue gets triaged

One question, asked once, and written down: does it lose data, break a promise on a public surface, or stop somebody installing and running the thing? Nine of thirty answer yes, and one — ISS-22 — is not mine to answer at all, because it is a security posture that freezes at the tag. The rest are real, some are embarrassing, and they wait: a backlog that grows as fast as it shrinks has no answer to is it done yet.

The rule also has to stop things that sound like defects. One report this week said the operator shell silently swallows the catalogue error at startup, which is literally true. Reading the surrounding code showed the discard is deliberate and explained — it feeds tab completion, and guessing names would be worse than silence — while ls, in the same file, reports the refusal properly. No ticket was opened. A rule that only ever adds is not a rule.

ISS-12 is the cautionary one. It sat here marked open after the work had been done, and was then used as evidence — twice in one sitting — to write a public claim that was false, the second time while correcting the first. A ticket is a record of what somebody found on a day. It is not a measurement of what is true now.

ISS-29 is the best thing on this page. It was found by ISS-28 within an hour of CI existing: a gate guarding a Done ticket had been measuring the number of cores in the machine and reporting the answer as a verdict about locks. The replacement counts how many reads are inside the database at once — an exclusive lock cannot reach two on any number of cores — and on the very runner that had been failing, it found four reads inside the database together, in three milliseconds. The code had been sharing all along. Only the gate could not see it.

What 1.0.0 freezes

A version number here is a promise that cannot be withdrawn. From the tag onwards these four surfaces are fixed: the on-disk format, the wire protocol (frames 1…13 never change role; fields may be added, never renamed or removed), the meaning of a declaration, and the public API. It does not promise performance, the ordering of reads against writes, the file layout inside a partition, or anything under internal/.

Frame 14 is now spent: SAPE-14 took it for establish. The next frame anyone adds starts at 15. The public Go surface is 39 names and follower mode added none of them — everything it needed lives under internal/.