Files
alkstore/tasks/release-publish-prep.md
T

242 lines
12 KiB
Markdown

---
id: release-publish-prep
name: Publish prep — package verification, exclusion check, publish records
status: completed
depends_on: [release-readme, release-flake-investigation]
scope: moderate
risk: medium
impact: project
level: implementation
tags: [wave-8, publish]
---
## Description
The plan's wave-8 "publish prep": everything short of the manual
`cargo publish` itself (CI and publishing are manual per the plan's
decided points — self-hosted Gitea, supply-chain posture; the actual
publish is the user's action, post-gate).
1. **Package metadata audit**: the four published crates currently
carry only version/edition/license/repository — `description` is
missing on all four (crates.io requires it). Land honest
descriptions per crate; decide the remaining optional fields
(`keywords`, `categories`, `homepage`/`docs` — the family's
published crates are the precedent to check) and record the
decisions.
2. **`cargo package` verification per published crate** (`alkstore`,
`alkstore-sqlite`, `alkstore-postgres`, `alkstore-mem`): each
packages clean (no warnings that block, `.crate` contents
inspected), builds + tests from the packaged source
(`cargo package --no-verify` off — let it verify, or verify
manually per crate and record which).
3. **The publish-exclusion verification** (parked from wave 7 —
`tasks/review-wave-7.md` item 4(iii)): the mechanism
(`exclude = ["fuzz"]` on the root workspace) landed; this is the
verification that **no published package leaks the sidecar** —
inspect each `.crate`'s file list: no `fuzz/` paths, no
`alkstore-fuzz-shared` references, no grown corpora/artifacts.
Also verify `alkstore-contract-suite` (`publish = false`) and the
fuzz sidecar are absent from any package.
4. **Path-dep + version records**: the engines' `alkstore = { version
= "0.1", path = … }` shape is publish-legal (version bound present)
— verify each path dep carries its version bound; record the
publish order (core first, then engines — ADR-017 §4.1's pairing)
and the version decision (0.1.0 as contract v1's initial release,
per ADR-017's semver-is-the-contract discipline) in the task Notes
as the publish checklist of record.
5. **Substrate packaging check** (ADR-013/018): `alkstore-sqlite`'s
package includes the in-tree substrate — verify `PROVENANCE.md` and
the dual-license notice ride in the `.crate`, and the package is
honest about carrying them.
6. **The publish checklist of record**: a Notes section listing the
exact manual commands in order (per crate: package → publish),
including the dry-run evidence, so the user's publish session is
mechanical.
## Acceptance Criteria
- [x] `description` landed on all four published crates; optional
metadata decisions recorded
- [x] `cargo package` clean per published crate (verification posture
recorded); `.crate` contents inspected
- [x] Publish-exclusion verification recorded: no fuzz/sidecar/
contract-suite paths in any package's file list
- [x] Path-dep version bounds verified; publish order + version
decision recorded
- [x] Substrate PROVENANCE + license notice confirmed in the
`alkstore-sqlite` package
- [x] The manual publish checklist of record written (commands in
order, evidence attached)
- [x] Workspace gates + the fuzz corpus-replay gate green at session
end
## References
- docs/plans/implementation.md §Wave 8, §Decided points (CI/publishing
manual)
- tasks/review-wave-7.md (the parked exclusion verification, item 4)
- docs/architecture/decisions/017-contract-versioning.md §4.1 (the
version pin + pairing)
- docs/architecture/decisions/013-fold-substrate-into-sqlite.md +
docs/architecture/decisions/018-provenance-register-and-cherry-picks.md
(the in-tree substrate's packaging posture)
- docs/architecture/decisions/022-contract-suite-layout.md (the suite
is not published)
## Notes
### Decisions of record
1. **Release version — 0.1.0, by user decision at this task
(2026-10-11).** This contradicted ADR-017 §1's "the initial release
is 1.0.0" pin, so a **pre-release class-1 amendment** was recorded
inline in ADR-017 §1 (the window this release closes): contract
v1's content ships whole in 0.1.0; the §4.1 manifest pins take the
ADR's own pre-1.0 `0.y` form (`alkstore = { version = "0.1", path
= … }`); breaking changes bump `0.y`, additions `0.y.z`; the
full coupling binds at the future 1.0. Motive recorded: the
family's 0.x-initial precedent (alkcall 0.8.1, alktunnels 0.2.1,
alksocks 0.1.0, alkblobs 0.1.0). This task's description itself
assumed "0.1.0" — the CHANGELOG (release-readme) had seeded it, but
the ADR pin was never dispositioned; the discrepancy was raised
with the user rather than landing silently in either direction.
2. **Optional metadata — `homepage` / `documentation` omitted.** The
family precedent (alkcall/alktunnels/alksocks/alktty/alkblobs)
carries neither field on any published crate; docs.rs links are
automatic on crates.io and `repository` is the de-facto homepage.
`keywords` + `categories` landed per crate (≤5 keywords,
lowercase; valid crates.io category slugs). Descriptions follow
the family's colon-form one-liners.
3. **License texts ride the packages — per-crate `LICENSE-MIT` /
`LICENSE-APACHE` copies.** The texts live at the workspace root,
and cargo (1.99) does **not** package workspace-root license files
into member `.crate`s: workspace-inherited `license-files` was
tried first and proved a packaging no-op (verified in a sandbox —
the field is accepted and inherited, but cargo's rewrite drops it
and the tarball carries no texts), so the field was reverted and
the canonical texts copied into the four published crate dirs,
where cargo's auto-detect (`LICENSE*` in the package dir) packages
them. The sqlite substrate's separate in-src bundled notice
(`src/substrate/LICENSE`) is unaffected — ADR-018's carrier.
4. **Verification posture.** `cargo package` verification (registry
resolution + verify build) is core-first by construction:
for the engines, the packaged manifest drops the path dep, so
packaging/verification must resolve `alkstore = "0.1"` from the
index — which fails pre-core-publish with
`no matching package named 'alkstore' found … searched: crates.io
index` (captured twice: `cargo package -p alkstore-postgres` and
`cargo publish --dry-run -p alkstore-mem`). Posture: **core got the
full cargo-native path** (`cargo package` clean, verification build
green, `cargo publish --dry-run` green to the "aborting upload due
to dry run" line); **engines got reconstructed-tree verification**:
per engine, the exact `cargo package --list` file set + a
hand-normalized publish-shaped manifest (the only semantic deltas
from the workspace manifest: the workspace-inheritance
concretization and the core dep's registry edge restored as its
publish-legal `version = "0.1", path = "../alkstore"` form — the
substitution; the suite stays a path-only dev-dep in the published
shape, which consumers never fetch) → `cargo build` + `cargo test`
green in each. The engines' registry-side verification happens
live, in order, at the publish session (checklist below).
### Field audit (the evidence)
- `cargo package --list` per crate saved at the time of the run; the
core `.crate` (the real cargo artifact,
`target/package/alkstore-0.1.0.crate`, 30 files) inspected: license
texts at the tarball root, README, the normalized `Cargo.toml`
(concrete fields, path dep dropped), no stray paths.
- **Exclusion verification (review-wave-7 item 4(iii)) — clean.** Each
package's file list diffed against its directory contents (identical
mod sort order): **no `fuzz/` paths, no `alkstore-fuzz-shared`
references, no grown corpora/artifacts in any package**; the suite
(`publish = false`) appears in no `[dependencies]` — engines carry
it only as a path-only dev-dep, and it is not a package itself. The
workspace `exclude = ["fuzz"]` holds (fuzz is a separate, excluded
workspace). The engines' `src/fuzz_surface_tests.rs` files DO ride
their packages — expected: they are the documented doc-hidden
re-export probe tests *inside the crate* (release-crate-docs), not
sidecar leakage.
- **`alkstore-sqlite` substrate — both carriers confirmed in the
package**: `src/substrate/PROVENANCE.md` (the full register with
fork-point statement and delta entries) and
`src/substrate/LICENSE` (the dual MIT+Apache text + fork-point +
modification statements); `substrate/mod.rs`'s module doc names
both, and the crate README + root README point at the notice — the
package is honest about carrying them (ADR-013 §3 / ADR-018 §1).
- **Path-dep version bounds verified**: `alkstore = { version = "0.1",
path = "../alkstore" }` on all three engines (the §4.1 carrier 1
manifest pin, pre-1.0 `0.y` form) and on the suite's dep; no
versioned path dep missing its bound.
- Packaged-source test evidence (all green, 2026-10-11): core
`.crate` extracted → 25 + 0 doc-tests; sqlite tree 193 + 25 suite
rows + 0; mem tree 102 + 25 + 1 doctest; postgres tree 127 + 25 + 9
+ 0 (postgres rows skip-green without a server env, the same posture
as the workspace test run).
### The manual publish checklist of record (the user's publish session)
Run from the workspace root; gates are assumed green (this task's
evidence; re-run if any later commit touched code):
```
cargo build
cargo test
cargo test --manifest-path fuzz/shared/Cargo.toml
cargo clippy --all-targets -- -D warnings
cargo fmt --check
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps
```
```
# 1. Core first — the engines' packaged manifests resolve `alkstore
# = "0.1"` from the index; until this lands, cargo package/publish
# for the engines is impossible (the error this task captured).
cargo package -p alkstore && tar tf target/package/alkstore-0.1.0.crate
# eyeball: LICENSE-MIT/LICENSE-APACHE at the tarball root, README,
# no stray paths (this task's evidence: 30 files, all clean).
cargo publish -p alkstore
# wait for index availability (a minute or two;
# `cargo search alkstore` resolving is the readiness probe).
# 2. Engines — any order among them (mutually independent); each now
# packages + verifies fully against the live core:
cargo package -p alkstore-sqlite
tar tf target/package/alkstore-sqlite-0.1.0.crate | grep -E 'LICENSE|substrate'
# eyeball: LICENSE-MIT/LICENSE-APACHE at the tarball root AND
# src/substrate/{PROVENANCE.md,LICENSE} riding in-tree.
cargo publish -p alkstore-sqlite
cargo package -p alkstore-postgres && cargo publish -p alkstore-postgres
cargo package -p alkstore-mem && cargo publish -p alkstore-mem
# 3. Tag + forge release: v0.1.0 (the CHANGELOG's tag link points here).
```
## Summary
Landed (2026-10-11): ADR-017 §1's pre-release class-1 amendment (initial
release 0.1.0, user decision — family 0.x-initial precedent, §4.1 pins
stay the pre-1.0 `0.y` form); package metadata on the four published
crates (colon-form descriptions, keywords ≤5, categories; homepage/
documentation omitted per family precedent); per-crate LICENSE-MIT +
LICENSE-APACHE copies (workspace-inherited `license-files` proved a
cargo-1.99 packaging no-op in a sandbox, reverted — the copies are what
cargo's auto-detect packages). Package verification: core full
cargo-native (package + verify build + `publish --dry-run` clean, 30
files); engines blocked pre-core-publish by construction (captured
error) — verified from reconstructed exact-`--list` trees with the
publish-shaped manifests (core dep as its publish-legal version+path
form), all green (sqlite 193+25, mem 102+25+1, postgres 127+25+9).
Publish-exclusion verification clean: no fuzz/sidecar/corpora/ suite
paths in any package's file list (engines' in-src
`fuzz_surface_tests.rs` are the documented crate-internal probe tests,
not leakage); sqlite's package carries `src/substrate/PROVENANCE.md` +
the dual-license `src/substrate/LICENSE`, documented in `mod.rs` and
the readmes. Path-dep bounds verified on all engines + suite; the
manual publish checklist of record (core → engines, per-crate package
→ eyeball → publish, plus the gates) written into Notes. Gates at
session end: build, full `cargo test` (15 result blocks green),
clippy `--all-targets -- -D warnings`, fmt --check, doc gate
(`RUSTDOCFLAGS="-D warnings"`), fuzz corpus replay — all green.