@rightkit/release 0.2.26 → 0.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,514 +1,530 @@
1
- import assert from "node:assert/strict";
2
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import path from "node:path";
5
- import { spawnSync } from "node:child_process";
6
- import { pathToFileURL } from "node:url";
7
- import test, { after } from "node:test";
8
- import {
9
- assertNoRightKitCargoOverrides,
10
- assertPublishedRightKitCargoDependencies,
11
- validateRightKitCargoContract,
12
- } from "./cargo-contract.mjs";
13
- import { assertAsrAdapterPair } from "./asr-artifact-adoption.mjs";
14
-
15
- const workspace = path.resolve(new URL("../../../..", import.meta.url).pathname.replace(/^\/(\w:)/, "$1"));
16
- // The Right Suite web layer's repo + filesystem path is `rightsites` post the 2026-07-15 naming lock;
17
- // a not-yet-renamed checkout may still have `rightapps`. Resolve whichever exists so the contract
18
- // passes on both. (The runtime service namespace stays `rightapps` — that is deliberately untouched.)
19
- const siteRepoDir = existsSync(path.join(workspace, "rightsites")) ? "rightsites" : "rightapps";
20
- const versionsPath = path.join(path.dirname(new URL(import.meta.url).pathname.replace(/^\/(\w:)/, "$1")), "rightkit-versions.json");
21
- const versions = JSON.parse(readFileSync(versionsPath, "utf8"));
22
- const isolatedCargoHome = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-home-"));
23
- after(() => rmSync(isolatedCargoHome, { recursive: true, force: true }));
24
- const pubkey = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDI5Mzk1RjlGRjQ2NjI2MUQKUldRZEptYjBuMTg1S1VSUXlBdFM4WmtzaHArYko0U2hRMDVlSDJmSExVZG82Q0hoQ2srUlhqanAK";
25
- const apps = [
26
- { key: "viewright", root: "viewright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/build-mac-notarized.sh"] },
27
- { key: "scraperight", root: "scraperight", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["package.sh"] },
28
- { key: "heardright", root: "heardright/tauri-app-next", repoRoot: "heardright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs", "scripts/publish-release.mjs"] },
29
- // mac-dmg.mjs is the release file, as in HeardRight/CodeRight. build-mac.sh only delegates to it,
30
- // so asserting the mirror call against the wrapper failed a pipeline that does mirror.
31
- { key: "mailright", root: "mailright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
32
- { key: "coderight", root: "coderight/apps/coderight-tauri", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
33
- ];
34
-
35
- function resolveCargoVersionContract(versionManifest, canonicalVersions) {
36
- const consumer = new Map(Object.entries(versionManifest.cargo ?? {}));
37
- const staged = new Map(Object.entries(versionManifest.stagedCargo ?? {}));
38
- const canonical = new Map();
39
-
40
- for (const [crate, version] of staged) {
41
- if (!canonicalVersions.has(crate)) throw new Error(`unknown staged Cargo crate: ${crate}`);
42
- const actual = canonicalVersions.get(crate);
43
- if (actual !== version) {
44
- throw new Error(`${crate} canonical manifest is ${actual}, expected staged version ${version}`);
45
- }
46
- canonical.set(crate, version);
47
- }
48
-
49
- for (const [crate, version] of consumer) {
50
- if (!canonicalVersions.has(crate)) throw new Error(`unknown published Cargo crate: ${crate}`);
51
- const expected = staged.get(crate) ?? version;
52
- const actual = canonicalVersions.get(crate);
53
- if (actual !== expected) {
54
- const source = staged.has(crate) ? "staged" : "published";
55
- throw new Error(`${crate} canonical manifest is ${actual}, expected ${source} version ${expected}`);
56
- }
57
- canonical.set(crate, expected);
58
- }
59
-
60
- return { canonical, consumer };
61
- }
62
-
63
- let currentCargoVersionContract;
64
- function getCurrentCargoVersionContract() {
65
- currentCargoVersionContract ??= resolveCargoVersionContract(versions, readCanonicalCrateVersions());
66
- return currentCargoVersionContract;
67
- }
68
-
69
- const cargoContractCache = new Map();
70
- function readCargoManifestContract(manifestPath, label) {
71
- const cacheKey = path.resolve(manifestPath).toLowerCase();
72
- if (cargoContractCache.has(cacheKey)) return cargoContractCache.get(cacheKey);
73
- const result = spawnSync(
74
- "cargo",
75
- ["metadata", "--no-deps", "--offline", "--format-version", "1", "--manifest-path", manifestPath],
76
- {
77
- cwd: path.dirname(manifestPath),
78
- encoding: "utf8",
79
- env: { ...process.env, CARGO_HOME: isolatedCargoHome },
80
- windowsHide: true,
81
- },
82
- );
83
- assert.equal(
84
- result.status,
85
- 0,
86
- `${label} Cargo metadata rejected manifest; RightKit dependencies must use exact crates.io versions: ${String(result.stderr ?? "").trim()}`,
87
- );
88
- const metadata = JSON.parse(result.stdout);
89
- const expectedPath = path.resolve(manifestPath).toLowerCase();
90
- const pkg = metadata.packages.find(({ manifest_path: candidate }) => path.resolve(candidate).toLowerCase() === expectedPath);
91
- if (!pkg && path.resolve(metadata.workspace_root, "Cargo.toml").toLowerCase() === expectedPath) {
92
- const contract = { dependencies: [], workspaceRoot: path.resolve(metadata.workspace_root) };
93
- cargoContractCache.set(cacheKey, contract);
94
- return contract;
95
- }
96
- assert.ok(pkg, `${label} was not returned by Cargo metadata`);
97
- const contract = { dependencies: pkg.dependencies, workspaceRoot: path.resolve(metadata.workspace_root) };
98
- cargoContractCache.set(cacheKey, contract);
99
- return contract;
100
- }
101
-
102
- function assertCargoFixture(manifest, published, label) {
103
- const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-contract-"));
104
- const manifestPath = path.join(fixtureRoot, "Cargo.toml");
105
- const packageMetadata = /^\s*\[\s*package\s*\]/m.test(manifest)
106
- ? ""
107
- : '\n[package]\nname = "rightkit-contract-fixture"\nversion = "0.0.0"\nedition = "2021"\n';
108
- writeFileSync(manifestPath, `${manifest}${packageMetadata}\n[lib]\npath = "fixture.rs"\n`, "utf8");
109
- writeFileSync(path.join(fixtureRoot, "fixture.rs"), "", "utf8");
110
- try {
111
- return assertPublishedRightKitCargoDependencies(
112
- readCargoManifestContract(manifestPath, label).dependencies,
113
- published,
114
- label,
115
- );
116
- } finally {
117
- rmSync(fixtureRoot, { recursive: true, force: true });
118
- }
119
- }
120
-
121
- function assertCargoOverrideFixture({ manifest, workspaceManifest, localConfig, ancestorConfig, outsideConfig }) {
122
- const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-override-"));
123
- const repoRoot = path.join(fixtureRoot, "repo");
124
- const appRoot = path.join(repoRoot, "app");
125
- mkdirSync(appRoot, { recursive: true });
126
- const manifestPath = path.join(appRoot, "Cargo.toml");
127
- writeFileSync(manifestPath, manifest, "utf8");
128
- if (workspaceManifest) writeFileSync(path.join(repoRoot, "Cargo.toml"), workspaceManifest, "utf8");
129
- for (const [root, filename, source] of [
130
- [appRoot, "config", localConfig],
131
- [repoRoot, "config.toml", ancestorConfig],
132
- [fixtureRoot, "config.toml", outsideConfig],
133
- ]) {
134
- if (!source) continue;
135
- const cargoDir = path.join(root, ".cargo");
136
- mkdirSync(cargoDir, { recursive: true });
137
- writeFileSync(path.join(cargoDir, filename), source, "utf8");
138
- }
139
- try {
140
- assertNoRightKitCargoOverrides(manifestPath, repoRoot, "fixture/Cargo.toml");
141
- if (workspaceManifest) {
142
- assertNoRightKitCargoOverrides(path.join(repoRoot, "Cargo.toml"), repoRoot, "fixture/workspace Cargo.toml");
143
- }
144
- return 0;
145
- } finally {
146
- rmSync(fixtureRoot, { recursive: true, force: true });
147
- }
148
- }
149
-
150
- test("Cargo override contract accepts exact registry pins without repo-local overrides", () => {
151
- assert.equal(assertCargoOverrideFixture({
152
- manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
153
- localConfig: `[net]\nretry = 2\n[registries.private]\nindex = "https://example.test/index"`,
154
- outsideConfig: `[source.crates-io]\nreplace-with = "user-global-vendor"`,
155
- }), 0);
156
- });
157
-
158
- test("Cargo override contract rejects RightKit patches and replacements in repo-local Cargo config", () => {
159
- for (const config of [
160
- { localConfig: `[patch.crates-io]\nrightkit-license = { path = "../rightkit-license" }` },
161
- { localConfig: `patch . "https://github.com/rust-lang/crates.io-index" . "rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }` },
162
- { localConfig: `[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }` },
163
- { ancestorConfig: `[patch.private-source]\nadapter = { package = "rightkit-license", registry = "private" }` },
164
- ]) {
165
- assert.throws(
166
- () => assertCargoOverrideFixture({
167
- manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
168
- ...config,
169
- }),
170
- /forbidden RightKit Cargo override/,
171
- );
172
- }
173
- });
174
-
175
- test("Cargo override contract rejects path patches, Git patches, and replace entries", () => {
176
- for (const manifest of [
177
- `patch . "crates-io" . "rightkit-license" = { path = "../rightkit-license" } # dotted path patch`,
178
- `[ patch . "https://github.com/rust-lang/crates.io-index" ]\n"rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }`,
179
- `[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }`,
180
- ]) {
181
- assert.throws(
182
- () => assertCargoOverrideFixture({ manifest }),
183
- /forbidden RightKit Cargo override/,
184
- );
185
- }
186
- });
187
-
188
- test("Cargo override contract rejects workspace-root patches inherited by a member", () => {
189
- assert.throws(
190
- () => assertCargoOverrideFixture({
191
- manifest: `[package]\nname = "fixture"\nversion = "0.0.0"`,
192
- workspaceManifest: `[workspace]\nmembers = ["app"]\n[patch.crates-io]\nrightkit-license = { path = "patched/rightkit-license" }`,
193
- }),
194
- /forbidden RightKit Cargo override/,
195
- );
196
- });
197
-
198
- test("Cargo override contract rejects local and repo-ancestor crates.io source replacement", () => {
199
- for (const fixture of [
200
- {
201
- localConfig: `source . crates-io . replace-with = "vendored-sources"\n[source.vendored-sources]\ndirectory = "vendor"`,
202
- },
203
- {
204
- ancestorConfig: `[source."crates-io"]\nreplace-with = "rightkit-git"\n[source.rightkit-git]\ngit = "https://example.test/rightkit-index.git"`,
205
- },
206
- {
207
- ancestorConfig: `[source.crates-io]\nreplace-with = "private-registry"\n[source.private-registry]\nregistry = "https://example.test/index"`,
208
- },
209
- ]) {
210
- assert.throws(
211
- () => assertCargoOverrideFixture({
212
- manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
213
- ...fixture,
214
- }),
215
- /forbidden crates\.io source replacement/,
216
- );
217
- }
218
- });
219
-
220
- test("direct Cargo dependency contract accepts only published exact RightKit pins", () => {
221
- const published = new Map([
222
- ["rightkit-license", "0.1.2"],
223
- ["rightkit-logs", "0.1.0"],
224
- ["rightkit-tauri", "0.1.0"],
225
- ]);
226
- const manifest = `
227
- [ package ]
228
- name = "rightkit-tauri"
229
- # rightkit-tauri = "=0.1.0"
230
-
231
- [ dependencies ]
232
- "rightkit-license" = "=0.1.2" # published exact pin
233
- "rightkit-tauri" = "=0.1.0"
234
-
235
- [ target . 'cfg(windows)' . dependencies . "rightkit-logs" ]
236
- version = "=0.1.0"
237
-
238
- [ target . 'cfg(unix)' . dev-dependencies ]
239
- license-adapter = { package = "rightkit-license", version = "=0.1.2" }
240
- `;
241
-
242
- assert.equal(assertCargoFixture(manifest, published, "fixture/Cargo.toml"), 4);
243
- });
244
-
245
- test("direct Cargo dependency contract rejects staged-only RightKit crates", () => {
246
- const { consumer } = resolveCargoVersionContract(
247
- {
248
- cargo: { "rightkit-license": "0.1.2" },
249
- stagedCargo: { "rightkit-tauri": "0.1.0" },
250
- },
251
- new Map([
252
- ["rightkit-license", "0.1.2"],
253
- ["rightkit-tauri", "0.1.0"],
254
- ]),
255
- );
256
- assert.equal(consumer.has("rightkit-tauri"), false);
257
- assert.throws(
258
- () => assertCargoFixture(
259
- `dependencies . "rightkit-tauri" = "=0.1.0" # staged only`,
260
- consumer,
261
- "fixture/Cargo.toml",
262
- ),
263
- /fixture\/Cargo\.toml rightkit-tauri is not a published RightKit crate/,
264
- );
265
- });
266
-
267
- test("direct Cargo dependency contract still rejects path, Git, and custom registry sources", () => {
268
- const published = new Map([
269
- ["rightkit-license", "0.1.1"],
270
- ["rightkit-logs", "0.1.0"],
271
- ]);
272
- for (const manifest of [
273
- `dependencies . rightkit-license = { path = "../rightkit-license" }`,
274
- `target . 'cfg(windows)' . dependencies . "rightkit-logs" = { git = "https://example.test/rightkit.git" }`,
275
- `dependencies . rightkit-license = { version = "=0.1.1", registry = "private" }`,
276
- ]) {
277
- assert.throws(
278
- () => assertCargoFixture(manifest, published, "fixture/Cargo.toml"),
279
- /must use exact crates\.io versions|must use the exact crates\.io version/,
280
- );
281
- }
282
- });
283
-
284
- test("Cargo version contract keeps staged versions out of consumer pins", () => {
285
- const resolved = resolveCargoVersionContract(
286
- {
287
- cargo: { "rightkit-license": "0.1.1" },
288
- stagedCargo: { "rightkit-license": "0.1.2" },
289
- },
290
- new Map([["rightkit-license", "0.1.2"]]),
291
- );
292
-
293
- assert.equal(resolved.consumer.get("rightkit-license"), "0.1.1");
294
- assert.equal(resolved.canonical.get("rightkit-license"), "0.1.2");
295
- });
296
-
297
- test("Cargo version contract rejects unknown staged crates", () => {
298
- assert.throws(
299
- () => resolveCargoVersionContract(
300
- { cargo: {}, stagedCargo: { "rightkit-unknown": "0.1.0" } },
301
- new Map(),
302
- ),
303
- /unknown staged Cargo crate: rightkit-unknown/,
304
- );
305
- });
306
-
307
- test("Cargo version contract rejects staged versions that mismatch canonical manifests", () => {
308
- assert.throws(
309
- () => resolveCargoVersionContract(
310
- { cargo: { "rightkit-license": "0.1.1" }, stagedCargo: { "rightkit-license": "0.1.3" } },
311
- new Map([["rightkit-license", "0.1.2"]]),
312
- ),
313
- /rightkit-license canonical manifest is 0\.1\.2, expected staged version 0\.1\.3/,
314
- );
315
- });
316
-
317
- test("RightKit exposes one current version manifest", () => {
318
- assert.equal(existsSync(versionsPath), true, "rightkit-versions.json must be the single current-version source");
319
- assert.match(versions.packageManager, /^pnpm@\d+\.\d+\.\d+$/);
320
- assert.equal(versions.npm["@rightkit/release"], "0.2.26");
321
- assert.equal(versions.npm["@rightkit/legal"], "0.2.0");
322
- assert.equal(versions.npm["@rightkit/license"], "0.1.5");
323
- assert.equal(versions.npm["@rightkit/logs"], "0.1.3");
324
- assert.equal(versions.npm["@rightkit/tauri"], "0.1.0");
325
- assert.equal(versions.npm["@rightkit/updates"], "0.2.3");
326
- assert.equal(versions.cargo["rightkit-license"], "0.1.2");
327
- assert.equal(versions.cargo["rightkit-logs"], "0.1.0");
328
- assert.equal(versions.cargo["rightkit-tauri"], "0.1.0");
329
- assert.deepEqual(versions.stagedCargo, { "rightkit-license": "0.1.3" });
330
- getCurrentCargoVersionContract();
331
- });
332
-
333
- test("license v2 public vector is identical at every portable consumer boundary", () => {
334
- const canonical = readFileSync(
335
- path.join(workspace, "tools/rightkit/crates/rightkit-license/test-vectors/license-v2.json"),
336
- "utf8",
337
- );
338
- for (const relativePath of [
339
- "tools/rightkit/packages/license/test-vectors/license-v2.json",
340
- `${siteRepoDir}/packages/api/src/licensing/test-vectors/license-v2.json`,
341
- "scraperight/tests/fixtures/license-v2.json",
342
- ]) {
343
- assert.equal(
344
- readFileSync(path.join(workspace, relativePath), "utf8"),
345
- canonical,
346
- `${relativePath} must be the canonical public license vector byte-for-byte`,
347
- );
348
- }
349
- });
350
-
351
- for (const app of apps) {
352
- test(`${app.key} follows the signed tiered Right Release contract`, async () => {
353
- const root = path.join(workspace, app.root);
354
- const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
355
- const rightKitDeps = { ...pkg.dependencies, ...pkg.devDependencies };
356
- for (const [name, specifier] of Object.entries(rightKitDeps).filter(([name]) => name.startsWith("@rightkit/"))) {
357
- assert.doesNotMatch(specifier, /^(?:git|file|link|workspace):|github/i, `${app.key} ${name} must come from the published npm package`);
358
- if (versions.npm[name]) assert.equal(specifier, versions.npm[name], `${app.key} ${name} must match rightkit-versions.json exactly`);
359
- }
360
- assert.equal(pkg.packageManager, versions.packageManager);
361
- assert.equal(pkg.devDependencies?.["@rightkit/release"], versions.npm["@rightkit/release"]);
362
- assert.equal(
363
- pkg.dependencies?.["@rightkit/updates"],
364
- versions.npm["@rightkit/updates"],
365
- `${app.key} must consume the exact published shared updater runtime`,
366
- );
367
- assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/right-release"));
368
- assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/rightkit/packages/release"));
369
- assert(!JSON.stringify(pkg).includes("git+https://github.com/adrdsouza/rightkit.git"));
370
- assert.equal(pkg.scripts["release:doctor"], "right-release doctor");
371
- assert.equal(pkg.scripts["release:mac"], undefined, "tierless release entry points are forbidden");
372
- assert.equal(pkg.scripts["release:win"], undefined, "tierless release entry points are forbidden");
373
- assert.equal(pkg.scripts["release:patch:mac"], "right-release --platform mac --tier patch");
374
- assert.equal(pkg.scripts["release:patch:win"], "right-release --platform win --tier patch");
375
- assert.equal(pkg.scripts["release:update:mac"], "right-release --platform mac --tier update");
376
- assert.equal(pkg.scripts["release:update:win"], "right-release --platform win --tier update");
377
- assert.equal(pkg.scripts["publish:patch:mac"], "right-release publish --platform mac --tier patch");
378
- assert.equal(pkg.scripts["publish:patch:win"], "right-release publish --platform win --tier patch");
379
- assert.equal(pkg.scripts["publish:update:mac"], "right-release publish --platform mac --tier update");
380
- assert.equal(pkg.scripts["publish:update:win"], "right-release publish --platform win --tier update");
381
- assert.equal(pkg.scripts["deps:check"], "right-release deps --check");
382
- assert.equal(pkg.scripts["deps:update"], "right-release deps --update");
383
- assert.ok(!Object.entries(pkg.scripts).some(([name, command]) => /^(?:release|publish):/i.test(name) && /unsigned|--no-sign/i.test(command)), `${app.key} release/publish commands must not expose an unsigned macOS DMG mode`);
384
- assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/right-release"), `${app.key} scripts must not depend on the parent Claude workspace`);
385
- assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/rightkit/packages/release"), `${app.key} scripts must not depend on the parent Claude workspace`);
386
-
387
- const config = (await import(`${pathToFileURL(path.join(root, "right-release.config.mjs"))}?contract=${Date.now()}`)).default;
388
- assert.equal(config.app, app.key);
389
- assert.ok(config.version);
390
- for (const platform of ["mac", "win"]) {
391
- const target = config.targets[platform];
392
- assert.equal(target.signed, true);
393
- assert.equal(target.upload, undefined, "generic uploads bypass tier manifest routing");
394
- assert.equal(target.publish.cmd, "right-release");
395
- assert.match(target.publish.args.join(" "), /^publish-update\b/);
396
- assert.ok(new Set(target.updater.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current updater R2 object key`);
397
- assert.ok(new Set(target.installer.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current installer R2 object key`);
398
- for (const installer of target.installer.artifacts) {
399
- assert.match(installer.key, /\/installers\/(mac|windows)\/current\//, `${app.key} ${platform} installers must replace the stable current R2 object`);
400
- }
401
- for (const updater of target.updater.artifacts) {
402
- assert.match(updater.key, /\/updates\/(mac|windows)\/current\//, `${app.key} ${platform} updaters must replace the stable current R2 object`);
403
- }
404
- }
405
- assert.equal(config.targets.mac.package.cmd, "pnpm", `${app.key} must use the shared pnpm package entry point`);
406
- assert.deepEqual(config.targets.mac.package.args, ["run", "mac:dmg:notarized"], `${app.key} R2 release must use the signed and notarized macOS package entry point`);
407
- for (const installer of config.targets.mac.installer.artifacts) {
408
- assert.equal(path.dirname(installer.file), ".", `${app.key} macOS installer must be copied to the app package root before upload`);
409
- }
410
- assert.ok(config.targets.win.sign.files.length);
411
- const winUpdaterFiles = new Set(config.targets.win.updater.artifacts.map((artifact) => artifact.file));
412
- for (const signed of config.targets.win.sign.files) assert.ok(winUpdaterFiles.has(signed), `${signed} must be both Azure-signed and updater-signed`);
413
-
414
- const tauri = JSON.parse(readFileSync(path.join(root, app.tauri), "utf8"));
415
- assert.equal(tauri.plugins.updater.pubkey, pubkey);
416
- assert.deepEqual(tauri.plugins.updater.endpoints, [
417
- `https://api.spoares.com/v1/apps/${app.key}/releases/latest.json?platform={{target}}`,
418
- ]);
419
- assert.equal(tauri.bundle.createUpdaterArtifacts, true);
420
-
421
- const { consumer } = getCurrentCargoVersionContract();
422
- validateRightKitCargoContract(root, consumer, app.key);
423
-
424
- for (const localCopy of [
425
- "src-tauri/vendor/rightkit-license",
426
- "src-tauri/vendor/rightkit-logs",
427
- "crates/rightkit-license",
428
- ]) {
429
- assert.equal(
430
- existsSync(path.join(root, localCopy)),
431
- false,
432
- `${app.key} must not carry an app-local ${localCopy} copy`,
433
- );
434
- }
435
-
436
- const repoRoot = path.join(workspace, app.repoRoot ?? app.root);
437
- for (const packagePath of findFiles(repoRoot, "package.json")) {
438
- const candidate = JSON.parse(readFileSync(packagePath, "utf8"));
439
- assert.equal(candidate.scripts?.["release:win"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless Windows release script`);
440
- assert.equal(candidate.scripts?.["release:mac"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless macOS release script`);
441
- for (const command of Object.values(candidate.scripts ?? {})) {
442
- assert.doesNotMatch(command, /\brelease:(?:win|mac)\b/, `${path.relative(workspace, packagePath)} delegates to a forbidden tierless release command`);
443
- }
444
- }
445
- for (const instructionName of ["AGENTS.md", "CLAUDE.md"]) {
446
- const instructionPath = path.join(repoRoot, instructionName);
447
- if (!existsSync(instructionPath)) continue;
448
- const instruction = readFileSync(instructionPath, "utf8");
449
- assert.doesNotMatch(instruction, /pnpm(?: run)? release:(?:win|mac)\b/, `${app.key} ${instructionName} documents a forbidden tierless release`);
450
- assert.doesNotMatch(instruction, /shared tooling at [`']?\.\.\/tools\/right-release/i, `${app.key} ${instructionName} documents a sibling source dependency`);
451
- assert.doesNotMatch(instruction, /\$env:RIGHTAPPS_ADMIN_TOKEN|pnpm publish:r2/, `${app.key} ${instructionName} documents obsolete release credentials or publishers`);
452
- }
453
- for (const releaseFile of app.releaseFiles) {
454
- const source = readFileSync(path.join(root, releaseFile), "utf8");
455
- assert.doesNotMatch(source, /(?:\.\.\/)+tools\/right-release|tools\/right-release\//, `${app.key} ${releaseFile} must consume the installed package`);
456
- assert.match(source, /right-release["']?,?\s*["']mirror-root-artifact|right-release mirror-root-artifact/, `${app.key} ${releaseFile} must mirror the final DMG to the canonical package root`);
457
- }
458
- });
459
- }
460
-
461
- test("HeardRight and ScrapeRight expose one locked ASR promotion adapter contract", async () => {
462
- const heard = (await import(`${pathToFileURL(path.join(workspace, "heardright/tauri-app-next/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
463
- const scrape = (await import(`${pathToFileURL(path.join(workspace, "scraperight/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
464
- assert.equal(assertAsrAdapterPair(heard.runtimeArtifacts?.asr, scrape.runtimeArtifacts?.asr), true);
465
- });
466
-
467
- function findFiles(root, filename) {
468
- const found = [];
469
- const visit = (dir) => {
470
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
471
- if (entry.isDirectory() && [".audit", ".cache", ".git", ".claude", ".worktrees", "node_modules", "target", "vendor"].includes(entry.name)) continue;
472
- const full = path.join(dir, entry.name);
473
- if (entry.isDirectory()) visit(full);
474
- else if (entry.isFile() && entry.name === filename) found.push(full);
475
- }
476
- };
477
- visit(root);
478
- return found;
479
- }
480
-
481
- function readCanonicalCrateVersions() {
482
- const crateRoot = path.join(workspace, "tools/rightkit/crates");
483
- return new Map(
484
- readdirSync(crateRoot, { withFileTypes: true })
485
- .filter((entry) => entry.isDirectory() && existsSync(path.join(crateRoot, entry.name, "Cargo.toml")))
486
- .map((entry) => {
487
- const manifest = readFileSync(path.join(crateRoot, entry.name, "Cargo.toml"), "utf8");
488
- const version = manifest.match(/^version\s*=\s*"([^"]+)"$/m)?.[1];
489
- assert.ok(version, `${entry.name} canonical manifest must declare a package version`);
490
- return [entry.name, version];
491
- }),
492
- );
493
- }
494
-
495
- test("Right Suite has no hosted workflow files", () => {
496
- for (const root of ["viewright", "scraperight", "heardright", "mailright", "coderight", "genright", "voiceright", "tools/rightkit"]) {
497
- const workflowDir = path.join(workspace, root, ".github", "workflows");
498
- const workflows = existsSync(workflowDir) ? readdirSync(workflowDir) : [];
499
- assert.deepEqual(workflows, [], `${root} must not contain hosted workflow files`);
500
- }
501
- });
502
-
503
- test("RightApps brand hosts expose app-keyed update manifest proxies", () => {
504
- for (const app of apps) {
505
- const siteRoot = path.join(workspace, siteRepoDir, app.key);
506
- for (const route of ["patches", "latest"]) {
507
- const routeFile = path.join(siteRoot, "src", "routes", "releases", `${route}.json`, "index.ts");
508
- const source = readFileSync(routeFile, "utf8");
509
- assert.match(source, new RegExp(`APP_KEY\\s*=\\s*["']${app.key}["']`), `${app.key} ${route}.json proxy must set the app key`);
510
- assert.match(source, /RIGHTAPPS_API_URL/, `${app.key} ${route}.json proxy must use the configurable RightApps API base`);
511
- assert.match(source, /x-app-key/i, `${app.key} ${route}.json proxy must forward the app key header`);
512
- }
513
- }
514
- });
1
+ import assert from "node:assert/strict";
2
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+ import { pathToFileURL } from "node:url";
7
+ import test, { after } from "node:test";
8
+ import {
9
+ assertNoRightKitCargoOverrides,
10
+ assertPublishedRightKitCargoDependencies,
11
+ validateRightKitCargoContract,
12
+ } from "./cargo-contract.mjs";
13
+ import { assertAsrAdapterPair } from "./asr-artifact-adoption.mjs";
14
+
15
+ const workspace = path.resolve(new URL("../../../..", import.meta.url).pathname.replace(/^\/(\w:)/, "$1"));
16
+ // The Right Suite web layer's repo + filesystem path is `rightsites` post the 2026-07-15 naming lock;
17
+ // a not-yet-renamed checkout may still have `rightapps`. Resolve whichever exists so the contract
18
+ // passes on both. (The runtime service namespace stays `rightapps` — that is deliberately untouched.)
19
+ const siteRepoDir = existsSync(path.join(workspace, "rightsites")) ? "rightsites" : "rightapps";
20
+ const versionsPath = path.join(path.dirname(new URL(import.meta.url).pathname.replace(/^\/(\w:)/, "$1")), "rightkit-versions.json");
21
+ const versions = JSON.parse(readFileSync(versionsPath, "utf8"));
22
+ const isolatedCargoHome = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-home-"));
23
+ after(() => rmSync(isolatedCargoHome, { recursive: true, force: true }));
24
+ const pubkey = "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDI5Mzk1RjlGRjQ2NjI2MUQKUldRZEptYjBuMTg1S1VSUXlBdFM4WmtzaHArYko0U2hRMDVlSDJmSExVZG82Q0hoQ2srUlhqanAK";
25
+ const apps = [
26
+ { key: "viewright", root: "viewright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/build-mac-notarized.sh"] },
27
+ { key: "scraperight", root: "scraperight", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["package.sh"] },
28
+ { key: "heardright", root: "heardright/tauri-app-next", repoRoot: "heardright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs", "scripts/publish-release.mjs"] },
29
+ // mac-dmg.mjs is the release file, as in HeardRight/CodeRight. build-mac.sh only delegates to it,
30
+ // so asserting the mirror call against the wrapper failed a pipeline that does mirror.
31
+ { key: "mailright", root: "mailright", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
32
+ { key: "coderight", root: "coderight/apps/coderight-tauri", tauri: "src-tauri/tauri.conf.json", releaseFiles: ["scripts/mac-dmg.mjs"] },
33
+ ];
34
+
35
+ function resolveCargoVersionContract(versionManifest, canonicalVersions) {
36
+ const consumer = new Map(Object.entries(versionManifest.cargo ?? {}));
37
+ const staged = new Map(Object.entries(versionManifest.stagedCargo ?? {}));
38
+ const canonical = new Map();
39
+
40
+ for (const [crate, version] of staged) {
41
+ if (!canonicalVersions.has(crate)) throw new Error(`unknown staged Cargo crate: ${crate}`);
42
+ const actual = canonicalVersions.get(crate);
43
+ if (actual !== version) {
44
+ throw new Error(`${crate} canonical manifest is ${actual}, expected staged version ${version}`);
45
+ }
46
+ canonical.set(crate, version);
47
+ }
48
+
49
+ for (const [crate, version] of consumer) {
50
+ if (!canonicalVersions.has(crate)) throw new Error(`unknown published Cargo crate: ${crate}`);
51
+ const expected = staged.get(crate) ?? version;
52
+ const actual = canonicalVersions.get(crate);
53
+ if (actual !== expected) {
54
+ const source = staged.has(crate) ? "staged" : "published";
55
+ throw new Error(`${crate} canonical manifest is ${actual}, expected ${source} version ${expected}`);
56
+ }
57
+ canonical.set(crate, expected);
58
+ }
59
+
60
+ return { canonical, consumer };
61
+ }
62
+
63
+ let currentCargoVersionContract;
64
+ function getCurrentCargoVersionContract() {
65
+ currentCargoVersionContract ??= resolveCargoVersionContract(versions, readCanonicalCrateVersions());
66
+ return currentCargoVersionContract;
67
+ }
68
+
69
+ const cargoContractCache = new Map();
70
+ function readCargoManifestContract(manifestPath, label) {
71
+ const cacheKey = path.resolve(manifestPath).toLowerCase();
72
+ if (cargoContractCache.has(cacheKey)) return cargoContractCache.get(cacheKey);
73
+ const result = spawnSync(
74
+ "cargo",
75
+ ["metadata", "--no-deps", "--offline", "--format-version", "1", "--manifest-path", manifestPath],
76
+ {
77
+ cwd: path.dirname(manifestPath),
78
+ encoding: "utf8",
79
+ env: { ...process.env, CARGO_HOME: isolatedCargoHome },
80
+ windowsHide: true,
81
+ },
82
+ );
83
+ assert.equal(
84
+ result.status,
85
+ 0,
86
+ `${label} Cargo metadata rejected manifest; RightKit dependencies must use exact crates.io versions: ${String(result.stderr ?? "").trim()}`,
87
+ );
88
+ const metadata = JSON.parse(result.stdout);
89
+ const expectedPath = path.resolve(manifestPath).toLowerCase();
90
+ const pkg = metadata.packages.find(({ manifest_path: candidate }) => path.resolve(candidate).toLowerCase() === expectedPath);
91
+ if (!pkg && path.resolve(metadata.workspace_root, "Cargo.toml").toLowerCase() === expectedPath) {
92
+ const contract = { dependencies: [], workspaceRoot: path.resolve(metadata.workspace_root) };
93
+ cargoContractCache.set(cacheKey, contract);
94
+ return contract;
95
+ }
96
+ assert.ok(pkg, `${label} was not returned by Cargo metadata`);
97
+ const contract = { dependencies: pkg.dependencies, workspaceRoot: path.resolve(metadata.workspace_root) };
98
+ cargoContractCache.set(cacheKey, contract);
99
+ return contract;
100
+ }
101
+
102
+ function assertCargoFixture(manifest, published, label) {
103
+ const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-contract-"));
104
+ const manifestPath = path.join(fixtureRoot, "Cargo.toml");
105
+ const packageMetadata = /^\s*\[\s*package\s*\]/m.test(manifest)
106
+ ? ""
107
+ : '\n[package]\nname = "rightkit-contract-fixture"\nversion = "0.0.0"\nedition = "2021"\n';
108
+ writeFileSync(manifestPath, `${manifest}${packageMetadata}\n[lib]\npath = "fixture.rs"\n`, "utf8");
109
+ writeFileSync(path.join(fixtureRoot, "fixture.rs"), "", "utf8");
110
+ try {
111
+ return assertPublishedRightKitCargoDependencies(
112
+ readCargoManifestContract(manifestPath, label).dependencies,
113
+ published,
114
+ label,
115
+ );
116
+ } finally {
117
+ rmSync(fixtureRoot, { recursive: true, force: true });
118
+ }
119
+ }
120
+
121
+ function assertCargoOverrideFixture({ manifest, workspaceManifest, localConfig, ancestorConfig, outsideConfig }) {
122
+ const fixtureRoot = mkdtempSync(path.join(tmpdir(), "rightkit-cargo-override-"));
123
+ const repoRoot = path.join(fixtureRoot, "repo");
124
+ const appRoot = path.join(repoRoot, "app");
125
+ mkdirSync(appRoot, { recursive: true });
126
+ const manifestPath = path.join(appRoot, "Cargo.toml");
127
+ writeFileSync(manifestPath, manifest, "utf8");
128
+ if (workspaceManifest) writeFileSync(path.join(repoRoot, "Cargo.toml"), workspaceManifest, "utf8");
129
+ for (const [root, filename, source] of [
130
+ [appRoot, "config", localConfig],
131
+ [repoRoot, "config.toml", ancestorConfig],
132
+ [fixtureRoot, "config.toml", outsideConfig],
133
+ ]) {
134
+ if (!source) continue;
135
+ const cargoDir = path.join(root, ".cargo");
136
+ mkdirSync(cargoDir, { recursive: true });
137
+ writeFileSync(path.join(cargoDir, filename), source, "utf8");
138
+ }
139
+ try {
140
+ assertNoRightKitCargoOverrides(manifestPath, repoRoot, "fixture/Cargo.toml");
141
+ if (workspaceManifest) {
142
+ assertNoRightKitCargoOverrides(path.join(repoRoot, "Cargo.toml"), repoRoot, "fixture/workspace Cargo.toml");
143
+ }
144
+ return 0;
145
+ } finally {
146
+ rmSync(fixtureRoot, { recursive: true, force: true });
147
+ }
148
+ }
149
+
150
+ test("Cargo override contract accepts exact registry pins without repo-local overrides", () => {
151
+ assert.equal(assertCargoOverrideFixture({
152
+ manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
153
+ localConfig: `[net]\nretry = 2\n[registries.private]\nindex = "https://example.test/index"`,
154
+ outsideConfig: `[source.crates-io]\nreplace-with = "user-global-vendor"`,
155
+ }), 0);
156
+ });
157
+
158
+ test("Cargo override contract rejects RightKit patches and replacements in repo-local Cargo config", () => {
159
+ for (const config of [
160
+ { localConfig: `[patch.crates-io]\nrightkit-license = { path = "../rightkit-license" }` },
161
+ { localConfig: `patch . "https://github.com/rust-lang/crates.io-index" . "rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }` },
162
+ { localConfig: `[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }` },
163
+ { ancestorConfig: `[patch.private-source]\nadapter = { package = "rightkit-license", registry = "private" }` },
164
+ ]) {
165
+ assert.throws(
166
+ () => assertCargoOverrideFixture({
167
+ manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
168
+ ...config,
169
+ }),
170
+ /forbidden RightKit Cargo override/,
171
+ );
172
+ }
173
+ });
174
+
175
+ test("Cargo override contract rejects path patches, Git patches, and replace entries", () => {
176
+ for (const manifest of [
177
+ `patch . "crates-io" . "rightkit-license" = { path = "../rightkit-license" } # dotted path patch`,
178
+ `[ patch . "https://github.com/rust-lang/crates.io-index" ]\n"rightkit-logs" = { git = "https://example.test/rightkit-logs.git" }`,
179
+ `[ replace ]\n"rightkit-license:0.1.1" = { path = "../rightkit-license" }`,
180
+ ]) {
181
+ assert.throws(
182
+ () => assertCargoOverrideFixture({ manifest }),
183
+ /forbidden RightKit Cargo override/,
184
+ );
185
+ }
186
+ });
187
+
188
+ test("Cargo override contract rejects workspace-root patches inherited by a member", () => {
189
+ assert.throws(
190
+ () => assertCargoOverrideFixture({
191
+ manifest: `[package]\nname = "fixture"\nversion = "0.0.0"`,
192
+ workspaceManifest: `[workspace]\nmembers = ["app"]\n[patch.crates-io]\nrightkit-license = { path = "patched/rightkit-license" }`,
193
+ }),
194
+ /forbidden RightKit Cargo override/,
195
+ );
196
+ });
197
+
198
+ test("Cargo override contract rejects local and repo-ancestor crates.io source replacement", () => {
199
+ for (const fixture of [
200
+ {
201
+ localConfig: `source . crates-io . replace-with = "vendored-sources"\n[source.vendored-sources]\ndirectory = "vendor"`,
202
+ },
203
+ {
204
+ ancestorConfig: `[source."crates-io"]\nreplace-with = "rightkit-git"\n[source.rightkit-git]\ngit = "https://example.test/rightkit-index.git"`,
205
+ },
206
+ {
207
+ ancestorConfig: `[source.crates-io]\nreplace-with = "private-registry"\n[source.private-registry]\nregistry = "https://example.test/index"`,
208
+ },
209
+ ]) {
210
+ assert.throws(
211
+ () => assertCargoOverrideFixture({
212
+ manifest: `[package]\nname = "fixture"\nversion = "0.0.0"\n[dependencies]\nrightkit-license = "=0.1.1"`,
213
+ ...fixture,
214
+ }),
215
+ /forbidden crates\.io source replacement/,
216
+ );
217
+ }
218
+ });
219
+
220
+ test("direct Cargo dependency contract accepts only published exact RightKit pins", () => {
221
+ const published = new Map([
222
+ ["rightkit-license", "0.1.2"],
223
+ ["rightkit-logs", "0.1.0"],
224
+ ["rightkit-tauri", "0.1.0"],
225
+ ]);
226
+ const manifest = `
227
+ [ package ]
228
+ name = "rightkit-tauri"
229
+ # rightkit-tauri = "=0.1.0"
230
+
231
+ [ dependencies ]
232
+ "rightkit-license" = "=0.1.2" # published exact pin
233
+ "rightkit-tauri" = "=0.1.0"
234
+
235
+ [ target . 'cfg(windows)' . dependencies . "rightkit-logs" ]
236
+ version = "=0.1.0"
237
+
238
+ [ target . 'cfg(unix)' . dev-dependencies ]
239
+ license-adapter = { package = "rightkit-license", version = "=0.1.2" }
240
+ `;
241
+
242
+ assert.equal(assertCargoFixture(manifest, published, "fixture/Cargo.toml"), 4);
243
+ });
244
+
245
+ test("direct Cargo dependency contract rejects staged-only RightKit crates", () => {
246
+ const { consumer } = resolveCargoVersionContract(
247
+ {
248
+ cargo: { "rightkit-license": "0.1.2" },
249
+ stagedCargo: { "rightkit-tauri": "0.1.0" },
250
+ },
251
+ new Map([
252
+ ["rightkit-license", "0.1.2"],
253
+ ["rightkit-tauri", "0.1.0"],
254
+ ]),
255
+ );
256
+ assert.equal(consumer.has("rightkit-tauri"), false);
257
+ assert.throws(
258
+ () => assertCargoFixture(
259
+ `dependencies . "rightkit-tauri" = "=0.1.0" # staged only`,
260
+ consumer,
261
+ "fixture/Cargo.toml",
262
+ ),
263
+ /fixture\/Cargo\.toml rightkit-tauri is not a published RightKit crate/,
264
+ );
265
+ });
266
+
267
+ test("direct Cargo dependency contract still rejects path, Git, and custom registry sources", () => {
268
+ const published = new Map([
269
+ ["rightkit-license", "0.1.1"],
270
+ ["rightkit-logs", "0.1.0"],
271
+ ]);
272
+ for (const manifest of [
273
+ `dependencies . rightkit-license = { path = "../rightkit-license" }`,
274
+ `target . 'cfg(windows)' . dependencies . "rightkit-logs" = { git = "https://example.test/rightkit.git" }`,
275
+ `dependencies . rightkit-license = { version = "=0.1.1", registry = "private" }`,
276
+ ]) {
277
+ assert.throws(
278
+ () => assertCargoFixture(manifest, published, "fixture/Cargo.toml"),
279
+ /must use exact crates\.io versions|must use the exact crates\.io version/,
280
+ );
281
+ }
282
+ });
283
+
284
+ test("Cargo version contract keeps staged versions out of consumer pins", () => {
285
+ const resolved = resolveCargoVersionContract(
286
+ {
287
+ cargo: { "rightkit-license": "0.1.1" },
288
+ stagedCargo: { "rightkit-license": "0.1.2" },
289
+ },
290
+ new Map([["rightkit-license", "0.1.2"]]),
291
+ );
292
+
293
+ assert.equal(resolved.consumer.get("rightkit-license"), "0.1.1");
294
+ assert.equal(resolved.canonical.get("rightkit-license"), "0.1.2");
295
+ });
296
+
297
+ test("Cargo version contract rejects unknown staged crates", () => {
298
+ assert.throws(
299
+ () => resolveCargoVersionContract(
300
+ { cargo: {}, stagedCargo: { "rightkit-unknown": "0.1.0" } },
301
+ new Map(),
302
+ ),
303
+ /unknown staged Cargo crate: rightkit-unknown/,
304
+ );
305
+ });
306
+
307
+ test("Cargo version contract rejects staged versions that mismatch canonical manifests", () => {
308
+ assert.throws(
309
+ () => resolveCargoVersionContract(
310
+ { cargo: { "rightkit-license": "0.1.1" }, stagedCargo: { "rightkit-license": "0.1.3" } },
311
+ new Map([["rightkit-license", "0.1.2"]]),
312
+ ),
313
+ /rightkit-license canonical manifest is 0\.1\.2, expected staged version 0\.1\.3/,
314
+ );
315
+ });
316
+
317
+ test("RightKit exposes one current version manifest", () => {
318
+ assert.equal(existsSync(versionsPath), true, "rightkit-versions.json must be the single current-version source");
319
+ assert.match(versions.packageManager, /^pnpm@\d+\.\d+\.\d+$/);
320
+ assert.equal(versions.npm["@rightkit/release"], "0.2.26");
321
+ assert.equal(versions.npm["@rightkit/legal"], "0.2.0");
322
+ assert.equal(versions.npm["@rightkit/license"], "0.1.5");
323
+ assert.equal(versions.npm["@rightkit/logs"], "0.1.3");
324
+ assert.equal(versions.npm["@rightkit/tauri"], "0.1.0");
325
+ assert.equal(versions.npm["@rightkit/updates"], "0.2.3");
326
+ assert.deepEqual(versions.stagedNpm, {
327
+ "@rightkit/legal": "0.3.0",
328
+ "@rightkit/legal-ui": "0.1.0",
329
+ "@rightkit/license": "0.1.6",
330
+ "@rightkit/release": "0.2.28",
331
+ });
332
+ const licensePackage = JSON.parse(readFileSync(
333
+ path.join(workspace, "tools/rightkit/packages/license/package.json"),
334
+ "utf8",
335
+ ));
336
+ assert.equal(licensePackage.version, versions.stagedNpm["@rightkit/license"]);
337
+ assert.equal(versions.cargo["rightkit-license"], "0.1.2");
338
+ assert.equal(versions.cargo["rightkit-logs"], "0.1.0");
339
+ assert.equal(versions.cargo["rightkit-tauri"], "0.1.0");
340
+ assert.deepEqual(versions.stagedCargo, {
341
+ "rightkit-license": "0.1.3",
342
+ "rightkit-tauri": "0.1.1",
343
+ });
344
+ getCurrentCargoVersionContract();
345
+ });
346
+
347
+ test("license v2 public vector is identical at every portable consumer boundary", () => {
348
+ const canonical = readFileSync(
349
+ path.join(workspace, "tools/rightkit/crates/rightkit-license/test-vectors/license-v2.json"),
350
+ "utf8",
351
+ );
352
+ for (const relativePath of [
353
+ "tools/rightkit/packages/license/test-vectors/license-v2.json",
354
+ `${siteRepoDir}/packages/api/src/licensing/test-vectors/license-v2.json`,
355
+ "scraperight/tests/fixtures/license-v2.json",
356
+ ]) {
357
+ assert.equal(
358
+ readFileSync(path.join(workspace, relativePath), "utf8"),
359
+ canonical,
360
+ `${relativePath} must be the canonical public license vector byte-for-byte`,
361
+ );
362
+ }
363
+ });
364
+
365
+ for (const app of apps) {
366
+ test(`${app.key} follows the signed tiered Right Release contract`, async () => {
367
+ const root = path.join(workspace, app.root);
368
+ const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
369
+ const rightKitDeps = { ...pkg.dependencies, ...pkg.devDependencies };
370
+ for (const [name, specifier] of Object.entries(rightKitDeps).filter(([name]) => name.startsWith("@rightkit/"))) {
371
+ assert.doesNotMatch(specifier, /^(?:git|file|link|workspace):|github/i, `${app.key} ${name} must come from the published npm package`);
372
+ const allowed = new Set([versions.npm[name], versions.stagedNpm?.[name]].filter(Boolean));
373
+ if (allowed.size) assert.ok(allowed.has(specifier), `${app.key} ${name} must match a published rollout version`);
374
+ }
375
+ assert.equal(pkg.packageManager, versions.packageManager);
376
+ assert.ok(new Set([versions.npm["@rightkit/release"], versions.stagedNpm?.["@rightkit/release"]]).has(pkg.devDependencies?.["@rightkit/release"]));
377
+ assert.equal(
378
+ pkg.dependencies?.["@rightkit/updates"],
379
+ versions.npm["@rightkit/updates"],
380
+ `${app.key} must consume the exact published shared updater runtime`,
381
+ );
382
+ assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/right-release"));
383
+ assert(!JSON.stringify(pkg).includes("github:adrdsouza/claude#main&path:/tools/rightkit/packages/release"));
384
+ assert(!JSON.stringify(pkg).includes("git+https://github.com/adrdsouza/rightkit.git"));
385
+ assert.equal(pkg.scripts["release:doctor"], "right-release doctor");
386
+ assert.equal(pkg.scripts["release:mac"], undefined, "tierless release entry points are forbidden");
387
+ assert.equal(pkg.scripts["release:win"], undefined, "tierless release entry points are forbidden");
388
+ assert.equal(pkg.scripts["release:patch:mac"], "right-release --platform mac --tier patch");
389
+ assert.equal(pkg.scripts["release:patch:win"], "right-release --platform win --tier patch");
390
+ assert.equal(pkg.scripts["release:update:mac"], "right-release --platform mac --tier update");
391
+ assert.equal(pkg.scripts["release:update:win"], "right-release --platform win --tier update");
392
+ assert.equal(pkg.scripts["publish:patch:mac"], "right-release publish --platform mac --tier patch");
393
+ assert.equal(pkg.scripts["publish:patch:win"], "right-release publish --platform win --tier patch");
394
+ assert.equal(pkg.scripts["publish:update:mac"], "right-release publish --platform mac --tier update");
395
+ assert.equal(pkg.scripts["publish:update:win"], "right-release publish --platform win --tier update");
396
+ assert.equal(pkg.scripts["deps:check"], "right-release deps --check");
397
+ assert.equal(pkg.scripts["deps:update"], "right-release deps --update");
398
+ assert.ok(!Object.entries(pkg.scripts).some(([name, command]) => /^(?:release|publish):/i.test(name) && /unsigned|--no-sign/i.test(command)), `${app.key} release/publish commands must not expose an unsigned macOS DMG mode`);
399
+ assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/right-release"), `${app.key} scripts must not depend on the parent Claude workspace`);
400
+ assert.ok(!JSON.stringify(pkg.scripts).includes("../tools/rightkit/packages/release"), `${app.key} scripts must not depend on the parent Claude workspace`);
401
+
402
+ const config = (await import(`${pathToFileURL(path.join(root, "right-release.config.mjs"))}?contract=${Date.now()}`)).default;
403
+ assert.equal(config.app, app.key);
404
+ assert.ok(config.version);
405
+ for (const platform of ["mac", "win"]) {
406
+ const target = config.targets[platform];
407
+ assert.equal(target.signed, true);
408
+ assert.equal(target.upload, undefined, "generic uploads bypass tier manifest routing");
409
+ assert.equal(target.publish.cmd, "right-release");
410
+ assert.match(target.publish.args.join(" "), /^publish-update\b/);
411
+ assert.ok(new Set(target.updater.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current updater R2 object key`);
412
+ assert.ok(new Set(target.installer.artifacts.map((artifact) => artifact.key)).size <= 1, `${app.key} ${platform} must expose at most one current installer R2 object key`);
413
+ for (const installer of target.installer.artifacts) {
414
+ assert.match(installer.key, /\/installers\/(mac|windows)\/current\//, `${app.key} ${platform} installers must replace the stable current R2 object`);
415
+ }
416
+ for (const updater of target.updater.artifacts) {
417
+ assert.match(updater.key, /\/updates\/(mac|windows)\/current\//, `${app.key} ${platform} updaters must replace the stable current R2 object`);
418
+ }
419
+ }
420
+ assert.equal(config.targets.mac.package.cmd, "pnpm", `${app.key} must use the shared pnpm package entry point`);
421
+ assert.deepEqual(config.targets.mac.package.args, ["run", "mac:dmg:notarized"], `${app.key} R2 release must use the signed and notarized macOS package entry point`);
422
+ for (const installer of config.targets.mac.installer.artifacts) {
423
+ assert.equal(path.dirname(installer.file), ".", `${app.key} macOS installer must be copied to the app package root before upload`);
424
+ }
425
+ assert.ok(config.targets.win.sign.files.length);
426
+ const winUpdaterFiles = new Set(config.targets.win.updater.artifacts.map((artifact) => artifact.file));
427
+ for (const signed of config.targets.win.sign.files) assert.ok(winUpdaterFiles.has(signed), `${signed} must be both Azure-signed and updater-signed`);
428
+
429
+ const tauri = JSON.parse(readFileSync(path.join(root, app.tauri), "utf8"));
430
+ assert.equal(tauri.plugins.updater.pubkey, pubkey);
431
+ assert.deepEqual(tauri.plugins.updater.endpoints, [
432
+ `https://api.spoares.com/v1/apps/${app.key}/releases/latest.json?platform={{target}}`,
433
+ ]);
434
+ assert.equal(tauri.bundle.createUpdaterArtifacts, true);
435
+
436
+ const { consumer, canonical } = getCurrentCargoVersionContract();
437
+ const rollout = new Map([...consumer].map(([name, version]) => [name, new Set([version, canonical.get(name)].filter(Boolean))]));
438
+ validateRightKitCargoContract(root, rollout, app.key);
439
+
440
+ for (const localCopy of [
441
+ "src-tauri/vendor/rightkit-license",
442
+ "src-tauri/vendor/rightkit-logs",
443
+ "crates/rightkit-license",
444
+ ]) {
445
+ assert.equal(
446
+ existsSync(path.join(root, localCopy)),
447
+ false,
448
+ `${app.key} must not carry an app-local ${localCopy} copy`,
449
+ );
450
+ }
451
+
452
+ const repoRoot = path.join(workspace, app.repoRoot ?? app.root);
453
+ for (const packagePath of findFiles(repoRoot, "package.json")) {
454
+ const candidate = JSON.parse(readFileSync(packagePath, "utf8"));
455
+ assert.equal(candidate.scripts?.["release:win"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless Windows release script`);
456
+ assert.equal(candidate.scripts?.["release:mac"], undefined, `${path.relative(workspace, packagePath)} has a forbidden tierless macOS release script`);
457
+ for (const command of Object.values(candidate.scripts ?? {})) {
458
+ assert.doesNotMatch(command, /\brelease:(?:win|mac)\b/, `${path.relative(workspace, packagePath)} delegates to a forbidden tierless release command`);
459
+ }
460
+ }
461
+ for (const instructionName of ["AGENTS.md", "CLAUDE.md"]) {
462
+ const instructionPath = path.join(repoRoot, instructionName);
463
+ if (!existsSync(instructionPath)) continue;
464
+ const instruction = readFileSync(instructionPath, "utf8");
465
+ assert.doesNotMatch(instruction, /pnpm(?: run)? release:(?:win|mac)\b/, `${app.key} ${instructionName} documents a forbidden tierless release`);
466
+ assert.doesNotMatch(instruction, /shared tooling at [`']?\.\.\/tools\/right-release/i, `${app.key} ${instructionName} documents a sibling source dependency`);
467
+ assert.doesNotMatch(instruction, /\$env:RIGHTAPPS_ADMIN_TOKEN|pnpm publish:r2/, `${app.key} ${instructionName} documents obsolete release credentials or publishers`);
468
+ }
469
+ for (const releaseFile of app.releaseFiles) {
470
+ const source = readFileSync(path.join(root, releaseFile), "utf8");
471
+ assert.doesNotMatch(source, /(?:\.\.\/)+tools\/right-release|tools\/right-release\//, `${app.key} ${releaseFile} must consume the installed package`);
472
+ assert.match(source, /right-release["']?,?\s*["']mirror-root-artifact|right-release mirror-root-artifact/, `${app.key} ${releaseFile} must mirror the final DMG to the canonical package root`);
473
+ }
474
+ });
475
+ }
476
+
477
+ test("HeardRight and ScrapeRight expose one locked ASR promotion adapter contract", async () => {
478
+ const heard = (await import(`${pathToFileURL(path.join(workspace, "heardright/tauri-app-next/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
479
+ const scrape = (await import(`${pathToFileURL(path.join(workspace, "scraperight/right-release.config.mjs"))}?asr=${Date.now()}`)).default;
480
+ assert.equal(assertAsrAdapterPair(heard.runtimeArtifacts?.asr, scrape.runtimeArtifacts?.asr), true);
481
+ });
482
+
483
+ function findFiles(root, filename) {
484
+ const found = [];
485
+ const visit = (dir) => {
486
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
487
+ if (entry.isDirectory() && [".audit", ".cache", ".git", ".claude", ".worktrees", "node_modules", "target", "vendor"].includes(entry.name)) continue;
488
+ const full = path.join(dir, entry.name);
489
+ if (entry.isDirectory()) visit(full);
490
+ else if (entry.isFile() && entry.name === filename) found.push(full);
491
+ }
492
+ };
493
+ visit(root);
494
+ return found;
495
+ }
496
+
497
+ function readCanonicalCrateVersions() {
498
+ const crateRoot = path.join(workspace, "tools/rightkit/crates");
499
+ return new Map(
500
+ readdirSync(crateRoot, { withFileTypes: true })
501
+ .filter((entry) => entry.isDirectory() && existsSync(path.join(crateRoot, entry.name, "Cargo.toml")))
502
+ .map((entry) => {
503
+ const manifest = readFileSync(path.join(crateRoot, entry.name, "Cargo.toml"), "utf8");
504
+ const version = manifest.match(/^version\s*=\s*"([^"]+)"$/m)?.[1];
505
+ assert.ok(version, `${entry.name} canonical manifest must declare a package version`);
506
+ return [entry.name, version];
507
+ }),
508
+ );
509
+ }
510
+
511
+ test("Right Suite has no hosted workflow files", () => {
512
+ for (const root of ["viewright", "scraperight", "heardright", "mailright", "coderight", "genright", "voiceright", "tools/rightkit"]) {
513
+ const workflowDir = path.join(workspace, root, ".github", "workflows");
514
+ const workflows = existsSync(workflowDir) ? readdirSync(workflowDir) : [];
515
+ assert.deepEqual(workflows, [], `${root} must not contain hosted workflow files`);
516
+ }
517
+ });
518
+
519
+ test("RightApps brand hosts expose app-keyed update manifest proxies", () => {
520
+ for (const app of apps) {
521
+ const siteRoot = path.join(workspace, siteRepoDir, app.key);
522
+ for (const route of ["patches", "latest"]) {
523
+ const routeFile = path.join(siteRoot, "src", "routes", "releases", `${route}.json`, "index.ts");
524
+ const source = readFileSync(routeFile, "utf8");
525
+ assert.match(source, new RegExp(`APP_KEY\\s*=\\s*["']${app.key}["']`), `${app.key} ${route}.json proxy must set the app key`);
526
+ assert.match(source, /RIGHTAPPS_API_URL/, `${app.key} ${route}.json proxy must use the configurable RightApps API base`);
527
+ assert.match(source, /x-app-key/i, `${app.key} ${route}.json proxy must forward the app key header`);
528
+ }
529
+ }
530
+ });