Skip to content

Tester channel: public beta pre-releases signed with our own keys (D48) - #6

Draft
FacuM wants to merge 15 commits into
mainfrom
feat/tester-channel
Draft

FacuM wants to merge 15 commits into
mainfrom
feat/tester-channel

Conversation

@FacuM

@FacuM FacuM commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Tester channel: public beta pre-releases (D48), signed with our own ed25519 keys while Authenticode and crypto review pass 1 are pending.

Decision

  • D48 (decisions.md, requirements.md, 04 §10, §12.3): beta-channel builds may be published as public GitHub pre-releases before review pass 1 and before Authenticode. Gates review-pass1 and authenticode may be waived on beta only (with a note); stable keeps every gate. Each beta carries SHA256SUMS + ed25519 SHA256SUMS.sig, the "not yet externally reviewed" notice in setup and release notes, and the key fingerprints in the README.

What changes

  • sd-release gates check accepts the two beta waivers (stable still refuses them).
  • installer/dokany/dokany.lock: Dokany 2.3.1.1000 pinned from the upstream files (size, SHA-256, signer LEOSAC / Certum EV, MSI UpgradeCodes; dokan2.dll imports no VC++ runtime on x64/x86, so the MSI form applies; ARM64 has no row yet). sd-release dokany verify checks files against it; the setup EXE embeds the verified MSIs as DOKANY_X64/X86.
  • Keys: sd-release keyring turns installer/keys/{roots.txt,keyset.txt} into the stub's keyring and the agent's update trust at build time (cmake/SdKeyring.cmake). Without installer/keys/ every build keeps the revoked placeholder (fail closed), as today.
  • tools/release/key-ceremony.ps1 + docs/dev/key-ceremony.md: the offline ceremony (two roots, release-beta key, keyset v1 signed by both roots, fingerprints block).
  • Setup: SD_SETUP_PRERELEASE_NOTICE (on for the beta channel) shows the notice on the welcome page in en/es/fr/pt-BR/it/de; unattended runs log it.
  • tools/release/package-beta.ps1 and release.yml beta path: build with the beta channel, verify and embed Dokany, sign payload tables, insert PAYLOAD_SIG, SHA256SUMS(.sig), manifest, verify everything, gh release create --prerelease. The seed lives only in the protected beta-signing environment (temp file, never printed, deleted in an always() step); only the publish job has contents: write. Stable stays fail-closed. Guide: docs/dev/release-beta.md.

Verification

  • tools/ci-local.ps1 -Pipeline: all five presets pass at 1fc4df9.
  • Key ceremony dry run with throwaway keys (network check removed in a scratch copy only): both root signatures verify, and its output goes through sd-release keyring. The dry run found and fixed a bug in the second signature check.
  • Local end-to-end beta packaging with throwaway keys and the real Dokany files: setup EXEs for x86-ia32, arm64, arm32 and six MSIs; every sd-release verify OK, SHA256SUMS matches, the embedded PAYLOAD_SIG verifies against the compiled-in keyring and the embedded Dokany resources equal the locked files. tools/check-workflows.ps1: 0 warnings.

Before the first real beta (maintainer)

  1. Run the key ceremony offline; commit installer/keys/roots.txt and keyset.txt; add the fingerprints block to the README.
  2. GitHub: environment beta-signing (required reviewer) with secret RELEASE_BETA_SEED; workflow permissions allowing contents: write for the publish job.
  3. Commit installer/keys/release-gates.txt for the version (channel beta).

Known gaps

  • No setup EXE for x64-modern, x64-xp, x86-sse2 yet (no payload CAB target; the universal EXE is not in the tree).
  • The stub embeds Dokany but does not chain it yet (sd_setup_dokany_run is not called); the release notes say so.
  • Setup EXE sizes differed by 0.5-1 KB between two identical local runs: possible non-determinism to check with check-repro.
  • sign-beta repackages from scratch instead of signing the package job's artifacts.
  • Pre-existing flaky test seen in one gate run: unit.svc svc_autostart_failed_mount_is_replaced_by_a_new_mount assumes the same free drive letter while other gate tests mount drives.

FacuM added 15 commits October 31, 2026 23:06
… 1 and signing

Beta builds may be published as public GitHub pre-releases; the review-pass1 and
authenticode gates may be waived for beta only, with SHA256SUMS.sig, the
not-yet-reviewed notice and the key fingerprints in the README. Stable keeps
every gate.
Stable still refuses both waivers; tests cover the beta record and the two
stable refusals.
Size, SHA-256, signer and MSI UpgradeCodes recorded from the upstream files;
dokan2.dll imports no VC++ runtime on x64 or x86, so the MSI form applies.
ARM64 has no row yet.
tools/release/key-ceremony.ps1 generates the two roots and the release-beta key
on an offline machine, signs keyset version 1 with both roots, verifies each
signature and writes roots.txt, keyset.txt and the README fingerprints block.
docs/dev/key-ceremony.md walks the maintainer through it (D48, 04 9.3).
…age (D48)

