Skip to content

GitHub release assets for q2: installers + minisign + bundled quarto-hub.com MCP defaults (bd-c6l13j79)#278

Merged
cscheid merged 4 commits into
mainfrom
feature/bd-c6l13j79-github-release-assets-q2
Jun 12, 2026
Merged

GitHub release assets for q2: installers + minisign + bundled quarto-hub.com MCP defaults (bd-c6l13j79)#278
cscheid merged 4 commits into
mainfrom
feature/bd-c6l13j79-github-release-assets-q2

Conversation

@cscheid

@cscheid cscheid commented Jun 12, 2026

Copy link
Copy Markdown
Member

Adopts cscheid/braid's release mechanism for q2 and bakes the quarto-hub.com connection defaults into release binaries, so colleagues install q2 + node and run the MCP with zero configuration — no more out-of-band env-var distribution.

Plan: claude-notes/plans/2026-06-12-q2-github-releases-bundled-mcp.md · Strand: bd-c6l13j79

What's here

  • Bundled OAuth defaults (crates/quarto-mcp-launcher): release CI compiles QUARTO_HUB_BUNDLED_{CLIENT_ID,CLIENT_SECRET,SERVER} in via option_env!; the launcher injects them into the node child env for any variable the user hasn't set (blank = unset, mirroring readNonEmpty in oauth-config.ts). User env always wins; source builds behave exactly as before. q2 mcp --launcher-info reports per-variable env|bundled|absent. The Desktop-app client_secret is a public client credential (RFC 8252) — embedding matches gcloud/gh/rclone practice; CI-injection only keeps GOCSPX- scanners off the repo.
  • Installers: install.sh (checksum + minisign Ed25519, both mandatory/fail-closed, trusted comment = filename) and install.ps1 (checksum-only), ported from braid; pinned pubkey 91F595A50BD20376. 32 offline tests in crates/quarto/tests/integration/bootstrap_sh.rs; test-suite.yml installs minisign.
  • Target-aware keyring staging (ts-packages/quarto-hub-mcp/scripts/stage-keyring.mjs): KEYRING_PLATFORMS pins which @napi-rs/keyring native addons ship in the bundle — they must match the user's node, and the darwin_amd64 release builds on an arm64 runner. Missing addons fetched via npm pack at the loader's locked version; fail-closed. 10 offline unit tests.
  • Release workflow (.github/workflows/release.yml): tag-triggered, preflight tag↔version check, a web-payloads job building the target-independent embeds once (WASM → preview SPA, trace viewer), 5-target matrix (linux musl x2, darwin x2, windows), per-target anti-placeholder/anti-stale-embed verification (--launcher-info must show a real bundle, bundled defaults ×3, and the target's keyring addons), sha256 + minisign + self-verify against the install.sh pin, combined checksums, gh release create.
  • CLI version contract change (decided in-session): q2 --version now reports the real workspace version (quarto 0.1.0) instead of the 99.9.9-dev placeholder — release artifacts must be verifiable against their tag, and Lua-side quarto.version already reported {0,1,0}. Extension minimum-version checks will see 0.1.0; accepted for now.
  • musl TLS: openssl-sys/vendored scoped to cfg(target_env = "musl") (samod → tokio-tungstenite(native-tls) needs openssl; static linux builds get it from source).

Verification

  • Full workspace suite after the version change: 10038/10038 passed.
  • Clean-env cargo xtask verify: all steps green (the hub-mcp suite fails if QUARTO_HUB_MCP_* operator credentials are exported in the shell — pre-existing hermeticity gap, filed as bd-n6dhrz4j).
  • Launcher defaults verified end-to-end against a local build with test values baked in (child-env dump via fake QUARTO_NODE; user-override and absent-defaults paths included).
  • Cross-platform keyring fetch verified on an arm64 mac: staged a Mach-O x86_64 addon via npm pack.
  • The release workflow itself is actionlint-clean but unexercised — after merge, pushing tag v0.1.0 is the dry run (plan Phase 4). Static-musl (aws-lc-sys) is the known risk; fallback to gnu is a one-line matrix change (plan D4).

Discovered work filed

  • bd-n6dhrz4j — hub-mcp tests not hermetic against exported operator credentials
  • bd-3up1mf8c — pre-existing deny-level clippy error in quarto-core capture_splice.rs

🤖 Generated with Claude Code

cscheid and others added 4 commits June 12, 2026 16:59
…d-c6l13j79)

