@rightkit/release 0.2.83 → 0.2.84

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.2.83",
3
+ "version": "0.2.84",
4
4
  "description": "Portable Right Suite release CLI/SDK: signed native archives, direct bootstrap transactions, immutable GitHub Release upload, R2 bootstrap publication, and add-on adoption.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
package/release.mjs CHANGED
@@ -671,14 +671,43 @@ async function validateHostedWorkflows(root, appName, workflows, policy) {
671
671
  if (!source.startsWith("# Managed by right-git")) {
672
672
  fail(`${appName} ${workflow} is not marked as right-git managed`);
673
673
  }
674
- const requestedSecrets = [...source.matchAll(/\bsecrets\.([A-Z0-9_]+)/gi)].map((match) => match[1]);
674
+ const jobSpan = (jobName) => {
675
+ const marker = `\n ${jobName}:\n`;
676
+ const start = source.indexOf(marker);
677
+ if (start < 0) return null;
678
+ const remainder = source.slice(start + marker.length);
679
+ const next = /\n [A-Za-z0-9_-]+:\n/.exec(remainder);
680
+ return { start, end: next ? start + marker.length + next.index : source.length };
681
+ };
682
+ const inside = (index, span) => span && index >= span.start && index < span.end;
683
+ const requestedSecrets = [...source.matchAll(/\bsecrets\.([A-Z0-9_]+)/gi)].map((match) => ({ name: match[1], index: match.index }));
675
684
  const allowedMacosSecrets = new Set(["APPLE_CERTIFICATE_BASE64", "APPLE_CERTIFICATE_PASSWORD", "APPLE_KEYCHAIN_PASSWORD", "APPLE_API_KEY_BASE64", "APPLE_API_KEY", "APPLE_API_ISSUER"]);
676
- const macosSigningAllowed = workflow === "release-candidate.yml" && manifest?.candidate?.signMacos === true;
685
+ const windowsSpan = jobSpan("windows-sign");
686
+ const macosSpan = jobSpan("macos-sign");
687
+ const publishSpan = jobSpan("publish");
688
+ const windowsSource = windowsSpan ? source.slice(windowsSpan.start, windowsSpan.end) : "";
689
+ const macosSource = macosSpan ? source.slice(macosSpan.start, macosSpan.end) : "";
690
+ const publishSource = publishSpan ? source.slice(publishSpan.start, publishSpan.end) : "";
691
+ const protectedWindowsSigning = workflow === "release-candidate.yml"
692
+ && manifest?.candidate?.signWindows === true
693
+ && /windows-sign:\n needs: \[candidate\]\n if: \$\{\{ startsWith\(github\.ref, 'refs\/tags\/v'\) \}\}/.test(windowsSource);
694
+ const protectedMacosSigning = workflow === "release-candidate.yml"
695
+ && manifest?.candidate?.signMacos === true
696
+ && /macos-sign:\n needs: \[candidate\]\n if: \$\{\{ startsWith\(github\.ref, 'refs\/tags\/v'\) \}\}/.test(macosSource);
697
+ const releaseChain = workflow === "release-candidate.yml" ? manifest?.candidate?.releaseChain : undefined;
698
+ const allowedReleaseSecrets = new Set(releaseChain?.publishSecrets ?? []);
699
+ const writePermissions = [...source.matchAll(/^\s*(actions|attestations|checks|contents|deployments|discussions|id-token|issues|models|packages|pages|pull-requests|security-events|statuses):\s*write\s*$/gmi)].map((match) => ({ name: match[1].toLowerCase(), index: match.index }));
700
+ const protectedReleasePublish = releaseChain
701
+ && /publish:\n needs: \[[^\n]*installed-qualification[^\n]*\]\n if: \$\{\{ startsWith\(github\.ref, 'refs\/tags\/v'\) && needs\.installed-qualification\.result == 'success'/.test(publishSource)
702
+ && /\n permissions:\n contents: write\n/.test(publishSource);
677
703
  if (/^\s*permissions:\s*write-all\s*$/mi.test(source)
678
- || /^\s*(?:actions|attestations|checks|contents|deployments|discussions|id-token|issues|models|packages|pages|pull-requests|security-events|statuses):\s*write\s*$/mi.test(source)
704
+ || writePermissions.some(({ name, index }) => name === "id-token"
705
+ ? !(protectedWindowsSigning && inside(index, windowsSpan))
706
+ : name !== "contents" || !protectedReleasePublish || !inside(index, publishSpan))
679
707
  || /pull_request_target\s*:/i.test(source)
680
708
  || /\bsecrets\s*\[/i.test(source)
681
- || requestedSecrets.some((name) => !macosSigningAllowed || !allowedMacosSecrets.has(name))) {
709
+ || requestedSecrets.some(({ name, index }) => !(protectedMacosSigning && inside(index, macosSpan) && allowedMacosSecrets.has(name))
710
+ && !(protectedReleasePublish && inside(index, publishSpan) && allowedReleaseSecrets.has(name)))) {
682
711
  fail(`${appName} right-git managed ${workflow} requests release-capable permissions or secrets`);
683
712
  }
684
713
  }
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "stagedNpm": {
16
16
  "@rightkit/ax": "0.2.1",
17
- "@rightkit/git": "0.2.7",
17
+ "@rightkit/git": "0.2.8",
18
18
  "@rightkit/hooks": "0.1.1",
19
19
  "@rightkit/legal": "0.3.1",
20
20
  "@rightkit/legal-ui": "0.1.1",
@@ -22,7 +22,7 @@
22
22
  "@rightkit/logs": "0.1.4",
23
23
  "@rightkit/platform-ui": "0.1.1",
24
24
  "@rightkit/qa": "0.2.1",
25
- "@rightkit/release": "0.2.83",
25
+ "@rightkit/release": "0.2.84",
26
26
  "@rightkit/tauri": "0.1.1",
27
27
  "@rightkit/updates": "0.2.4"
28
28
  },
@@ -36,7 +36,8 @@
36
36
  "0.2.3",
37
37
  "0.2.4",
38
38
  "0.2.5",
39
- "0.2.6"
39
+ "0.2.6",
40
+ "0.2.7"
40
41
  ],
41
42
  "@rightkit/legal-ui": [
42
43
  "0.1.0"
@@ -84,7 +85,8 @@
84
85
  "0.2.74",
85
86
  "0.2.75",
86
87
  "0.2.76",
87
- "0.2.82"
88
+ "0.2.82",
89
+ "0.2.83"
88
90
  ],
89
91
  "@rightkit/qa": [
90
92
  "0.1.0",