@rightkit/release 0.6.3 → 0.6.5

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 (48) hide show
  1. package/README.md +67 -5
  2. package/admission-files.mjs +279 -0
  3. package/admission-host.mjs +403 -0
  4. package/admission.mjs +146 -0
  5. package/app-check.mjs +869 -0
  6. package/bin/darwin/rightkit-swap +0 -0
  7. package/bin/rightkit-gate.mjs +68 -29
  8. package/build-release.mjs +81 -21
  9. package/cli/right-release.mjs +39 -5
  10. package/deterministic-scans.mjs +42 -15
  11. package/development.mjs +3 -2
  12. package/hosted-workflow-policy.mjs +111 -0
  13. package/inventory-check.mjs +12 -1
  14. package/ios-dev.mjs +2 -2
  15. package/ios-host.mjs +7 -7
  16. package/ios-package-recipe.mjs +2 -2
  17. package/local-publish.mjs +1 -1
  18. package/local-qualify.mjs +3 -3
  19. package/local-runtime.mjs +1 -1
  20. package/ownership-dependency-allowlist.json +2 -0
  21. package/package.json +5 -3
  22. package/pipeline-admission.mjs +5 -4
  23. package/pipeline-receipts.mjs +302 -302
  24. package/pipeline-scan.mjs +3 -3
  25. package/pipeline-tools.mjs +175 -171
  26. package/prebuild-gates.mjs +191 -0
  27. package/progress-control.mjs +1 -1
  28. package/publish-update.mjs +4 -3
  29. package/qa-admission-policy.json +5 -0
  30. package/release-config.mjs +353 -330
  31. package/release-qa-audit.mjs +37 -11
  32. package/release-qa-command.mjs +46 -5
  33. package/release-qa-fixtures.mjs +127 -0
  34. package/release-qa-floor.json +6 -1
  35. package/release-qa-hardening.mjs +173 -0
  36. package/release-qa-policy.mjs +168 -0
  37. package/release-qa-receipt.mjs +21 -1
  38. package/release-switch-scan.mjs +137 -6
  39. package/release.mjs +333 -231
  40. package/rightapps-register.mjs +3 -1
  41. package/rightkit-drift.mjs +1 -1
  42. package/rightkit-ownership.json +15 -5
  43. package/rightkit-versions.json +50 -37
  44. package/stage-sidecar.mjs +17 -15
  45. package/suite-api-literal.mjs +109 -0
  46. package/suite-api.generated.mjs +78 -0
  47. package/swap-helper-bundle.mjs +2 -2
  48. package/win-package-recipe.mjs +7 -4
@@ -1,4 +1,6 @@
1
- const DEFAULT_API_BASE = "https://api.spoares.com";
1
+ import { RIGHT_SUITE_API_ORIGIN } from "./suite-api.generated.mjs";
2
+
3
+ const DEFAULT_API_BASE = RIGHT_SUITE_API_ORIGIN;
2
4
  const REGISTRATION_ROUTES = new Set([
3
5
  "/v1/admin/apps/patches",
4
6
  "/v1/admin/apps/releases",
@@ -91,7 +91,7 @@ export function applyRightkitAdoption(appRoot, versions = loadRightkitVersions()
91
91
  for (const file of byFile.keys()) {
92
92
  const dir = path.join(appRoot, path.dirname(file));
93
93
  if (file.endsWith("package.json")) run("pnpm", ["install", "--lockfile-only", "--ignore-scripts"], dir);
94
- else run("rightkit", ["cargo", "metadata", "--format-version", "1", "--manifest-path", path.join(appRoot, file)], dir);
94
+ else run("rustright", ["cargo", "metadata", "--format-version", "1", "--manifest-path", path.join(appRoot, file)], dir);
95
95
  }
96
96
  }
97
97
  return drift;
@@ -1023,7 +1023,7 @@
1023
1023
  "fingerprints": [],
1024
1024
  "detection": "declaration-only",
1025
1025
  "policyNotes": [
1026
- "Discovery alias so `rightkit owns docx` resolves to the document-io owner; carries no fingerprints of its own."
1026
+ "Discovery alias so `rustright owns docx` resolves to the document-io owner; carries no fingerprints of its own."
1027
1027
  ]
1028
1028
  },
1029
1029
  {
@@ -1033,7 +1033,7 @@
1033
1033
  "fingerprints": [],
1034
1034
  "detection": "declaration-only",
1035
1035
  "policyNotes": [
1036
- "Discovery alias so `rightkit owns xlsx` resolves to the document-io owner; carries no fingerprints of its own."
1036
+ "Discovery alias so `rustright owns xlsx` resolves to the document-io owner; carries no fingerprints of its own."
1037
1037
  ]
1038
1038
  },
1039
1039
  {
@@ -1043,7 +1043,7 @@
1043
1043
  "fingerprints": [],
1044
1044
  "detection": "declaration-only",
1045
1045
  "policyNotes": [
1046
- "Discovery alias so `rightkit owns document` resolves to the document-io owner; carries no fingerprints of its own."
1046
+ "Discovery alias so `rustright owns document` resolves to the document-io owner; carries no fingerprints of its own."
1047
1047
  ]
1048
1048
  },
1049
1049
  {
@@ -1053,7 +1053,7 @@
1053
1053
  "fingerprints": [],
1054
1054
  "detection": "declaration-only",
1055
1055
  "policyNotes": [
1056
- "Discovery alias so `rightkit owns spreadsheet` resolves to the document-io owner; carries no fingerprints of its own."
1056
+ "Discovery alias so `rustright owns spreadsheet` resolves to the document-io owner; carries no fingerprints of its own."
1057
1057
  ]
1058
1058
  },
1059
1059
  {
@@ -1661,6 +1661,16 @@
1661
1661
  "Fingerprints identify review candidates (competing dependencies and distinctive implementation code); published two-host replacement qualification is not recorded."
1662
1662
  ]
1663
1663
  },
1664
+ {
1665
+ "package": "rightkit-license",
1666
+ "capability": "right-suite-api",
1667
+ "summary": "The Right Suite API host and endpoint contract (contracts/right-suite-api.v1.json): canonical API host, updater and release-status paths, per-app artifact hosts. Rust projection rightkit_license::suite_api, TS @rightkit/app-update/suite-api; apps never write the host.",
1668
+ "fingerprints": [],
1669
+ "detection": "declaration-only",
1670
+ "policyNotes": [
1671
+ "Enforcement: the @rightkit/release pre-build gate suite-api-literal ships with this contract and is wired into the build after the app migrations (L1-L5); no ownership fingerprint."
1672
+ ]
1673
+ },
1664
1674
  {
1665
1675
  "package": "rightkit-llm",
1666
1676
  "capability": "llm-providers",
@@ -2469,7 +2479,7 @@
2469
2479
  "fingerprints": [],
2470
2480
  "detection": "declaration-only",
2471
2481
  "policyNotes": [
2472
- "Discovery alias so `rightkit owns pdf` resolves to the PDF owner; carries no fingerprints of its own."
2482
+ "Discovery alias so `rustright owns pdf` resolves to the PDF owner; carries no fingerprints of its own."
2473
2483
  ]
2474
2484
  },
2475
2485
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": 2,
3
- "packageManager": "pnpm@11.24.0",
3
+ "packageManager": "pnpm@11.25.0",
4
4
  "npm": {
5
5
  "@rightkit/git": "0.2.0",
6
6
  "@rightkit/legal": "0.2.0",
@@ -13,9 +13,9 @@
13
13
  "@rightkit/updates": "0.2.3"
14
14
  },
15
15
  "stagedNpm": {
16
- "@rightkit/app-update": "0.4.1",
16
+ "@rightkit/app-update": "0.4.2",
17
17
  "@rightkit/ax": "0.3.2",
18
- "@rightkit/ci": "0.3.0",
18
+ "@rightkit/ci": "0.3.1",
19
19
  "@rightkit/doc-render": "0.2.1",
20
20
  "@rightkit/hooks": "0.1.2",
21
21
  "@rightkit/i18n": "0.2.0",
@@ -32,10 +32,10 @@
32
32
  "@rightkit/qa": "0.6.1",
33
33
  "@rightkit/qa-chrome": "0.1.11",
34
34
  "@rightkit/react-shell": "0.7.2",
35
- "@rightkit/release": "0.6.3",
35
+ "@rightkit/release": "0.6.5",
36
36
  "@rightkit/settings-ui": "0.7.0",
37
37
  "@rightkit/tauri": "0.3.0",
38
- "@rightkit/tauri-shell": "0.1.2",
38
+ "@rightkit/tauri-shell": "0.1.3",
39
39
  "@rightkit/theme": "0.3.1"
40
40
  },
41
41
  "legacyNpm": {
@@ -229,7 +229,9 @@
229
229
  "0.5.1",
230
230
  "0.6.0",
231
231
  "0.6.1",
232
- "0.6.2"
232
+ "0.6.2",
233
+ "0.6.3",
234
+ "0.6.4"
233
235
  ],
234
236
  "@rightkit/qa": [
235
237
  "0.1.0",
@@ -390,7 +392,8 @@
390
392
  "0.2.43",
391
393
  "0.2.44",
392
394
  "0.2.45",
393
- "0.2.49"
395
+ "0.2.49",
396
+ "0.3.0"
394
397
  ],
395
398
  "@rightkit/react-shell": [
396
399
  "0.6.4",
@@ -407,14 +410,16 @@
407
410
  "@rightkit/app-update": [
408
411
  "0.2.5",
409
412
  "0.3.0",
410
- "0.4.0"
413
+ "0.4.0",
414
+ "0.4.1"
411
415
  ],
412
416
  "@rightkit/logs": [
413
417
  "0.1.4",
414
418
  "0.1.5"
415
419
  ],
416
420
  "@rightkit/tauri-shell": [
417
- "0.1.1"
421
+ "0.1.1",
422
+ "0.1.2"
418
423
  ]
419
424
  },
420
425
  "cargo": {
@@ -441,11 +446,11 @@
441
446
  "rightkit-app-settings": "0.3.0",
442
447
  "rightkit-asr": "0.3.0",
443
448
  "rightkit-audio": "0.3.1",
444
- "rightkit-automation": "0.6.0",
449
+ "rightkit-automation": "0.6.1",
445
450
  "rightkit-browser": "0.3.6",
446
451
  "rightkit-cache": "0.2.3",
447
452
  "rightkit-channel-memory": "0.2.1",
448
- "rightkit-child-process": "0.5.5",
453
+ "rightkit-child-process": "0.5.6",
449
454
  "rightkit-compose": "0.2.0",
450
455
  "rightkit-contracts": "0.1.7",
451
456
  "rightkit-crash": "0.3.6",
@@ -458,15 +463,15 @@
458
463
  "rightkit-embed": "0.6.1",
459
464
  "rightkit-ffmpeg": "0.2.10",
460
465
  "rightkit-file-watch": "0.4.1",
461
- "rightkit-fs": "0.4.6",
466
+ "rightkit-fs": "0.4.7",
462
467
  "rightkit-fsindex": "0.5.0",
463
468
  "rightkit-google-identity": "0.2.0",
464
469
  "rightkit-hooks": "0.2.0",
465
470
  "rightkit-hotkeys": "0.1.2",
466
471
  "rightkit-http": "0.3.8",
467
472
  "rightkit-identity": "0.1.0",
468
- "rightkit-job-queue": "0.5.0",
469
- "rightkit-license": "0.2.4",
473
+ "rightkit-job-queue": "0.5.1",
474
+ "rightkit-license": "0.2.5",
470
475
  "rightkit-llm": "0.3.1",
471
476
  "rightkit-logs": "0.3.5",
472
477
  "rightkit-mcp": "0.7.0",
@@ -477,11 +482,11 @@
477
482
  "rightkit-onnx": "0.2.7",
478
483
  "rightkit-overlay": "0.2.0",
479
484
  "rightkit-overlay-win": "0.1.0",
480
- "rightkit-ownership": "0.4.1",
485
+ "rightkit-ownership": "0.4.2",
481
486
  "rightkit-pdf": "0.3.3",
482
487
  "rightkit-platform-rules": "0.1.0",
483
488
  "rightkit-playback": "0.3.0",
484
- "rightkit-qa": "0.8.0",
489
+ "rightkit-qa": "0.9.0",
485
490
  "rightkit-qa-driver": "0.7.0",
486
491
  "rightkit-record": "0.3.3",
487
492
  "rightkit-review": "0.4.0",
@@ -492,7 +497,7 @@
492
497
  "rightkit-speech-client": "0.4.0",
493
498
  "rightkit-spend": "0.2.0",
494
499
  "rightkit-sync": "0.2.2",
495
- "rightkit-tauri-shell": "0.5.1",
500
+ "rightkit-tauri-shell": "0.6.0",
496
501
  "rightkit-time": "0.1.0",
497
502
  "rightkit-transcript": "0.4.0",
498
503
  "rightkit-tts": "0.2.3",
@@ -513,7 +518,7 @@
513
518
  "stagedSwift": {
514
519
  "rightkit-swift": {
515
520
  "url": "https://github.com/Orthic-Labs/rightkit",
516
- "version": "0.7.0"
521
+ "version": "0.8.1"
517
522
  }
518
523
  },
519
524
  "registry": {
@@ -524,11 +529,11 @@
524
529
  "rightkit-app-settings": "0.3.0",
525
530
  "rightkit-asr": "0.3.0",
526
531
  "rightkit-audio": "0.3.1",
527
- "rightkit-automation": "0.6.0",
532
+ "rightkit-automation": "0.6.1",
528
533
  "rightkit-browser": "0.3.6",
529
534
  "rightkit-cache": "0.2.3",
530
535
  "rightkit-channel-memory": "0.2.1",
531
- "rightkit-child-process": "0.5.5",
536
+ "rightkit-child-process": "0.5.6",
532
537
  "rightkit-compose": "0.2.0",
533
538
  "rightkit-contracts": "0.1.7",
534
539
  "rightkit-control": "0.3.0",
@@ -543,16 +548,16 @@
543
548
  "rightkit-ffmpeg": "0.2.10",
544
549
  "rightkit-file-watch": "0.4.1",
545
550
  "rightkit-framed-sidecar": "0.2.0",
546
- "rightkit-fs": "0.4.6",
551
+ "rightkit-fs": "0.4.7",
547
552
  "rightkit-fsindex": "0.5.0",
548
553
  "rightkit-google-identity": "0.2.0",
549
554
  "rightkit-hooks": "0.2.0",
550
555
  "rightkit-hotkeys": "0.1.2",
551
556
  "rightkit-http": "0.3.8",
552
557
  "rightkit-identity": "0.1.0",
553
- "rightkit-job-queue": "0.5.0",
558
+ "rightkit-job-queue": "0.5.1",
554
559
  "rightkit-jobs": "0.3.0",
555
- "rightkit-license": "0.2.4",
560
+ "rightkit-license": "0.2.5",
556
561
  "rightkit-llm": "0.3.1",
557
562
  "rightkit-logs": "0.3.5",
558
563
  "rightkit-mcp": "0.7.0",
@@ -565,12 +570,12 @@
565
570
  "rightkit-ort": "0.2.3",
566
571
  "rightkit-overlay": "0.2.0",
567
572
  "rightkit-overlay-win": "0.1.0",
568
- "rightkit-ownership": "0.4.1",
573
+ "rightkit-ownership": "0.4.2",
569
574
  "rightkit-pdf": "0.3.3",
570
575
  "rightkit-platform-rules": "0.1.0",
571
576
  "rightkit-playback": "0.3.0",
572
577
  "rightkit-process": "0.4.0",
573
- "rightkit-qa": "0.8.0",
578
+ "rightkit-qa": "0.9.0",
574
579
  "rightkit-qa-driver": "0.7.0",
575
580
  "rightkit-qts": "0.2.6",
576
581
  "rightkit-qts-ggml": "0.1.2",
@@ -589,7 +594,7 @@
589
594
  "rightkit-spend": "0.2.0",
590
595
  "rightkit-sync": "0.2.2",
591
596
  "rightkit-tauri": "0.1.3",
592
- "rightkit-tauri-shell": "0.5.1",
597
+ "rightkit-tauri-shell": "0.6.0",
593
598
  "rightkit-time": "0.1.0",
594
599
  "rightkit-transcript": "0.4.0",
595
600
  "rightkit-tts": "0.2.3",
@@ -603,7 +608,7 @@
603
608
  },
604
609
  "npm": {
605
610
  "@rightkit/app-shell": "0.6.2",
606
- "@rightkit/app-update": "0.4.1",
611
+ "@rightkit/app-update": "0.4.2",
607
612
  "@rightkit/ax": "0.3.2",
608
613
  "@rightkit/ci": "0.3.0",
609
614
  "@rightkit/doc-render": "0.2.1",
@@ -623,11 +628,11 @@
623
628
  "@rightkit/qa": "0.6.1",
624
629
  "@rightkit/qa-chrome": "0.1.11",
625
630
  "@rightkit/react-shell": "0.7.2",
626
- "@rightkit/release": "0.6.2",
631
+ "@rightkit/release": "0.6.4",
627
632
  "@rightkit/settings-ui": "0.7.0",
628
633
  "@rightkit/shell": "0.1.1",
629
634
  "@rightkit/tauri": "0.3.0",
630
- "@rightkit/tauri-shell": "0.1.2",
635
+ "@rightkit/tauri-shell": "0.1.3",
631
636
  "@rightkit/theme": "0.3.1",
632
637
  "@rightkit/updates": "0.2.5"
633
638
  }
@@ -637,7 +642,8 @@
637
642
  "0.2.0",
638
643
  "0.2.1",
639
644
  "0.3.1",
640
- "0.4.0"
645
+ "0.4.0",
646
+ "0.4.1"
641
647
  ],
