@rightkit/release 0.2.135 → 0.2.136
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/README.md +62 -0
- package/addon-command.mjs +53 -34
- package/apple-profile-renew.mjs +30 -12
- package/artifact-storage.mjs +47 -10
- package/background-process.mjs +18 -0
- package/build-release.mjs +1 -1
- package/cache-command.mjs +4 -3
- package/cargo-contract.mjs +1 -1
- package/cargo-guard.mjs +4 -3
- package/cargo-registry-readback.mjs +51 -0
- package/cargo-target.mjs +3 -1
- package/cli/right-release.mjs +26 -0
- package/codesign-environment.mjs +26 -2
- package/codesign-shim.mjs +2 -1
- package/committed-source.mjs +3 -3
- package/development.mjs +7 -7
- package/direct-bootstrap.mjs +19 -9
- package/dmg-build.mjs +117 -0
- package/dmg-layout.mjs +123 -0
- package/github-release.mjs +74 -37
- package/heavy-command.mjs +3 -2
- package/install-app.mjs +358 -0
- package/inventory-check.mjs +980 -0
- package/macos-signing-session.mjs +3 -0
- package/managed-cargo.mjs +23 -19
- package/managed-host-secrets.mjs +30 -0
- package/managed-roots.mjs +39 -0
- package/model-promote.mjs +31 -37
- package/notary-auth.mjs +4 -0
- package/osascript-guard.mjs +24 -0
- package/ownership-approval-command.mjs +15 -4
- package/ownership-approval.mjs +114 -49
- package/ownership-availability.mjs +25 -0
- package/ownership-catalog-config.json +18 -0
- package/ownership-catalog.mjs +94 -0
- package/ownership-command.mjs +17 -10
- package/ownership-declaration.json +15 -0
- package/ownership-default-policy.json +1 -11
- package/ownership-evidence.mjs +10 -8
- package/ownership-git-inventory.mjs +29 -1
- package/ownership-helper-paths.json +2 -2
- package/ownership-hooks.mjs +107 -0
- package/ownership-internal-owners.json +44 -0
- package/ownership-key-authority.mjs +112 -7
- package/ownership-key-command.mjs +76 -19
- package/ownership-key-trust.mjs +97 -9
- package/ownership-lockfiles.mjs +311 -0
- package/ownership-report-command.mjs +12 -3
- package/ownership-report.mjs +20 -17
- package/ownership-repositories.json +19 -0
- package/ownership-scan-worker.mjs +96 -11
- package/ownership-source.mjs +39 -0
- package/ownership-staged.mjs +193 -0
- package/ownership-verdict.mjs +74 -0
- package/ownership.mjs +215 -107
- package/package.json +1 -1
- package/protected-credentials.mjs +111 -0
- package/prune-r2.mjs +4 -3
- package/pub-upload.mjs +3 -85
- package/publication-artifacts.mjs +108 -0
- package/publication-gate.mjs +28 -7
- package/publish-cargo.mjs +47 -16
- package/publish-swift.mjs +46 -17
- package/publish-update.mjs +61 -39
- package/r2-verified-upload.mjs +41 -0
- package/registry-parity.mjs +5 -3
- package/release-state.mjs +1 -0
- package/release-token.mjs +2 -0
- package/rightkit-drift.mjs +3 -2
- package/rightkit-ownership.json +2028 -139
- package/rightkit-signing-agent.mjs +5 -3
- package/rightkit-sync.mjs +6 -2
- package/rightkit-versions.json +213 -103
- package/runtime-artifact-manifest.mjs +20 -6
- package/sign-updater.mjs +5 -0
- package/signing-agent-client.mjs +2 -1
- package/signing-agent-install.mjs +3 -2
- package/standalone-clone-verify.mjs +3 -2
- package/tauri-bundle-marker.mjs +3 -2
- package/upload-large.mjs +36 -82
- package/verifier.mjs +5 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveManagedRoots } from './managed-roots.mjs';
|
|
1
2
|
import * as fs from "node:fs";
|
|
2
3
|
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
@@ -29,7 +30,7 @@ export function signingAgentPlist({ paths, node = process.execPath, home }) {
|
|
|
29
30
|
}
|
|
30
31
|
export function installSigningAgent({ home = os.userInfo().homedir, username = os.userInfo().username,
|
|
31
32
|
uid = process.getuid?.(), platform = process.platform, run = spawnSync, io = fs, node = process.execPath,
|
|
32
|
-
managedRoot =
|
|
33
|
+
managedRoot = resolveManagedRoots({ home }).dataRoot, cargoTargetDirs = [], health = requestSigningAgentSync,
|
|
33
34
|
now = Date.now, sleep = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms) } = {}) {
|
|
34
35
|
if (platform !== "darwin") throw new SigningAgentError("MAC_SIGNING_AGENT_PLATFORM", "Signing agent requires macOS");
|
|
35
36
|
requireMacGuiSession({ run, uid });
|
|
@@ -46,7 +47,7 @@ export function installSigningAgent({ home = os.userInfo().homedir, username = o
|
|
|
46
47
|
for (const root of cargoTargetDirs) {
|
|
47
48
|
if (typeof root !== "string" || !path.isAbsolute(root) || ["/", home, "/Volumes", "/Volumes/D"].includes(path.resolve(root))) throw new SigningAgentError("MAC_SIGNING_AGENT_PATH_DENIED", "Cargo target root must be a dedicated absolute directory");
|
|
48
49
|
}
|
|
49
|
-
for (const name of ["rightkit-signing-agent.mjs", "background-process.mjs", "codesign-argv.mjs"]) {
|
|
50
|
+
for (const name of ["rightkit-signing-agent.mjs", "background-process.mjs", "codesign-argv.mjs", "managed-roots.mjs"]) {
|
|
50
51
|
const target = path.join(paths.runtime, name);
|
|
51
52
|
if (io.existsSync(target)) privatePath(target, 0o600, { io, uid });
|
|
52
53
|
io.writeFileSync(target, io.readFileSync(new URL(`./${name}`, import.meta.url)), { mode: 0o600 });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync, realpathSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { spawnSync } from "./background-process.mjs";
|
|
@@ -140,7 +140,8 @@ function parseArgs(argv) {
|
|
|
140
140
|
return { apps, evidencePath };
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
const realOrSelf = (file) => { try { return realpathSync(file); } catch { return path.resolve(file); } };
|
|
144
|
+
if (process.argv[1] && realOrSelf(process.argv[1]) === realOrSelf(fileURLToPath(import.meta.url))) {
|
|
144
145
|
try {
|
|
145
146
|
const evidence = await verifyStandaloneClones(parseArgs(process.argv.slice(2)));
|
|
146
147
|
for (const app of evidence.apps) process.stdout.write(`[standalone] ${app.key} ${app.revision.slice(0, 12)} install+doctor passed\n`);
|
package/tauri-bundle-marker.mjs
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// a byte changing outside the marker all mean the assumption no longer holds.
|
|
11
11
|
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { readFileSync, writeFileSync, realpathSync } from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
|
|
@@ -147,7 +147,8 @@ function sha256(bytes) {
|
|
|
147
147
|
return createHash("sha256").update(bytes).digest("hex");
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
const realOrSelf = (file) => { try { return realpathSync(file); } catch { return path.resolve(file); } };
|
|
151
|
+
if (process.argv[1] && realOrSelf(process.argv[1]) === realOrSelf(fileURLToPath(import.meta.url))) {
|
|
151
152
|
const argv = process.argv.slice(2);
|
|
152
153
|
const bundleIndex = argv.indexOf("--bundle");
|
|
153
154
|
const bundle = bundleIndex >= 0 ? argv[bundleIndex + 1] : "nsis";
|
package/upload-large.mjs
CHANGED
|
@@ -1,86 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { spawnSync } from "./background-process.mjs";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
process.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.
|
|
39
|
-
|
|
40
|
-
// Resolve the package runner before the dry-run exit: a release box without one cannot upload,
|
|
41
|
-
// and that must fail here rather than after a signed build has already been produced.
|
|
42
|
-
const runner = resolveRunner(env);
|
|
43
|
-
if (!runner) {
|
|
44
|
-
console.error(
|
|
45
|
-
"upload-large: no package runner found. Tried: " +
|
|
46
|
-
"pnpm dlx. Install the pinned workspace package manager before release.",
|
|
47
|
-
);
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
console.log(`runner: ${[runner.cmd, ...runner.prefix].join(" ")}`);
|
|
51
|
-
|
|
52
|
-
if (process.env.RIGHT_RELEASE_UPLOAD_DRY_RUN === "1") {
|
|
53
|
-
process.exit(0);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const result = spawnSync(runner.cmd, [...runner.prefix, ...wranglerArgs], {
|
|
57
|
-
env,
|
|
58
|
-
stdio: "inherit",
|
|
59
|
-
shell: process.platform === "win32",
|
|
60
|
-
windowsHide: true,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if (result.error) {
|
|
64
|
-
console.error(`upload-large: failed to start wrangler: ${result.error.message}`);
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
process.exit(result.status ?? 1);
|
|
68
|
-
|
|
69
|
-
function resolveRunner(env) {
|
|
70
|
-
const probe = spawnSync(RUNNER.cmd, ["--version"], {
|
|
71
|
-
env,
|
|
72
|
-
stdio: "ignore",
|
|
73
|
-
shell: process.platform === "win32",
|
|
74
|
-
windowsHide: true,
|
|
75
|
-
});
|
|
76
|
-
return !probe.error && probe.status === 0 ? RUNNER : null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function cleanCloudflareEnv(source) {
|
|
80
|
-
const env = { ...source, CLOUDFLARE_ACCOUNT_ID: source.CLOUDFLARE_ACCOUNT_ID || ACCOUNT_ID };
|
|
81
|
-
delete env.CLOUDFLARE_API_KEY;
|
|
82
|
-
delete env.CLOUDFLARE_EMAIL;
|
|
83
|
-
delete env.CF_API_KEY;
|
|
84
|
-
delete env.CF_EMAIL;
|
|
85
|
-
return env;
|
|
6
|
+
import { verifySealedRelease } from "./release-state.mjs";
|
|
7
|
+
import { uploadVerifiedR2File } from "./r2-verified-upload.mjs";
|
|
8
|
+
import { resolveCloudflareApiToken } from "./protected-credentials.mjs";
|
|
9
|
+
|
|
10
|
+
export function runLargeUpload(argv, { run = spawnSync, env = process.env, credentialStore } = {}) {
|
|
11
|
+
const [localFile, r2Key, bucketAlias = "public", flag, evidencePath, ...extra] = argv;
|
|
12
|
+
if (!localFile || !r2Key) throw new Error("Usage: upload-large <file> <key> public|private --evidence <json> | --seal <sealed-dir>");
|
|
13
|
+
if (!["public", "private"].includes(bucketAlias)) throw new Error(`invalid bucket alias ${bucketAlias}; expected public|private`);
|
|
14
|
+
if (!["--evidence", "--seal"].includes(flag) || !evidencePath || extra.length) throw new Error("publication seal or hash evidence is required (--seal or --evidence)");
|
|
15
|
+
let evidence;
|
|
16
|
+
if (flag === "--seal") {
|
|
17
|
+
const sealed = verifySealedRelease(path.resolve(evidencePath));
|
|
18
|
+
if (path.dirname(path.resolve(localFile)) !== path.resolve(sealed.sealedDir)) throw new Error("artifact is outside sealed directory");
|
|
19
|
+
evidence = sealed.manifest.files.find((entry) => entry.name === path.basename(localFile));
|
|
20
|
+
} else {
|
|
21
|
+
const value = JSON.parse(readFileSync(evidencePath, "utf8"));
|
|
22
|
+
evidence = { sha256: value.artifactSha256, sizeBytes: value.sizeBytes };
|
|
23
|
+
}
|
|
24
|
+
// Validate before runner discovery or any remote operation, including dry runs.
|
|
25
|
+
uploadVerifiedR2File(localFile, evidence, r2Key, bucketAlias, { dryRun: true });
|
|
26
|
+
// The Cloudflare token is resolved only for a real upload; it is injected into the Wrangler child environment alone.
|
|
27
|
+
const dryRun = env.RIGHT_RELEASE_UPLOAD_DRY_RUN === "1";
|
|
28
|
+
const token = resolveCloudflareApiToken({ env, credentialStore, required: !dryRun });
|
|
29
|
+
const uploadEnv = dryRun ? env : { ...env, CLOUDFLARE_API_TOKEN: token };
|
|
30
|
+
const probe = run("pnpm", ["--version"], { env, stdio: "ignore", shell: process.platform === "win32", windowsHide: true });
|
|
31
|
+
if (probe.error || probe.status !== 0) throw new Error("no package runner found: pnpm dlx");
|
|
32
|
+
const object = `${bucketAlias === "public" ? "rightapps-downloads" : "rightapps-updates"}/${r2Key}`;
|
|
33
|
+
console.log(`wrangler r2 object put ${object} --remote (mandatory hash readback)`);
|
|
34
|
+
console.log("runner: pnpm dlx");
|
|
35
|
+
return uploadVerifiedR2File(localFile, evidence, r2Key, bucketAlias, { run, env: uploadEnv, dryRun });
|
|
36
|
+
}
|
|
37
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
38
|
+
try { runLargeUpload(process.argv.slice(2)); }
|
|
39
|
+
catch (error) { console.error(`upload-large: ${error.message}`); process.exitCode = 1; }
|
|
86
40
|
}
|
package/verifier.mjs
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* human nor a model can hand-edit its way to a grant.
|
|
14
14
|
*/
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
|
+
import { realpathSync } from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
16
19
|
|
|
17
20
|
export const GRANTS = Object.freeze(["BUILD_AUTHORIZED", "SIGNING_AUTHORIZED", "RELEASE_AUTHORIZED"]);
|
|
18
21
|
|
|
@@ -136,7 +139,8 @@ function decision(grant, granted, issues, input) {
|
|
|
136
139
|
return body;
|
|
137
140
|
}
|
|
138
141
|
|
|
139
|
-
const
|
|
142
|
+
const realOrSelf = (file) => { try { return realpathSync(file); } catch { return path.resolve(file); } };
|
|
143
|
+
const invokedDirectly = process.argv[1] && realOrSelf(process.argv[1]) === realOrSelf(fileURLToPath(import.meta.url));
|
|
140
144
|
if (invokedDirectly) {
|
|
141
145
|
const grant = process.argv[2];
|
|
142
146
|
let input = {};
|