SD_SETUP_PRERELEASE_NOTICE (default on for the beta channel) adds a visible
notice to the welcome page in the six languages; unattended runs log it in
English. Tests check the catalogs and when the flow shows it.
One sentence next to the interim rule in 04 §10 (beta setups carry the
notice; silent runs log it in English) and a short paragraph in
docs/dev/m4-notes.md with the option's default, the compile-in path and
the tests.
sd-release keyring verifies the signed keyset of installer/keys/keyset.txt
against the two root public keys of roots.txt (the keyset's root line
encoding; comments and blank lines allowed) and writes the two include
files deterministically into the build tree: setup_keyring.inc (the stub's
payload keyring) and update_trust.inc (the update trust of
shelldrive-host). cmake/SdKeyring.cmake runs it as a build step whenever
installer/keys/ exists; without it the placeholders in the source tree are
compiled in, so every verification still fails closed.

The payload signature library splits: sd_payload_sig_text (pure verifier,
linked by sd-release) and sd_payload_sig (the stub's keyring wrapper), so
the keyring of the build can depend on the tool that generates it without
a dependency cycle. sd-release joins the host tools of the ARM64 and ARM32
nested builds, since it now runs during the build there too. The includes
are angle form and the generated directory goes first on the include path:
a quoted include would always find the placeholder beside the sources,
whatever the -I order (checked with cl).

Test: tests/release/keyring_flow.cmake (ctest release.keyring) covers the
generated entries, the inclusive unix-second dates, revocation, byte
determinism, a keyset signed by an unknown root (exit 3) and malformed
roots.txt variants (exit 2).
…-R23)

The package job checks size and SHA-256 of every pinned Dokany file at
embed time. The strict parser takes printable ASCII with LF or CRLF,
the dokany-lock 1 header, known key lines and file lines only, and
refuses unknown keys, duplicates and malformed file lines (exit 2); a
file that is missing or differs exits 3. --arch checks one arch plus
the bundle. Test release.dokany covers the cases with fake files.
sd-payload gains --dokany-x64/--dokany-x86: the lock-verified upstream
packages ride as RT_RCDATA resources (04 6.1), unmodified. SdPayload
passes them from the new SD_PAYLOAD_DOKANY_X64/X86 cache variables, so
the packaging script can reconfigure with PAYLOAD_SIG and the Dokany
resources in one attach step. Without them nothing changes.
…s1 (D48)

The whole beta packaging, runnable locally and from CI: fresh
-DSD_SETUP_CHANNEL=beta build trees (pre-release notice defaults ON),
setup EXEs and MSIs of the producible flavours, dokany.lock verification
of the upstream files (never a download), payload tables, and with
-seed the payload-table signatures, the PAYLOAD_SIG reattach plus the
DOKANY_X64/X86 resources, SHA256SUMS + SHA256SUMS.sig, the signed beta
manifest and release notes that open with the not-yet-reviewed notice.
Without -seed it stops after the unsigned artifacts and
payload-tables.txt. What the repository cannot produce (x64 and
x86-sse2 setups, MSIs without WiX, ARM64 Dokany) is skipped with a
clear message, never faked.
workflow_dispatch gains the channel input, beta by default. package
downloads the pinned Dokany files fresh from the lock's url-upstream
(no caches, TM-R39) and runs package-beta.ps1 without the seed; sign-beta
holds the release-beta seed in the protected beta-signing environment
(secret RELEASE_BETA_SEED, written to a temp file and deleted after the
run, never printed) and produces the signed release set; publish-beta is
the only contents: write job and creates the v<V>-beta pre-release with
the generated notes. Stable keeps every gate and its offline sessions:
its package and finalize jobs fail closed as before.
docs/dev/release-beta.md: the one-time GitHub setup (beta-signing
environment, RELEASE_BETA_SEED, installer/keys committed, the gates
record), the CI job order and the local flow with
tools/release/package-beta.ps1, plus what is skipped and why.
key-ceremony.md points there from the release-beta seed section.
…fix the MSI copy source

Extract PAYLOAD_TABLE, PAYLOAD_SIG and the Dokany resources from each final setup EXE, require them to be the signed/verified bytes, and verify the embedded signature. Collect the MSIs from the build tree, and fix the skipped-flavour message.
…h-beta

The publish job has no checkout, so gh needs GH_REPO. It no longer binds beta-signing, which keeps RELEASE_BETA_SEED out of the job that holds contents: write.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant