GitHub release assets for q2: installers + minisign + bundled quarto-hub.com MCP defaults (bd-c6l13j79)#278
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-c6l13j79What's here
crates/quarto-mcp-launcher): release CI compilesQUARTO_HUB_BUNDLED_{CLIENT_ID,CLIENT_SECRET,SERVER}in viaoption_env!; the launcher injects them into the node child env for any variable the user hasn't set (blank = unset, mirroringreadNonEmptyin oauth-config.ts). User env always wins; source builds behave exactly as before.q2 mcp --launcher-inforeports per-variableenv|bundled|absent. The Desktop-appclient_secretis a public client credential (RFC 8252) — embedding matches gcloud/gh/rclone practice; CI-injection only keepsGOCSPX-scanners off the repo.install.sh(checksum + minisign Ed25519, both mandatory/fail-closed, trusted comment = filename) andinstall.ps1(checksum-only), ported from braid; pinned pubkey91F595A50BD20376. 32 offline tests incrates/quarto/tests/integration/bootstrap_sh.rs;test-suite.ymlinstalls minisign.ts-packages/quarto-hub-mcp/scripts/stage-keyring.mjs):KEYRING_PLATFORMSpins which@napi-rs/keyringnative 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 vianpm packat the loader's locked version; fail-closed. 10 offline unit tests..github/workflows/release.yml): tag-triggered, preflight tag↔version check, aweb-payloadsjob 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-infomust 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.q2 --versionnow reports the real workspace version (quarto 0.1.0) instead of the99.9.9-devplaceholder — release artifacts must be verifiable against their tag, and Lua-sidequarto.versionalready reported{0,1,0}. Extension minimum-version checks will see 0.1.0; accepted for now.openssl-sys/vendoredscoped tocfg(target_env = "musl")(samod → tokio-tungstenite(native-tls) needs openssl; static linux builds get it from source).Verification
cargo xtask verify: all steps green (the hub-mcp suite fails ifQUARTO_HUB_MCP_*operator credentials are exported in the shell — pre-existing hermeticity gap, filed as bd-n6dhrz4j).QUARTO_NODE; user-override and absent-defaults paths included).npm pack.v0.1.0is 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
🤖 Generated with Claude Code