Release builds of q2 compile in defaults for the three env vars the TS
MCP server reads (QUARTO_HUB_MCP_CLIENT_ID/CLIENT_SECRET, QUARTO_HUB_SERVER)
from QUARTO_HUB_BUNDLED_{CLIENT_ID,CLIENT_SECRET,SERVER} build-time env
(set only by the release workflow, from GH secrets/vars). The launcher
injects them into the node child's environment for any variable the
user hasn't set to a non-blank value — readNonEmpty semantics mirrored
from oauth-config.ts, so blank counts as unset. Source builds compile
with no values and behave exactly as before (TS server's own error).

The Desktop-app OAuth client_secret is a public client credential
(RFC 8252) — embedding is the standard native-app distribution (gcloud,
gh, rclone); CI-time injection only keeps GOCSPX- scanners away from
the repo. Plan: claude-notes/plans/2026-06-12-q2-github-releases-bundled-mcp.md

- src/defaults.rs: bundled_defaults() + classify/injections/sources
  pure logic, unit-tested (9 tests)
- delegate.rs: build_command seam (testable — the Unix path execs and
  cannot be observed by a test); env injection ahead of the
  exec/spawn split (2 tests)
- --launcher-info gains 'default <VAR>: env|bundled|absent' lines
  (values uniformly elided; printed for placeholder builds too)
- .gitignore: /q2-release.{key,pub} — release signing keypair must
  never be committed

Verified end-to-end with test values baked into a local build: child
process receives bundled values only for unset vars; user env wins;
absent-defaults build injects nothing. 35/35 launcher tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arness (bd-c6l13j79)

Ported from cscheid/braid's release tooling (study copy in
external-sources/braid): checksum + minisign Ed25519 verification both
mandatory and fail-closed, trusted comment = archive filename (replay
protection), atomic install, non-interactive under curl|bash. q2
deltas: flat archive (the MCP bundle is embedded in the binary), Q2_*
env vars, --from-source builds the MCP bundle when npm is present,
unsupported-platform advice points at --from-source. The pinned
signing key is 91F595A50BD20376 (public half; the secret lives in the
MINISIGN_SECRET_KEY repo secret).

- crates/quarto/tests/integration/bootstrap_sh.rs: 32 offline tests
  (file:// + --checksum; no network), covering refusal paths, signature
  replay, tampering, dest resolution, quiet mode, uninstall, shellcheck
- test-suite.yml: install minisign on both runners (the suite requires
  it loudly — silent skip would leave the signature contract unguarded)
- README: Installing section with pinned pubkey + manual verification

Plan: claude-notes/plans/2026-06-12-q2-github-releases-bundled-mcp.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The .node addon ships inside the bundle's mini node_modules and is
loaded by the *user's* node, so it must match the release target, not
the build host — braid-style release matrices cross-build darwin_amd64
on arm64 runners, where only keyring-darwin-arm64 is installed.

scripts/stage-keyring.mjs (split from bundle.mjs, injectable fetcher):
- KEYRING_PLATFORMS env (e.g. 'darwin-x64,darwin-arm64') pins exactly
  which platform packages ship; missing ones are fetched via npm pack
  at the loader's exact version
- unset → original dev behavior (stage every installed platform pkg)
- fail-closed: unfetchable platform or addon-less package aborts

10 offline unit tests (fake fetcher, fabricated @napi-rs trees) in
src/keyring-staging.test.ts. Real-fetch path verified by hand on this
arm64 mac: KEYRING_PLATFORMS=darwin-arm64,darwin-x64 staged a Mach-O
x86_64 keyring.darwin-x64.node via npm pack. Full package suite green
(194 passed; requires QUARTO_HUB_MCP_* unset — exported operator
credentials make spawned test servers register auth tools).

Plan: claude-notes/plans/2026-06-12-q2-github-releases-bundled-mcp.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
.github/workflows/release.yml, ported from cscheid/braid with q2's
three-embedded-payloads reality:
- preflight: tag must match the workspace Cargo.toml version
- web-payloads job builds the target-independent embeds once (WASM →
  preview SPA, trace viewer; toolchain mirrors hub-client-e2e.yml,
  wasm-bindgen-cli pinned from Cargo.lock); the 5-target matrix
  downloads them and builds the MCP bundle per target with
  KEYRING_PLATFORMS (user-node addons: both libcs on linux, both mac
  archs, both win archs)
- bundled hub defaults injected from secrets/vars into the cargo env,
  release workflow only, with an empty-value fail-fast
- per-target verify step: --version equals the tag version; launcher
  info shows no PLACEHOLDER, 'default …: bundled' ×3, and a keyring
  addon per requested platform (the anti-stale-embed gate)
- archives + sha256 + minisign (trusted comment = filename),
  self-verified against the install.sh pinned key; combined
  checksums.sha256; gh release create (prerelease on -suffix tags)

CLI version contract change (Carlos, in-session): q2 --version now
reports the real workspace version ('quarto 0.1.0') instead of the
99.9.9-dev extension-compat placeholder — release artifacts must be
verifiable against their tag, and Lua-side quarto.version already
reported {0,1,0}. TDD'd (red first) in quarto-util. The since_version
99.9.9 markers in error_catalog.json are a separate concern, untouched.

Also: musl-scoped openssl-sys/vendored in crates/quarto (samod →
tokio-tungstenite(native-tls) needs openssl; static musl builds get it
from source), and a semver-compliant deprecated-since in
quarto-source-map (pre-existing deny-level clippy error, on-topic with
the version decision). Remaining pre-existing clippy deny in
quarto-core filed as bd-3up1mf8c.

Full workspace suite after the version change: 10038/10038 passed.

Plan: claude-notes/plans/2026-06-12-q2-github-releases-bundled-mcp.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cscheid
cscheid merged commit 3122294 into main Jun 12, 2026
5 checks passed
@cscheid
cscheid deleted the feature/bd-c6l13j79-github-release-assets-q2 branch June 12, 2026 23:10
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