You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Zed deployment contract (SWR-IDE-ZED) and release change-detection scope (#34)
## TLDR
Pin the Zed extension deployment model as `[SWR-IDE-ZED]` across the
specs and the shipwright-compliance skill — the WASM extension verifies
the downloaded binary's SHA-256 digest in-extension while the cosign
signature is checked at the release boundary — and land the
`shipwright-release-scope` change-detection tool with its spec, schema,
template, and fixtures.
## Details
**Zed deployment contract — `[SWR-IDE-ZED]`**
- `docs/specs/ide-extension-deployment.md`: new `[SWR-IDE-ZED]` section.
A Zed extension is WASM and cannot bundle a native binary; resolution
order is user `binary.path` → cached download → verified
`github-release` download (`latest_github_release` + `download_file` for
the current platform → SHA-256 verified against `SHA256SUMS` →
`make_file_executable`), then version-gated via LSP `initialize`.
`~/.cargo/bin`, bare-PATH, and `worktree.which` are forbidden as silent
defaults. A download branch made unreachable behind a never-true guard
(dead-download) is a FAIL. Publishing is a reviewed PR to
`zed-industries/extensions` (submodule + `extensions.toml` + `pnpm
sort-extensions`), WASM built reproducibly in CI, never committed.
- `docs/specs/supply-chain-security.md`: carve Zed out of
cosign-signature-before-exec. The WASM sandbox has no cosign primitive,
so the extension verifies the SHA-256 **digest** in-extension; the
cosign **signature** over `SHA256SUMS` is verified at the release/CI
boundary. Updated `[SWR-SEC-CHECKSUM]`, the per-channel table row, and
the Zed paragraph.
- shipwright-compliance skill (`SKILL.md`,
`reference/audit-checklist.md`, `reference/implement-release.md`,
`reference/manifest-and-platforms.md`): audit rules updated to match —
digest-in-extension vs signature-at-boundary,
`worktree.which`/`~/.cargo/bin` barred as silent defaults, dead-download
as a FAIL, registry publishing mechanics.
- `crates/shipwright-zed/src/lib.rs`: module doc references
`SWR-IDE-ZED`.
- `.github/workflows/deploy-pages.yml`: auto-deploy the website on push
to `main` (paths `docs/specs/**`, `website/**`) instead of
`workflow_dispatch` only, so the published specs stay current.
**Release change-detection — `shipwright-release-scope`**
- `tools/shipwright-release-scope/`: new Rust workspace member (adds the
`glob` workspace dependency; `Cargo.toml`/`Cargo.lock` updated).
- `docs/specs/release-change-detection.md` (`SWR-REL-CHANGES-*`),
`schemas/release-scope.schema.json`,
`templates/gh-actions/release-change-detection.yml`,
`fixtures/release-scope/basilisk.json`.
- `fixtures/spec-coverage.json`: coverage entry
(`SWR-SPEC-RELEASE-CHANGE-DETECTION`) for the new spec.
- `coverage-thresholds.json`: 100% threshold for the new crate.
No breaking changes — spec/doc/skill updates plus additive tooling; all
source version fields remain `0.0.0-dev`.
## How Do The Automated Tests Prove It Works?
- `node --test tests/fixtures.test.mjs` (7/7): `each spec file has
fixture coverage or a tracked ticket id` now passes for
`docs/specs/release-change-detection.md` (it was red — the spec existed
with no coverage entry); `tracked SWR ids do not use numeric suffixes`
passes for the new `SWR-IDE-ZED` and `SWR-SPEC-RELEASE-CHANGE-DETECTION`
ids.
- `make test`: 100% line coverage across every crate including
`crates/shipwright-zed` and `tools/shipwright-release-scope`; Dart
resolver-vector tests and .NET tests pass.
- TypeScript matrix: `@nimblesite/shipwright-core` (55 tests),
`@nimblesite/shipwright-vscode` (16), `@nimblesite/shipwright-mcp` (5)
all pass.
- `make lint`: clippy (compiling the `shipwright-zed` doc-comment
change), .NET warnings-as-errors (0), Dart analyze (no issues), and AJV
manifest/schema validation all pass.
Copy file name to clipboardExpand all lines: docs/agents/shipwright-compliance/reference/audit-checklist.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -173,7 +173,7 @@ pipeline can still have required controls outstanding. Cite the `SWR-SEC-*` / `S
173
173
| VS Code Marketplace | per-VSIX provenance; bundled binary verified vs signed release (`SWR-VSIX-BUNDLE-VERIFY`); **Entra OIDC publish, no stored PAT** — `id-token: write`, publisher-member SP, in a protected env | SWR-VSIX-PUBLISH-OIDC / SWR-SEC-OIDC-PUBLISH |
174
174
| Open VSX |`node-ovsx-sign`; a **separate** short-expiry PAT in a protected env | SWR-SEC-OIDC-PUBLISH |
175
175
| JetBrains / Android Studio |`signPlugin` certificate signature; publish token in a protected env | SWR-SEC-OIDC-PUBLISH |
176
-
| Zed | no committed `.wasm` drift; runtime`github-release` download verifies checksum + signature; version via LSP `initialize`| SWR-SEC-CHECKSUM |
176
+
| Zed | no committed `.wasm` drift; the`github-release` download verifies the SHA-256 digest **in-extension** (cosign signature is a release-boundary check, not in the WASM sandbox); the download branch is reachable (no dead-download behind a never-true guard); no `~/.cargo/bin`/`worktree.which`/PATH default; reviewed-PR publish (submodule + `extensions.toml`); version via LSP `initialize`| SWR-SEC-CHECKSUM, SWR-IDE-ZED|
177
177
| Homebrew / Scoop |`sha256`/`hash` sourced from the verified `SHA256SUMS`; scoped `tap_token`/`bucket_token` in a protected env | SWR-SEC-CHECKSUM |
178
178
| Neovim | downloader verifies `SHA256SUMS` + cosign before exec; pins the resolved tag (never `/latest`) | SWR-SEC-CHECKSUM |
Copy file name to clipboardExpand all lines: docs/specs/ide-extension-deployment.md
+38-1Lines changed: 38 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,7 +60,7 @@ bin/
60
60
shipwright.json
61
61
```
62
62
63
-
Zed extensions may download and cache release assets when marketplace packaging prevents bundling native binaries. In that case, the extension MUST validate the server version from LSP initialize before enabling product features.
63
+
Zed extensions may download and cache release assets when marketplace packaging prevents bundling native binaries. In that case, the extension MUST validate the server version from LSP initialize before enabling product features. The canonical model — resolution order, integrity, and publishing — is [SWR-IDE-ZED].
64
64
65
65
## [SWR-IDE-TEST-ISOLATION] Extension Test Isolation
66
66
@@ -112,6 +112,43 @@ manager as a normal startup source.
112
112
113
113
If the user explicitly configured a path and it mismatches, do not fall back. The user needs a precise error so they can fix the configured path.
114
114
115
+
## [SWR-IDE-ZED] Zed Extension Deployment
116
+
117
+
Zed extensions are WebAssembly published through a human-reviewed PR to the `zed-industries/extensions`
118
+
registry; they cannot bundle a native binary (see [SWR-COMPAT-HOST-REQ] in the binary version contract).
119
+
Every Shipwright product's Zed extension MUST follow one model so the user experience matches the
120
+
bundled-VSIX flow: install the extension, get the matching binary, no manual steps.
121
+
122
+
**Resolution order** (in `language_server_command`, via `shipwright-zed` on the pure `shipwright-host`
123
+
resolver):
124
+
125
+
1. Explicit user override — the Zed LSP `binary.path` setting (or a documented env override).
126
+
2. A previously cached download in the extension's version-stamped work directory.
127
+
3. A verified `github-release` download: `latest_github_release` (pinned repo, resolved tag — never
128
+
`/latest` drift) → `download_file` for the current platform → SHA-256 digest verified against
129
+
`SHA256SUMS` → `make_file_executable`.
130
+
131
+
Then validate the running server's version from the LSP `initialize``serverInfo` before enabling
132
+
product features; a mismatch stops startup with a precise error ([SWR-IDE-ERROR]). Zed cannot preflight
133
+
`--version`.
134
+
135
+
**Forbidden as silent defaults.**`~/.cargo/bin`, a bare command name on `PATH`, and `worktree.which`
136
+
MUST NOT be the unconfigured startup source. A preinstalled/PATH binary is honored only when the user
137
+
explicitly opts into it (equivalent to an override), never as the default — the default is the verified
138
+
`github-release` download.
139
+
140
+
**Anti-pattern — dead download (FAIL).** A `github-release` download branch that is unreachable because
141
+
it is gated behind a condition that never occurs (e.g. only when `$HOME` is unset), leaving
142
+
`cargo install` / `~/.cargo/bin` or another package-manager path as the de-facto default, is a release
143
+
blocker. The audit MUST confirm the download branch is actually reachable on a normal machine.
144
+
145
+
**Integrity.** The digest is verified in-extension; the cosign signature over `SHA256SUMS` is verified at
146
+
the release/CI boundary, not in the WASM sandbox ([SWR-SEC-CHECKSUM]).
147
+
148
+
**Publishing.** Reviewed PR to `zed-industries/extensions`: add the extension as a git submodule under
149
+
`extensions/<id>`, add an `extensions.toml` entry (`submodule`, `version`, optional `path`), and run
150
+
`pnpm sort-extensions`. The `.wasm` is built reproducibly in CI and is never committed.
0 commit comments