642
648
  "rightkit-browser": [
643
649
  "0.2.0",
@@ -755,7 +761,8 @@
755
761
  "0.6.1",
756
762
  "0.6.4",
757
763
  "0.7.0",
758
- "0.7.1"
764
+ "0.7.1",
765
+ "0.8.0"
759
766
  ],
760
767
  "rightkit-sandbox": [
761
768
  "0.1.0",
@@ -828,7 +835,8 @@
828
835
  "0.4.1",
829
836
  "0.4.3",
830
837
  "0.4.4",
831
- "0.4.5"
838
+ "0.4.5",
839
+ "0.4.6"
832
840
  ],
833
841
  "rightkit-service": [
834
842
  "0.1.0",
@@ -936,7 +944,8 @@
936
944
  "0.3.0",
937
945
  "0.3.1",
938
946
  "0.3.2",
939
- "0.4.0"
947
+ "0.4.0",
948
+ "0.5.0"
940
949
  ],
941
950
  "rightkit-qa-driver": [
942
951
  "0.3.0",
@@ -958,7 +967,8 @@
958
967
  "0.4.0",
959
968
  "0.4.1",
960
969
  "0.4.4",
961
- "0.5.0"
970
+ "0.5.0",
971
+ "0.6.0"
962
972
  ],
963
973
  "rightkit-child-process": [
964
974
  "0.4.0",
@@ -968,7 +978,8 @@
968
978
  "0.5.1",
969
979
  "0.5.2",
970
980
  "0.5.3",
971
- "0.5.4"
981
+ "0.5.4",
982
+ "0.5.5"
972
983
  ],
