@rightkit/release 0.2.165 → 0.2.173

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.
Files changed (86) hide show
  1. package/README.md +121 -4
  2. package/addon-command.mjs +6 -13
  3. package/android-aab-scan.mjs +265 -0
  4. package/android-dev.mjs +111 -0
  5. package/android-ndk.mjs +77 -0
  6. package/android-play-upload.mjs +262 -0
  7. package/android-release.mjs +344 -0
  8. package/android-test-fixtures.mjs +79 -0
  9. package/apple-profile-create.mjs +363 -0
  10. package/bin/darwin/rightkit-swap +0 -0
  11. package/bin/darwin/rightkit-swap.sign.json +6 -0
  12. package/build-release.mjs +73 -13
  13. package/cargo-guard.mjs +2 -0
  14. package/cargo-profile-contract.mjs +183 -0
  15. package/cargo-target.mjs +8 -0
  16. package/cli/right-release.mjs +16 -4
  17. package/committed-source.mjs +1 -1
  18. package/dev-artifact-refresh.mjs +176 -0
  19. package/dev-artifact-support.mjs +61 -0
  20. package/development-signing.mjs +71 -4
  21. package/development.mjs +93 -47
  22. package/direct-bootstrap.mjs +26 -41
  23. package/disk-command.mjs +298 -5
  24. package/disk-policy.json +7 -5
  25. package/disk-policy.mjs +105 -16
  26. package/disk-stable-root.mjs +19 -16
  27. package/engine-locator.mjs +116 -0
  28. package/external-bin.mjs +133 -0
  29. package/github-release.mjs +2 -2
  30. package/github-updater-release.mjs +154 -0
  31. package/hardeningscan.mjs +1 -1
  32. package/in-place-install.mjs +56 -0
  33. package/install-app-windows.mjs +63 -0
  34. package/install-app.mjs +53 -23
  35. package/install-tauri-devid.mjs +172 -0
  36. package/inventory-check.mjs +1 -1
  37. package/local-publish.mjs +11 -1
  38. package/mac-package-recipe.mjs +304 -0
  39. package/mac-signing-matrix.mjs +23 -11
  40. package/managed-cargo.mjs +6 -0
  41. package/media-sidecar-catalog.mjs +45 -0
  42. package/media-sidecar.mjs +306 -0
  43. package/ownership-approval-command.mjs +10 -44
  44. package/ownership-approval.mjs +3 -42
  45. package/ownership-catalog-config.json +2 -1
  46. package/ownership-catalog.mjs +4 -2
  47. package/ownership-command.mjs +7 -9
  48. package/ownership-dependency-allowlist.json +25 -1
  49. package/ownership-evidence.mjs +8 -5
  50. package/ownership-git-inventory.mjs +41 -7
  51. package/ownership-lockfiles.mjs +91 -8
  52. package/ownership-mandatory-set.json +36 -16
  53. package/ownership-report.mjs +5 -6
  54. package/ownership-scan-worker.mjs +2 -2
  55. package/ownership-verdict.mjs +10 -7
  56. package/ownership.mjs +47 -29
  57. package/package-recipe-targets.mjs +95 -0
  58. package/package.json +7 -4
  59. package/portable-development.mjs +32 -115
  60. package/preflight.mjs +4 -6
  61. package/project-type.mjs +1 -1
  62. package/publication-artifacts.mjs +34 -0
  63. package/publish-update.mjs +72 -11
  64. package/qa-adoption-exemptions.json +5 -0
  65. package/qa-build-features.mjs +7 -0
  66. package/qa-contract.mjs +182 -0
  67. package/qa-control-scan.mjs +3 -3
  68. package/release-qa-command.mjs +38 -12
  69. package/release-qa-installed.mjs +136 -0
  70. package/release-qa-receipt.mjs +23 -2
  71. package/release.mjs +285 -14
  72. package/rightkit-ownership.json +537 -5
  73. package/rightkit-sync.mjs +27 -1
  74. package/rightkit-versions.json +111 -63
  75. package/runtime-budget-classes.json +28 -0
  76. package/runtime-budgets.mjs +4 -1
  77. package/sign-candidate.mjs +161 -0
  78. package/sign-dev-artifact.mjs +198 -0
  79. package/stage-binary.mjs +60 -0
  80. package/stage-sidecar-command.mjs +41 -0
  81. package/stage-sidecar.mjs +424 -0
  82. package/swap-helper-bundle.mjs +105 -0
  83. package/swift-mac-dmg.mjs +2 -1
  84. package/templates/cargo-profiles.toml +28 -0
  85. package/upload-release.mjs +11 -1
  86. package/win-package-recipe.mjs +321 -0
package/rightkit-sync.mjs CHANGED
@@ -10,7 +10,7 @@ import { fileURLToPath } from "node:url";
10
10
  const packageRoot = path.dirname(fileURLToPath(import.meta.url));
11
11
  const rightkitRoot = path.resolve(packageRoot, "..", "..");
12
12
  const VERSIONS_FILE = path.join(packageRoot, "rightkit-versions.json");
13
- const USER_AGENT = "rightkit-sync/1 (https://github.com/Orthic-Labs/rightkit)";
13
+ const USER_AGENT = "rightkit-sync/1 (https://github.com/bogusyogi/rightkit)";
14
14
 
15
15
  const field = (toml, key) => toml.match(new RegExp(`^${key}\\s*=\\s*"([^"]*)"`, "m"))?.[1] ?? null;
16
16
 
@@ -166,6 +166,32 @@ export async function syncRightkitVersions({ check = false, fetchImpl = fetch, f
166
166
  return { changes, unpublished, copies, written };
167
167
  }
168
168
 
169
+ /** Stage source versions into the feed BEFORE packing, so the rightkit-versions.json a tarball ships lists
170
+ * the very version it ships with (the feed is otherwise written after publish and lags by one release).
171
+ * Synchronous and offline: a unit below its staged version is skipped (never lowered); published pins stay
172
+ * allowed through the same retainPublished rule as stageVersion. Refreshes the consumer copies. */
173
+ export function stageSourceVersions(entries, { file = VERSIONS_FILE, root = rightkitRoot, log = (line) => process.stdout.write(`${line}\n`) } = {}) {
174
+ const versions = JSON.parse(readFileSync(file, "utf8"));
175
+ const next = structuredClone(versions); const changes = [];
176
+ for (const { registry, name, version } of entries) {
177
+ const [stagedKey] = versionKeys(registry);
178
+ if (typeof name !== "string" || !name.trim()) throw new Error("stageSourceVersions requires a package or crate name");
179
+ if (typeof version !== "string" || !SEMVER.test(version)) throw new Error(`invalid semver: ${version}`);
180
+ const current = next[stagedKey]?.[name] ?? next[registry]?.[name] ?? null;
181
+ if (current && compareVersions(version, current) <= 0) continue;
182
+ retainPublished(next, { registry, name, version }, [current, next.registry?.[registry]?.[name]], undefined);
183
+ next[stagedKey] ??= {};
184
+ next[stagedKey][name] = version;
185
+ next[stagedKey] = Object.fromEntries(Object.entries(next[stagedKey]).sort(([a], [b]) => a.localeCompare(b)));
186
+ changes.push({ registry, name, from: current, to: version });
187
+ }
188
+ const written = JSON.stringify(next) !== JSON.stringify(versions);
189
+ if (written) writeFileSync(file, `${JSON.stringify(next, null, 2)}\n`);
190
+ const copies = syncConsumerCopies(root);
191
+ for (const change of changes) log(`${change.registry} ${change.name}: ${change.from ?? "unlisted"} -> ${change.to} (staged before pack)`);
192
+ return { changes, copies, written };
193
+ }
194
+
169
195
  /** Record one just-published version (the registry index can lag the upload) and refresh the copies.
170
196
  * Called by right-release after a verified cargo or npm publish; never fails the publish itself unless `strict` is set. */
171
197
  export function recordPublished({ registry, name, version }, { file = VERSIONS_FILE, root = rightkitRoot, log = (line) => process.stdout.write(`${line}\n`), strict = false } = {}) {
@@ -15,27 +15,27 @@
15
15
  "stagedNpm": {
16
16
  "@rightkit/app-update": "0.2.5",
17
17
  "@rightkit/ax": "0.3.2",
18
- "@rightkit/ci": "0.2.45",
18
+ "@rightkit/ci": "0.2.49",
19
19
  "@rightkit/doc-render": "0.1.6",
20
20
  "@rightkit/hooks": "0.1.2",
21
- "@rightkit/i18n": "0.1.0",
22
- "@rightkit/legal": "0.3.1",
23
- "@rightkit/legal-ui": "0.2.2",
21
+ "@rightkit/i18n": "0.1.1",
22
+ "@rightkit/legal": "0.5.0",
23
+ "@rightkit/legal-ui": "0.3.0",
24
24
  "@rightkit/license": "0.2.0",
25
25
  "@rightkit/logs": "0.1.4",
26
26
  "@rightkit/media-ui": "0.3.4",
27
- "@rightkit/onboarding": "0.3.3",
27
+ "@rightkit/onboarding": "0.5.0",
28
28
  "@rightkit/outdated": "0.2.0",
29
- "@rightkit/pdf-ui": "0.1.6",
29
+ "@rightkit/pdf-ui": "0.1.8",
30
30
  "@rightkit/platform-ui": "0.2.8",
31
- "@rightkit/qa": "0.4.8",
32
- "@rightkit/qa-chrome": "0.1.6",
33
- "@rightkit/react-shell": "0.6.4",
34
- "@rightkit/release": "0.2.164",
35
- "@rightkit/settings-ui": "0.4.4",
31
+ "@rightkit/qa": "0.4.9",
32
+ "@rightkit/qa-chrome": "0.1.8",
33
+ "@rightkit/react-shell": "0.6.8",
34
+ "@rightkit/release": "0.2.173",
35
+ "@rightkit/settings-ui": "0.5.0",
36
36
  "@rightkit/tauri": "0.2.1",
37
37
  "@rightkit/tauri-shell": "0.1.1",
38
- "@rightkit/theme": "0.2.3"
38
+ "@rightkit/theme": "0.2.4"
39
39
  },
40
40
  "legacyNpm": {
41
41
  "@rightkit/ax": [
@@ -92,14 +92,16 @@
92
92
  "0.1.2",
93
93
  "0.1.3",
94
94
  "0.2.0",
95
- "0.2.1"
95
+ "0.2.1",
96
+ "0.2.2"
96
97
  ],
97
98
  "@rightkit/hooks": [
98
99
  "0.1.0",
99
100
  "0.1.1"
100
101
  ],
101
102
  "@rightkit/legal": [
102
- "0.3.0"
103
+ "0.3.0",
104
+ "0.3.1"
103
105
  ],
104
106
  "@rightkit/license": [
105
107
  "0.1.6",
@@ -205,7 +207,10 @@
205
207
  "0.2.160",
206
208
  "0.2.161",
207
209
  "0.2.162",
208
- "0.2.163"
210
+ "0.2.163",
211
+ "0.2.164",
212
+ "0.2.165",
213
+ "0.2.172"
209
214
  ],
210
215
  "@rightkit/qa": [
211
216
  "0.1.0",
@@ -224,7 +229,8 @@
224
229
  "0.4.4",
225
230
  "0.4.5",
226
231
  "0.4.6",
227
- "0.4.7"
232
+ "0.4.7",
233
+ "0.4.8"
228
234
  ],
229
235
  "@rightkit/app-shell": [
230
236
  "0.1.0",
@@ -256,7 +262,8 @@
256
262
  "0.1.0",
257
263
  "0.2.0",
258
264
  "0.2.1",
259
- "0.2.2"
265
+ "0.2.2",
266
+ "0.2.3"
260
267
  ],
261
268
  "@rightkit/settings-ui": [
262
269
  "0.1.0",
@@ -275,7 +282,8 @@
275
282
  "0.4.0",
276
283
  "0.4.1",
277
284
  "0.4.2",
278
- "0.4.3"
285
+ "0.4.3",
286
+ "0.4.4"
279
287
  ],
280
288
  "@rightkit/onboarding": [
281
289
  "0.1.0",
@@ -285,7 +293,8 @@
285
293
  "0.2.3",
286
294
  "0.3.0",
287
295
  "0.3.1",
288
- "0.3.2"
296
+ "0.3.2",
297
+ "0.3.3"
289
298
  ],
290
299
  "@rightkit/doc-render": [
291
300
  "0.1.0",
@@ -313,7 +322,8 @@
313
322
  "0.1.2",
314
323
  "0.1.3",
315
324
  "0.1.4",
316
- "0.1.5"
325
+ "0.1.5",
326
+ "0.1.6"
317
327
  ],
318
328
  "@rightkit/qa-chrome": [
319
329
  "0.1.0",
@@ -321,7 +331,8 @@
321
331
  "0.1.2",
322
332
  "0.1.3",
323
333
  "0.1.4",
324
- "0.1.5"
334
+ "0.1.5",
335
+ "0.1.6"
325
336
  ],
326
337
  "@rightkit/updates": [
327
338
  "0.2.4"
@@ -335,7 +346,16 @@
335
346
  ],
336
347
  "@rightkit/ci": [
337
348
  "0.2.43",
338
- "0.2.44"
349
+ "0.2.44",
350
+ "0.2.45"
351
+ ],
352
+ "@rightkit/react-shell": [
353
+ "0.6.4",
354
+ "0.6.5",
355
+ "0.6.6"
356
+ ],
357
+ "@rightkit/i18n": [
358
+ "0.1.0"
339
359
  ]
340
360
  },
341
361
  "cargo": {
@@ -356,16 +376,16 @@
356
376
  "rightkit-tauri": "0.1.0"
357
377
  },
358
378
  "stagedCargo": {
359
- "rightkit-agent-tools": "0.1.3",
379
+ "rightkit-agent-tools": "0.1.4",
360
380
  "rightkit-agents": "0.1.0",
361
381
  "rightkit-app-settings": "0.2.0",
362
382
  "rightkit-asr": "0.2.1",
363
383
  "rightkit-audio": "0.2.3",
364
- "rightkit-automation": "0.3.0",
384
+ "rightkit-automation": "0.4.1",
365
385
  "rightkit-browser": "0.3.1",
366
386
  "rightkit-cache": "0.2.0",
367
387
  "rightkit-channel-memory": "0.1.0",
368
- "rightkit-child-process": "0.4.0",
388
+ "rightkit-child-process": "0.4.3",
369
389
  "rightkit-compose": "0.1.0",
370
390
  "rightkit-contracts": "0.1.5",
371
391
  "rightkit-crash": "0.3.0",
@@ -373,19 +393,21 @@
373
393
  "rightkit-daemon": "0.2.3",
374
394
  "rightkit-db": "0.4.0",
375
395
  "rightkit-device": "0.1.3",
376
- "rightkit-embed": "0.4.0",
396
+ "rightkit-docs": "0.1.0",
397
+ "rightkit-embed": "0.5.0",
377
398
  "rightkit-ffmpeg": "0.2.6",
378
399
  "rightkit-file-watch": "0.4.0",
379
- "rightkit-fs": "0.4.0",
380
- "rightkit-fsindex": "0.2.1",
381
- "rightkit-hotkeys": "0.1.0",
400
+ "rightkit-fs": "0.4.3",
401
+ "rightkit-fsindex": "0.3.0",
402
+ "rightkit-hooks": "0.1.0",
403
+ "rightkit-hotkeys": "0.1.1",
382
404
  "rightkit-http": "0.3.0",
383
405
  "rightkit-job-queue": "0.3.1",
384
406
  "rightkit-license": "0.2.0",
385
407
  "rightkit-llm": "0.2.1",
386
408
  "rightkit-logs": "0.3.0",
387
- "rightkit-mcp": "0.5.3",
388
- "rightkit-models": "0.3.2",
409
+ "rightkit-mcp": "0.6.0",
410
+ "rightkit-models": "0.4.4",
389
411
  "rightkit-oauth": "0.5.0",
390
412
  "rightkit-ocr": "0.2.2",
391
413
  "rightkit-onnx": "0.2.3",
@@ -393,8 +415,8 @@
393
415
  "rightkit-ownership": "0.2.1",
394
416
  "rightkit-pdf": "0.3.0",
395
417
  "rightkit-playback": "0.2.1",
396
- "rightkit-qa": "0.4.0",
397
- "rightkit-qa-driver": "0.4.0",
418
+ "rightkit-qa": "0.6.4",
419
+ "rightkit-qa-driver": "0.5.0",
398
420
  "rightkit-record": "0.3.0",
399
421
  "rightkit-review": "0.2.0",
400
422
  "rightkit-sandbox": "0.4.0",
@@ -426,16 +448,16 @@
426
448
  },
427
449
  "registry": {
428
450
  "cargo": {
429
- "rightkit-agent-tools": "0.1.3",
451
+ "rightkit-agent-tools": "0.1.4",
430
452
  "rightkit-agents": "0.1.0",
431
453
  "rightkit-app-settings": "0.2.0",
432
454
  "rightkit-asr": "0.2.1",
433
455
  "rightkit-audio": "0.2.3",
434
- "rightkit-automation": "0.3.0",
456
+ "rightkit-automation": "0.4.1",
435
457
  "rightkit-browser": "0.3.1",
436
458
  "rightkit-cache": "0.2.0",
437
459
  "rightkit-channel-memory": "0.1.0",
438
- "rightkit-child-process": "0.4.0",
460
+ "rightkit-child-process": "0.4.1",
439
461
  "rightkit-compose": "0.1.0",
440
462
  "rightkit-contracts": "0.1.5",
441
463
  "rightkit-control": "0.3.0",
@@ -444,20 +466,22 @@
444
466
  "rightkit-daemon": "0.2.3",
445
467
  "rightkit-db": "0.4.0",
446
468
  "rightkit-device": "0.1.3",
447
- "rightkit-embed": "0.4.0",
469
+ "rightkit-docs": "0.1.0",
470
+ "rightkit-embed": "0.5.0",
448
471
  "rightkit-ffmpeg": "0.2.6",
449
472
  "rightkit-file-watch": "0.4.0",
450
473
  "rightkit-framed-sidecar": "0.2.0",
451
- "rightkit-fs": "0.4.0",
452
- "rightkit-fsindex": "0.2.1",
453
- "rightkit-hotkeys": "0.1.0",
474
+ "rightkit-fs": "0.4.1",
475
+ "rightkit-fsindex": "0.3.0",
476
+ "rightkit-hooks": "0.1.0",
477
+ "rightkit-hotkeys": "0.1.1",
454
478
  "rightkit-http": "0.3.0",
455
479
  "rightkit-job-queue": "0.3.1",
456
480
  "rightkit-jobs": "0.3.0",
457
481
  "rightkit-license": "0.2.0",
458
482
  "rightkit-llm": "0.2.1",
459
483
  "rightkit-logs": "0.3.0",
460
- "rightkit-mcp": "0.5.3",
484
+ "rightkit-mcp": "0.6.0",
461
485
  "rightkit-media": "0.2.6",
462
486
  "rightkit-models": "0.3.2",
463
487
  "rightkit-oauth": "0.5.0",
@@ -469,8 +493,8 @@
469
493
  "rightkit-pdf": "0.3.0",
470
494
  "rightkit-playback": "0.2.1",
471
495
  "rightkit-process": "0.4.0",
472
- "rightkit-qa": "0.4.0",
473
- "rightkit-qa-driver": "0.4.0",
496
+ "rightkit-qa": "0.6.1",
497
+ "rightkit-qa-driver": "0.5.0",
474
498
  "rightkit-qts": "0.2.6",
475
499
  "rightkit-qts-ggml": "0.1.2",
476
500
  "rightkit-qts-ggml-sys": "0.1.2",
@@ -500,29 +524,29 @@
500
524
  "@rightkit/app-shell": "0.6.2",
501
525
  "@rightkit/app-update": "0.2.5",
502
526
  "@rightkit/ax": "0.3.2",
503
- "@rightkit/ci": "0.2.45",
527
+ "@rightkit/ci": "0.2.49",
504
528
  "@rightkit/doc-render": "0.1.6",
505
529
  "@rightkit/git": "0.2.42",
506
530
  "@rightkit/hooks": "0.1.2",
507
- "@rightkit/i18n": "0.1.0",
508
- "@rightkit/legal": "0.3.1",
509
- "@rightkit/legal-ui": "0.2.2",
531
+ "@rightkit/i18n": "0.1.1",
532
+ "@rightkit/legal": "0.5.0",
533
+ "@rightkit/legal-ui": "0.3.0",
510
534
  "@rightkit/license": "0.2.0",
511
535
  "@rightkit/logs": "0.1.4",
512
536
  "@rightkit/media-ui": "0.3.4",
513
- "@rightkit/onboarding": "0.3.3",
537
+ "@rightkit/onboarding": "0.5.0",
514
538
  "@rightkit/outdated": "0.2.0",
515
- "@rightkit/pdf-ui": "0.1.6",
539
+ "@rightkit/pdf-ui": "0.1.8",
516
540
  "@rightkit/platform-ui": "0.2.8",
517
- "@rightkit/qa": "0.4.8",
518
- "@rightkit/qa-chrome": "0.1.6",
519
- "@rightkit/react-shell": "0.6.4",
520
- "@rightkit/release": "0.2.164",
521
- "@rightkit/settings-ui": "0.4.4",
541
+ "@rightkit/qa": "0.4.9",
542
+ "@rightkit/qa-chrome": "0.1.8",
543
+ "@rightkit/react-shell": "0.6.8",
544
+ "@rightkit/release": "0.2.172",
545
+ "@rightkit/settings-ui": "0.5.0",
522
546
  "@rightkit/shell": "0.1.1",
523
547
  "@rightkit/tauri": "0.2.1",
524
548
  "@rightkit/tauri-shell": "0.1.1",
525
- "@rightkit/theme": "0.2.3",
549
+ "@rightkit/theme": "0.2.4",
526
550
  "@rightkit/updates": "0.2.5"
527
551
  }
528
552
  },
@@ -545,7 +569,8 @@
545
569
  "0.2.6",
546
570
  "0.2.7",
547
571
  "0.3.0",
548
- "0.3.1"
572
+ "0.3.1",
573
+ "0.3.2"
549
574
  ],
550
575
  "rightkit-audio": [
551
576
  "0.1.0",
@@ -563,7 +588,8 @@
563
588
  "0.2.2",
564
589
  "0.3.0",
565
590
  "0.3.1",
566
- "0.3.2"
591
+ "0.3.2",
592
+ "0.4.0"
567
593
  ],
568
594
  "rightkit-jobs": [
569
595
  "0.2.1",
@@ -581,7 +607,8 @@
581
607
  "0.4.0",
582
608
  "0.5.0",
583
609
  "0.5.1",
584
- "0.5.2"
610
+ "0.5.2",
611
+ "0.5.3"
585
612
  ],
586
613
  "rightkit-media": [
587
614
  "0.2.2",
@@ -619,7 +646,11 @@
619
646
  "0.2.12",
620
647
  "0.2.14",
621
648
  "0.2.16",
622
- "0.3.0"
649
+ "0.3.0",
650
+ "0.4.0",
651
+ "0.5.0",
652
+ "0.6.0",
653
+ "0.6.1"
623
654
  ],
624
655
  "rightkit-sandbox": [
625
656
  "0.1.0",
@@ -680,7 +711,9 @@
680
711
  "0.2.0",
681
712
  "0.3.0",
682
713
  "0.3.1",
683
- "0.3.2"
714
+ "0.3.2",
715
+ "0.4.0",
716
+ "0.4.1"
684
717
  ],
685
718
  "rightkit-service": [
686
719
  "0.1.0",
@@ -718,7 +751,8 @@
718
751
  ],
719
752
  "rightkit-fsindex": [
720
753
  "0.1.0",
721
- "0.2.0"
754
+ "0.2.0",
755
+ "0.2.1"
722
756
  ],
723
757
  "rightkit-asr": [
724
758
  "0.0.2",
@@ -760,10 +794,24 @@
760
794
  ],
761
795
  "rightkit-qa-driver": [
762
796
  "0.3.0",
763
- "0.3.1"
797
+ "0.3.1",
798
+ "0.4.0",
799
+ "0.4.1"
764
800
  ],
765
801
  "rightkit-agent-tools": [
766
- "0.1.2"
802
+ "0.1.2",
803
+ "0.1.3"
804
+ ],
805
+ "rightkit-automation": [
806
+ "0.3.0",
807
+ "0.4.0"
808
+ ],
809
+ "rightkit-child-process": [
810
+ "0.4.0",
811
+ "0.4.1"
812
+ ],
813
+ "rightkit-hotkeys": [
814
+ "0.1.0"
767
815
  ]
768
816
  }
769
817
  }
@@ -1,6 +1,14 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "heldResource": {
4
+ "rightkit-agent-tools": {
5
+ "ceilings": null,
6
+ "requiredScale": null
7
+ },
8
+ "rightkit-agents": {
9
+ "ceilings": null,
10
+ "requiredScale": null
11
+ },
4
12
  "rightkit-asr": {
5
13
  "ceilings": null,
6
14
  "requiredScale": null
@@ -17,10 +25,22 @@
17
25
  "ceilings": null,
18
26
  "requiredScale": null
19
27
  },
28
+ "rightkit-hotkeys": {
29
+ "ceilings": null,
30
+ "requiredScale": null
31
+ },
32
+ "rightkit-mcp": {
33
+ "ceilings": null,
34
+ "requiredScale": null
35
+ },
20
36
  "rightkit-ocr": {
21
37
  "ceilings": null,
22
38
  "requiredScale": null
23
39
  },
40
+ "rightkit-onnx": {
41
+ "ceilings": null,
42
+ "requiredScale": null
43
+ },
24
44
  "rightkit-record": {
25
45
  "ceilings": null,
26
46
  "requiredScale": null
@@ -29,6 +49,14 @@
29
49
  "ceilings": null,
30
50
  "requiredScale": null
31
51
  },
52
+ "rightkit-tts": {
53
+ "ceilings": null,
54
+ "requiredScale": null
55
+ },
56
+ "rightkit-tts-qwen": {
57
+ "ceilings": null,
58
+ "requiredScale": null
59
+ },
32
60
  "rightkit-vad": {
33
61
  "ceilings": null,
34
62
  "requiredScale": null
@@ -345,6 +345,9 @@ function checkEvidence(m, index, budget, crateDir, { exists, readFile }) {
345
345
 
346
346
  const stripComments = (text) => text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
347
347
 
348
+ // `use`, `pub use` and `pub(crate) use` declarations, including multi-line `{ ... }` lists: an import cannot start work.
349
+ const stripImports = (text) => text.replace(/^[ \t]*(?:pub(?:\([^)]*\))?\s+)?use\s[^;]*;/gm, "");
350
+
348
351
  /** Source with `#[cfg(test)]` modules removed (brace-balanced), for scanning shipped code only. */
349
352
  function withoutTestModules(text) {
350
353
  const out = [];
@@ -380,7 +383,7 @@ function rustFiles(dir) {
380
383
  export function scanContinuousFiles(crateDir) {
381
384
  const files = {};
382
385
  for (const file of rustFiles(path.join(crateDir, "src")).sort()) {
383
- const text = stripComments(withoutTestModules(fs.readFileSync(file, "utf8")));
386
+ const text = stripImports(stripComments(withoutTestModules(fs.readFileSync(file, "utf8"))));
384
387
  const ids = Object.entries(CONTINUOUS_PATTERNS).filter(([, pattern]) => pattern.test(text)).map(([id]) => id);
385
388
  if (ids.length) files[path.relative(crateDir, file).split(path.sep).join("/")] = ids;
386
389
  }
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ // right-release sign-candidate: sign the EXACT bytes of an unsigned release candidate instead of rebuilding from source
3
+ // (Orthic-Labs/rightkit#320, SwiftRight SR0 7a). The candidate job's artifact (MSIX / .exe on Windows, .app or loose executables on
4
+ // macOS) is the signing input. Steps: verify every file's sha256 against the candidate receipt (refuse on any mismatch, missing or
5
+ // unrecorded file), sign in place (Windows: Azure Artifact Signing through sign-windows.mjs; macOS: Developer ID through
6
+ // sign-dev-artifact), confirm each signed file changed, and write a receipt binding candidate sha -> signed sha. It never builds,
7
+ // notarizes or publishes, and a signing job calls it instead of `right-release build`.
8
+ //
9
+ // Candidate receipt (same shape as the dev artifact payload metadata): { schema: 1, files: [{ path, sha256 }] }, paths relative to --artifact.
10
+ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
11
+ import os from "node:os";
12
+ import path from "node:path";
13
+ import { fileURLToPath, pathToFileURL } from "node:url";
14
+ import { spawnSync } from "./background-process.mjs";
15
+ import { fileEvidence } from "./macos-file-evidence.mjs";
16
+ import { readMsixSignerSubject } from "./msix-signer.mjs";
17
+ import { signDevArtifact, verifyDevArtifactPayload } from "./sign-dev-artifact.mjs";
18
+
19
+ export const SIGN_CANDIDATE_CONTRACT = "rightkit-sign-candidate-v1";
20
+ export const SIGN_CANDIDATE_SCHEMA = 1;
21
+
22
+ export class SignCandidateError extends Error {
23
+ constructor(code, message) {
24
+ super(message);
25
+ this.name = "SignCandidateError";
26
+ this.code = code;
27
+ }
28
+ }
29
+
30
+ const fail = (code, message) => { throw new SignCandidateError(code, message); };
31
+ const toPosix = (value) => value.split(path.sep).join("/");
32
+ const USAGE = "usage: right-release sign-candidate --platform win|mac --artifact <dir> --candidate-receipt <receipt.json> --out <binding.json> [--manifest <sign.json>] [--publisher <subject>] [--dry-run]";
33
+
34
+ const defaultSignWindows = ({ files, env, run }) => {
35
+ const script = path.join(path.dirname(fileURLToPath(import.meta.url)), "sign-windows.mjs");
36
+ const tempDir = mkdtempSync(path.join(os.tmpdir(), "sign-candidate-"));
37
+ try {
38
+ const result = run(process.execPath, [script, "--receipt", path.join(tempDir, "authenticode.json"), ...files], { env, encoding: "utf8", windowsHide: true, shell: false });
39
+ if (result.error || result.status !== 0) fail("SIGN_CANDIDATE_SIGNING_FAILED", `sign-windows failed: ${`${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim() || result.error?.message}`);
40
+ } finally { rmSync(tempDir, { recursive: true, force: true }); }
41
+ };
42
+
43
+ /**
44
+ * Sign an existing candidate. Injectable for tests: `signWindows({ files })`, `signMac(options)` (defaults to signDevArtifact),
45
+ * `evidenceOf`, `readSigner`. Returns the binding receipt (also written to `outPath`). With `dryRun` only the hash check runs.
46
+ */
47
+ export function signCandidate({
48
+ platform, artifact, receiptPath, outPath, manifestPath, publisher, dryRun = false,
49
+ env = process.env, run = spawnSync, hostPlatform = process.platform,
50
+ evidenceOf = fileEvidence, readSigner = readMsixSignerSubject,
51
+ signWindows = (options) => defaultSignWindows({ ...options, env, run }),
52
+ signMac = (options) => signDevArtifact(options),
53
+ } = {}) {
54
+ if (!platform || !artifact || !receiptPath || !outPath) fail("SIGN_CANDIDATE_USAGE", USAGE);
55
+ if (platform !== "win" && platform !== "mac") fail("SIGN_CANDIDATE_USAGE", `--platform must be win or mac: ${JSON.stringify(platform)}`);
56
+ if (platform === "mac" && !manifestPath) fail("SIGN_CANDIDATE_USAGE", "--manifest <sign.json> is required for --platform mac (fixed identifier per file)");
57
+ const root = path.resolve(artifact);
58
+ if (!existsSync(root)) fail("SIGN_CANDIDATE_MISSING", `artifact directory does not exist: ${root}`);
59
+ const receiptFile = path.resolve(receiptPath);
60
+ if (!existsSync(receiptFile)) fail("SIGN_CANDIDATE_MISSING", `candidate receipt does not exist: ${receiptFile}`);
61
+
62
+ // Bytes must be the qualified candidate: every recorded hash is checked before anything is signed.
63
+ let candidate;
64
+ try { candidate = verifyDevArtifactPayload(root, receiptFile); } catch (error) {
65
+ fail(`SIGN_CANDIDATE_${String(error.code ?? "RECEIPT_INVALID").replace(/^SIGN_DEV_ARTIFACT_/, "")}`, error.message);
66
+ }
67
+ const candidateSha = new Map([...candidate.recorded].map(([file, item]) => [path.relative(root, file), item.sha256]));
68
+ const receiptSha256 = evidenceOf(receiptFile).sha256;
69
+ if (dryRun) return { schema: SIGN_CANDIDATE_SCHEMA, dryRun: true, platform, files: [...candidateSha].map(([rel, sha256]) => ({ path: toPosix(rel), candidateSha256: sha256 })) };
70
+ if (platform === "win" && hostPlatform !== "win32") fail("SIGN_CANDIDATE_PLATFORM", "--platform win must run on Windows");
71
+ if (platform === "mac" && hostPlatform !== "darwin") fail("SIGN_CANDIDATE_PLATFORM", "--platform mac must run on macOS");
72
+
73
+ let files;
74
+ let signing;
75
+ if (platform === "win") {
76
+ const absolute = [...candidateSha.keys()].map((rel) => path.resolve(root, rel));
77
+ signWindows({ files: absolute });
78
+ files = [...candidateSha].map(([rel, sha]) => {
79
+ const signedSha256 = evidenceOf(path.resolve(root, rel)).sha256;
80
+ if (signedSha256 === sha) fail("SIGN_CANDIDATE_UNCHANGED", `${toPosix(rel)} was not changed by signing`);
81
+ let signer;
82
+ if (/\.msix(bundle)?$/i.test(rel)) {
83
+ signer = readSigner(path.resolve(root, rel));
84
+ if (publisher && signer !== publisher) fail("SIGN_CANDIDATE_PUBLISHER_MISMATCH", `${toPosix(rel)} is signed as ${JSON.stringify(signer)}, expected ${JSON.stringify(publisher)} (a subject change changes the package family name)`);
85
+ }
86
+ return { path: toPosix(rel), candidateSha256: sha, signedSha256, ...(signer ? { signerSubject: signer } : {}) };
87
+ });
88
+ signing = "azure-artifact-signing";
89
+ } else {
90
+ // The candidate receipt doubles as the payload metadata, so work on a copy and keep the candidate receipt as submitted.
91
+ const workDir = mkdtempSync(path.join(os.tmpdir(), "sign-candidate-"));
92
+ try {
93
+ const metadata = path.join(workDir, "payload.json");
94
+ copyFileSync(receiptFile, metadata);
95
+ const evidence = signMac({ artifact: root, manifestPath, metadataPath: metadata, evidencePath: path.join(workDir, "evidence.json"), env, run, platform: hostPlatform });
96
+ const signedByPath = new Map(evidence.files.map((file) => [file.path, file]));
97
+ files = [...candidateSha].map(([rel, sha]) => {
98
+ const key = toPosix(rel);
99
+ const record = signedByPath.get(key);
100
+ if (record) {
101
+ if (record.sha256Before !== sha) fail("SIGN_CANDIDATE_HASH_MISMATCH", `${key}: signing started from ${record.sha256Before}, candidate receipt says ${sha}`);
102
+ return { path: key, candidateSha256: sha, signedSha256: record.sha256After, identifier: record.identifier, teamIdentifier: record.teamIdentifier };
103
+ }
104
+ const unchanged = evidenceOf(path.resolve(root, rel)).sha256;
105
+ if (unchanged !== sha) fail("SIGN_CANDIDATE_HASH_MISMATCH", `${key} is not in the sign manifest but changed during signing`);
106
+ return { path: key, candidateSha256: sha, signedSha256: unchanged, unsigned: true };
107
+ });
108
+ signing = `developer-id:${evidence.teamIdentifier}`;
109
+ } finally { rmSync(workDir, { recursive: true, force: true }); }
110
+ }
111
+
112
+ const binding = {
113
+ schema: SIGN_CANDIDATE_SCHEMA, contract: SIGN_CANDIDATE_CONTRACT, platform, signing,
114
+ rebuilt: false, built: false, notarized: false, published: false,
115
+ candidateReceiptSha256: receiptSha256, artifact: root, files,
116
+ };
117
+ const absoluteOut = path.resolve(outPath);
118
+ mkdirSync(path.dirname(absoluteOut), { recursive: true });
119
+ writeFileSync(absoluteOut, `${JSON.stringify(binding, null, 2)}\n`);
120
+ return binding;
121
+ }
122
+
123
+ /** Validate a binding receipt: contract, no rebuild, every file bound candidate sha -> signed sha. Throws SIGN_CANDIDATE_BINDING_INVALID. */
124
+ export function validateCandidateBinding(binding, expected = {}) {
125
+ const bad = (message) => fail("SIGN_CANDIDATE_BINDING_INVALID", `candidate binding receipt: ${message}`);
126
+ if (!binding || binding.schema !== SIGN_CANDIDATE_SCHEMA || binding.contract !== SIGN_CANDIDATE_CONTRACT) bad("unrecognized contract");
127
+ if (binding.rebuilt !== false) bad("signed bytes were rebuilt, not derived from the candidate");
128
+ if (!Array.isArray(binding.files) || !binding.files.length) bad("no files");
129
+ for (const file of binding.files) {
130
+ for (const key of ["candidateSha256", "signedSha256"]) if (!/^[0-9a-f]{64}$/.test(file?.[key] ?? "")) bad(`${file?.path}.${key} must be a SHA-256`);
131
+ if (!file.unsigned && file.candidateSha256 === file.signedSha256) bad(`${file.path} was not changed by signing`);
132
+ }
133
+ if (expected.platform && binding.platform !== expected.platform) bad(`platform ${binding.platform} is not ${expected.platform}`);
134
+ if (expected.candidateSha256s) {
135
+ const bound = new Set(binding.files.map((file) => file.candidateSha256));
136
+ for (const sha of expected.candidateSha256s) if (!bound.has(sha)) bad(`candidate ${sha} is not bound`);
137
+ }
138
+ return binding;
139
+ }
140
+
141
+ export function main(args = process.argv.slice(2), options = {}) {
142
+ const take = (flag) => {
143
+ const index = args.indexOf(flag);
144
+ if (index < 0) return undefined;
145
+ const value = args[index + 1];
146
+ if (!value || value.startsWith("--")) fail("SIGN_CANDIDATE_USAGE", `${flag} requires a value`);
147
+ return value;
148
+ };
149
+ try {
150
+ const result = signCandidate({
151
+ platform: take("--platform"), artifact: take("--artifact"), receiptPath: take("--candidate-receipt"), outPath: take("--out"),
152
+ manifestPath: take("--manifest"), publisher: take("--publisher"), dryRun: args.includes("--dry-run"), ...options,
153
+ });
154
+ console.log(result.dryRun ? `dry-run: candidate hashes verified; would sign ${result.files.map((file) => file.path).join(", ")}` : `signed ${result.files.length} candidate file(s) (${result.signing}); binding receipt written`);
155
+ } catch (error) {
156
+ console.error(`right-release sign-candidate: ${error.code ? `[${error.code}] ` : ""}${error.message}`);
157
+ process.exitCode = 1;
158
+ }
159
+ }
160
+
161
+ if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) main();