973
984
  "rightkit-hotkeys": [
974
985
  "0.1.0",
@@ -1007,7 +1018,8 @@
1007
1018
  "rightkit-license": [
1008
1019
  "0.2.0",
1009
1020
  "0.2.2",
1010
- "0.2.3"
1021
+ "0.2.3",
1022
+ "0.2.4"
1011
1023
  ],
1012
1024
  "rightkit-credentials": [
1013
1025
  "0.2.0",
@@ -1065,7 +1077,8 @@
1065
1077
  "0.3.2",
1066
1078
  "0.3.3",
1067
1079
  "0.4.0",
1068
- "0.5.0"
1080
+ "0.5.0",
1081
+ "0.5.1"
1069
1082
  ],
1070
1083
  "rightkit-android": [
1071
1084
  "0.2.0"
package/stage-sidecar.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  // Declarative engine and sidecar staging for Tauri externalBin (bogusyogi/rightkit#345).
2
2
  //
3
- // Eight apps hand-rolled the same script: build an engine through `rightkit cargo`, find the executable, copy it to
3
+ // Eight apps hand-rolled the same script: build an engine through `rustright cargo`, find the executable, copy it to
4
4
  // src-tauri/binaries/<name>-<target-triple>[.exe], stage ffmpeg, stage onnxruntime, copy model resources. This module is
5
5
  // that script, driven by a `sidecars` list in right-release.config.mjs:
6
6
  //
@@ -19,7 +19,7 @@
19
19
  // then not an externalBin. `clean: true` removes a stale file at the destination before staging. The wrapper key
20
20
  // `wipeStageDir: true` removes stale files named exactly `<name>-<current triple>[.exe]` for a declared name this run no longer produces.
21
21
  //
22
- // `catalog` is a relative path, an absolute path, { crate: "rightkit-ffmpeg", file? } (resolved through `rightkit cargo
22
+ // `catalog` is a relative path, an absolute path, { crate: "rightkit-ffmpeg", file? } (resolved through `rustright cargo
23
23
  // metadata`) or { npm: "<pkg>/<file>" }. The wrapper form { sidecars, profiles: { dev, release } } sets the default cargo
24
24
  // profile pair; RIGHTKIT_BUILD_MODE (dev|release, default release) selects. The target `universal-apple-darwin` builds
25
25
  // both slices of a cargo-bin and lipo-creates `<name>-universal-apple-darwin`. `ffmpeg` and `onnxruntime` do the same from their
@@ -122,13 +122,13 @@ export function parseTargetTriple(target) {
122
122
  return { triple: target, ...row };
123
123
  }
124
124
 
125
- /** `--target`, then TAURI_ENV_TARGET_TRIPLE, then the host triple from `rightkit rustc -vV`. */
125
+ /** `--target`, then TAURI_ENV_TARGET_TRIPLE, then the host triple from `rustright rustc -vV`. */
126
126
  export function resolveTargetTriple({ target, env = process.env, run = defaultRun, cwd = process.cwd() } = {}) {
127
127
  if (target) return target;
128
128
  if (env.TAURI_ENV_TARGET_TRIPLE) return env.TAURI_ENV_TARGET_TRIPLE;
129
- const result = run("rightkit", ["rustc", "-vV"], { cwd, env });
129
+ const result = run("rustright", ["rustc", "-vV"], { cwd, env });
130
130
  const host = result?.stdout?.match(/^host:\s*(.+)$/m)?.[1]?.trim();
131
- if (!host || result.status !== 0) fail("STAGE_SIDECAR_TARGET_UNKNOWN", "cannot determine the host triple (rightkit rustc -vV failed); pass a target");
131
+ if (!host || result.status !== 0) fail("STAGE_SIDECAR_TARGET_UNKNOWN", "cannot determine the host triple (rustright rustc -vV failed); pass a target");
132
132
  return host;
133
133
  }
134
134
 
@@ -354,7 +354,8 @@ export function validateSidecarManifest(raw, { target, mode = "release" } = {})
354
354
  Object.assign(entry, { package: item.package, bin, name, profile, features: [...features], ...(manifestPath ? { manifestPath } : {}), ...(item.sha256 ? { sha256: item.sha256 } : {}), ...(dest ? { dest } : {}), ...(clean ? { clean } : {}) });
355
355
  } else if (item.kind === "ffmpeg") {
356
356
  const { kind: _kind, platforms: _platforms, catalog: rawCatalog, sources: rawSources, probe: rawProbe, ...rest } = item;
357
- if (rest.stage !== undefined && isObject(rest.stage) && rest.stage.cmd === "cargo") errors.push(`${where}: stage.cmd must not be bare cargo; use { cmd: "rightkit", args: ["cargo", ...] }`);
357
+ if (rest.stage !== undefined && isObject(rest.stage) && rest.stage.cmd === "cargo") errors.push(`${where}: stage.cmd must not be bare cargo; use { cmd: "rustright", args: ["cargo", ...] }`);
358
+ if (rest.stage !== undefined && isObject(rest.stage) && rest.stage.cmd === "rightkit") errors.push(`${where}: stage.cmd "rightkit" is the retired name of the RustRight client (rustright#91); use { cmd: "rustright", args: ["cargo", ...] }`);
358
359
  const catalogSpec = parseCatalogSpec(rawCatalog, `${where}: catalog`, errors, "ffmpeg");
359
360
  if (catalogSpec) entry.catalogSpec = catalogSpec;
360
361
  if (rawProbe !== undefined && typeof rawProbe !== "boolean") errors.push(`${where}: probe must be a boolean`);
@@ -513,9 +514,10 @@ function catalogContentDigest(bytes, arch) {
513
514
  const profileDirectory = (profile) => (profile === "dev" || profile === "test" ? "debug" : profile === "bench" ? "release" : profile);
514
515
  const tail = (text, lines = 12) => String(text ?? "").trim().split("\n").slice(-lines).join("\n");
515
516
 
516
- /** Default process runner: `rightkit` resolves through the installed runtime client (as the apps' scripts did). */
517
+ /** Default process runner: `rustright` resolves through the installed runtime client (its Windows shim is rustright.cmd). */
517
518
  export function defaultRun(command, args, { cwd, env = process.env } = {}) {
518
- const launch = command === "rightkit" ? resolveCommand("rightkit", args, { root: cwd, env }) : { command, args };
519
+ if (command === "rightkit") throw new Error("`rightkit` is the retired name of the RustRight client (rustright#91); use rustright (stage: { cmd: \"rustright\" })");
520
+ const launch = command === "rustright" ? resolveCommand(command, args, { root: cwd, env }) : { command, args };
519
521
  return nodeSpawnSync(launch.command, launch.args, {
520
522
  cwd, env: { ...env, ...(launch.env ?? {}) }, encoding: "utf8", maxBuffer: 512 * 1024 * 1024, shell: false, windowsHide: true, stdio: ["inherit", "pipe", "inherit"],
521
523
  });
@@ -561,7 +563,7 @@ function resolveCatalogFile(spec, ctx, kind) {
561
563
  if (spec.via === "absolute") return spec.file;
562
564
  if (spec.via === "path") return path.resolve(ctx.appRoot, spec.file);
563
565
  if (spec.via === "crate") {
564
- const meta = ctx.run("rightkit", ["cargo", "metadata", "--format-version", "1"], { cwd: ctx.appRoot, env: ctx.env });
566
+ const meta = ctx.run("rustright", ["cargo", "metadata", "--format-version", "1"], { cwd: ctx.appRoot, env: ctx.env });
565
567
  let packages;
566
568
  try { packages = JSON.parse(meta.stdout).packages; } catch { /* refused below */ }
567
569
  if (meta?.status !== 0 || !Array.isArray(packages)) fail("STAGE_SIDECAR_CATALOG_UNREADABLE", `the ${label} catalog crate ${spec.crate} cannot be located: the workspace metadata query failed`, { crate: spec.crate });
@@ -737,18 +739,18 @@ function stageCargoSlice(entry, ctx, triple, { dest }) {
737
739
  return [{ kind: "cargo-bin", name: entry.name, path: rel(ctx, dest), ...copied, sourceSha256, package: entry.package, bin: entry.bin, profile: entry.profile, features: entry.features, externalBin: !entry.dest }];
738
740
  }
739
741
 
740
- /** Build one slice through `rightkit cargo` and locate the executable. Returns { source, sourceSha256 }. */
742
+ /** Build one slice through `rustright cargo` and locate the executable. Returns { source, sourceSha256 }. */
741
743
  function stageCargoBuild(entry, ctx, triple) {
742
744
  const { run, appRoot, env, fs } = ctx;
743
745
  const args = ["cargo", "build", "--locked", ...(entry.manifestPath ? ["--manifest-path", path.resolve(appRoot, entry.manifestPath)] : []),
744
746
  "-p", entry.package, "--bin", entry.bin, "--target", triple, "--profile", entry.profile,
745
747
  ...(entry.features.length ? ["--features", entry.features.join(",")] : []), "--message-format=json-render-diagnostics"];
746
748
  ctx.log(`stage-sidecar: rightkit ${args.join(" ")}`);
747
- const built = run("rightkit", args, { cwd: appRoot, env });
748
- if (built?.error || built?.status !== 0) fail("STAGE_SIDECAR_BUILD_FAILED", `rightkit cargo build of ${entry.package} failed (${built?.error?.message ?? `exit ${built?.status}`})`, { package: entry.package, stderr: tail(built?.stderr) });
749
+ const built = run("rustright", args, { cwd: appRoot, env });
750
+ if (built?.error || built?.status !== 0) fail("STAGE_SIDECAR_BUILD_FAILED", `rustright cargo build of ${entry.package} failed (${built?.error?.message ?? `exit ${built?.status}`})`, { package: entry.package, stderr: tail(built?.stderr) });
749
751
  let source = artifactFromStream(built.stdout, entry.bin);
750
752
  if (!source || !fs.existsSync(source)) {
751
- const meta = run("rightkit", ["cargo", "metadata", "--format-version", "1", "--no-deps", ...(entry.manifestPath ? ["--manifest-path", path.resolve(appRoot, entry.manifestPath)] : [])], { cwd: appRoot, env });
753
+ const meta = run("rustright", ["cargo", "metadata", "--format-version", "1", "--no-deps", ...(entry.manifestPath ? ["--manifest-path", path.resolve(appRoot, entry.manifestPath)] : [])], { cwd: appRoot, env });
752
754
  let targetDir;
753
755
  try { targetDir = JSON.parse(meta.stdout).target_directory; } catch { /* refused below */ }
754
756
  if (meta?.status !== 0 || typeof targetDir !== "string" || !path.isAbsolute(targetDir)) targetDir = undefined;
@@ -1378,12 +1380,12 @@ export function isNestedBrokerContext(env = process.env) {
1378
1380
  return insideTauri && (managedHost(env ?? {}) || env?.RIGHTSUITE_HEAVY_WORK_OWNER === "1");
1379
1381
  }
1380
1382
 
1381
- /** True when staging would call `rightkit cargo` for a non-skipped entry. */
1383
+ /** True when staging would call `rustright cargo` for a non-skipped entry. */
1382
1384
  const needsBroker = (plan) => plan.entries.some((entry) => !entry.skipped && (entry.kind === "cargo-bin" || entry.catalogSpec?.via === "crate"));
1383
1385
 
1384
1386
  function assertNotNested(plan, env) {
1385
1387
  if (needsBroker(plan) && isNestedBrokerContext(env)) {
1386
- fail(NESTED_BROKER_CODE, "stage-sidecar needs `rightkit cargo`, but it is running inside an outer broker build (a Tauri beforeBuildCommand/beforeDevCommand on a managed host), where a nested broker call exits 125. Run stage-sidecar in the recipe `prepare` step, before the Tauri build (or call it from your own script before `tauri build`), not from beforeBuildCommand.");
1388
+ fail(NESTED_BROKER_CODE, "stage-sidecar needs `rustright cargo`, but it is running inside an outer broker build (a Tauri beforeBuildCommand/beforeDevCommand on a managed host), where a nested broker call exits 125. Run stage-sidecar in the recipe `prepare` step, before the Tauri build (or call it from your own script before `tauri build`), not from beforeBuildCommand.");
1387
1389
  }
1388
1390
  }
1389
1391
 
@@ -0,0 +1,109 @@
1
+ // Pre-build gate `suite-api-literal`: an app must not carry a Right Suite API host literal. The owner (RightKit) supplies
2
+ // the host, the updater endpoint and the artifact allowlists through @rightkit/app-update/suite-api and the native shell.
3
+ // Source of truth: contracts/right-suite-api.v1.json, read here through its generated projection.
4
+ import { existsSync, readFileSync, statSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { spawnSync } from "./background-process.mjs";
7
+ import {
8
+ RIGHT_SUITE_API_CONTRACT,
9
+ RIGHT_SUITE_API_HOST,
10
+ RIGHT_SUITE_API_ORIGIN,
11
+ RIGHT_SUITE_GATED_ARTIFACT_HOST,
12
+ RIGHT_SUITE_LEGACY_HOSTS,
13
+ RIGHT_SUITE_PUBLIC_ARTIFACT_HOST,
14
+ RIGHT_SUITE_UPDATER_MANIFEST_PATH,
15
+ } from "./suite-api.generated.mjs";
16
+
17
+ /** Every host the contract names: the API host, its legacy hosts, and both artifact hosts. */
18
+ export const SUITE_API_CONTRACT_HOSTS = Object.freeze([
19
+ RIGHT_SUITE_API_HOST,
20
+ ...RIGHT_SUITE_LEGACY_HOSTS,
21
+ RIGHT_SUITE_GATED_ARTIFACT_HOST,
22
+ RIGHT_SUITE_PUBLIC_ARTIFACT_HOST,
23
+ ]);
24
+
25
+ const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
26
+ // A host literal is refused as a whole name: a neighbouring label or hyphen does not make a different host.
27
+ const HOST_PATTERNS = SUITE_API_CONTRACT_HOSTS.map((host) => ({
28
+ host,
29
+ pattern: new RegExp(`(?<![A-Za-z0-9-])${escapeRegExp(host)}(?![A-Za-z0-9-])`, "giu"),
30
+ }));
31
+
32
+ /** The one updater endpoint a pending app may keep in its tauri conf (contract pendingNativeUpdater). */
33
+ export function pendingUpdaterEndpoint(appKey) {
34
+ return `${RIGHT_SUITE_API_ORIGIN}${RIGHT_SUITE_UPDATER_MANIFEST_PATH.split("{app}").join(appKey)}`;
35
+ }
36
+
37
+ function trackedFiles(root) {
38
+ const result = spawnSync("git", ["ls-files", "-z"], { cwd: root, encoding: "utf8", windowsHide: true });
39
+ if (result.status !== 0) throw new Error(`suite-api-literal: cannot list tracked files under ${root}: ${(result.stderr ?? "").trim()}`);
40
+ return result.stdout.split("\0").filter(Boolean).map((file) => file.split(path.sep).join("/"));
41
+ }
42
+
43
+ const isExcluded = (file) => /\.md$/iu.test(file) || file === "docs" || file.startsWith("docs/");
44
+
45
+ /**
46
+ * Scan the app's tracked, non-Markdown files for Right Suite API host literals.
47
+ * `appKey` is the app's identity (right-release config `app`). Returns findings `{ file, line, host, kind, detail }`;
48
+ * `file` is relative to `root` with forward slashes. Empty array means the app carries no literal.
49
+ *
50
+ * Refused: (a) any contract host in any tracked file; (b) `plugins.updater.endpoints` in a `tauri*.conf.json` of an app the
51
+ * contract lists under `apps`; (c) a host in a Tauri capability JSON scope (`capabilities/*.json`).
52
+ * Exception: for an app in `pendingNativeUpdater`, its conf may keep `plugins.updater.endpoints` when that array is exactly
53
+ * the one contract updater endpoint for the app. Only that exact string is exempt from the host scan.
54
+ */
55
+ export function suiteApiLiteralFindings({ root, appKey, contract = RIGHT_SUITE_API_CONTRACT }) {
56
+ const findings = [];
57
+ const inContract = typeof appKey === "string" && Object.hasOwn(contract.apps ?? {}, appKey);
58
+ const pending = typeof appKey === "string" && (contract.pendingNativeUpdater ?? []).includes(appKey);
59
+ const allowedEndpoint = typeof appKey === "string" ? pendingUpdaterEndpoint(appKey) : null;
60
+
61
+ for (const file of trackedFiles(root)) {
62
+ if (isExcluded(file)) continue;
63
+ const absolute = path.join(root, file);
64
+ if (!existsSync(absolute) || !statSync(absolute).isFile()) continue;
65
+ const buffer = readFileSync(absolute);
66
+ if (buffer.includes(0)) continue;
67
+ let text = buffer.toString("utf8");
68
+ const base = path.posix.basename(file);
69
+ const isTauriConf = /^tauri.*\.conf\.json$/iu.test(base);
70
+ const isCapability = /(^|\/)capabilities\/[^/]+\.json$/iu.test(file);
71
+
72
+ if (isTauriConf && inContract && text.includes("endpoints")) {
73
+ let endpoints;
74
+ let parsed = true;
75
+ try { endpoints = JSON.parse(text)?.plugins?.updater?.endpoints; } catch { parsed = false; }
76
+ if (!parsed) {
77
+ findings.push({ file, line: 1, host: "(unparseable)", kind: "updater-endpoints", detail: "tauri conf cannot be parsed, so its updater endpoints cannot be verified" });
78
+ } else if (endpoints !== undefined) {
79
+ const exact = pending && Array.isArray(endpoints) && endpoints.length === 1 && endpoints[0] === allowedEndpoint;
80
+ if (exact) {
81
+ // Remove only the exact contract string; line count is unchanged because the string has no newline.
82
+ text = text.split(allowedEndpoint).join("");
83
+ } else {
84
+ const line = text.split("\n").findIndex((candidate) => candidate.includes("endpoints")) + 1 || 1;
85
+ findings.push({ file, line, host: "plugins.updater.endpoints", kind: "updater-endpoints", detail: "updater endpoints must be absent; the shell supplies the endpoint from @rightkit/app-update/suite-api" });
86
+ }
87
+ }
88
+ }
89
+
90
+ const lines = text.split("\n");
91
+ lines.forEach((content, index) => {
92
+ for (const { host, pattern } of HOST_PATTERNS) {
93
+ pattern.lastIndex = 0;
94
+ if (!pattern.test(content)) continue;
95
+ pattern.lastIndex = 0;
96
+ const kind = isCapability && file.endsWith(".json") ? "capability-scope" : "host-literal";
97
+ findings.push({ file, line: index + 1, host, kind, detail: kind === "capability-scope" ? "capability scope names a Right Suite API host" : "Right Suite API host literal" });
98
+ }
99
+ });
100
+ }
101
+ return findings;
102
+ }
103
+
104
+ /** The gate's refusal text: one line per finding, `file:line` and the host, so the author can fix each site. */
105
+ export function suiteApiLiteralDetail(appKey, findings) {
106
+ return `${appKey ?? "app"} carries Right Suite API host literals (contract right-suite-api.v1); use @rightkit/app-update/suite-api or the native update host:\n${findings
107
+ .map((finding) => `- ${finding.file}:${finding.line}: ${finding.host} (${finding.kind})`)
108
+ .join("\n")}`;
109
+ }