@rightkit/release 0.6.16 → 0.6.20
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 +7 -3
- package/admission-host.mjs +9 -5
- package/app-closure.mjs +9 -3
- package/bin/darwin/rightkit-swap +0 -0
- package/bin/rightkit-gate.mjs +469 -102
- package/bin/rightkit-linux-setup.mjs +15 -0
- package/broker-admission.mjs +184 -0
- package/broker-wire.mjs +15 -3
- package/build-launch.mjs +4 -1
- package/build-ownership.mjs +125 -36
- package/build-release.mjs +39 -7
- package/cargo-contract.mjs +4 -1
- package/cargo-guard.mjs +25 -5
- package/cargo-target-shim.mjs +56 -7
- package/clippy-route.mjs +8 -7
- package/crate-graph.mjs +5 -1
- package/credential-provider.mjs +174 -0
- package/deterministic-scans.mjs +247 -40
- package/development.mjs +8 -0
- package/disk-policy.mjs +2 -2
- package/gate-executor.mjs +5 -3
- package/gate-stages.mjs +34 -3
- package/gradle-lock.mjs +206 -0
- package/heavy-command.mjs +33 -2
- package/linux-artifacts.mjs +2 -1
- package/linux-setup.mjs +106 -0
- package/local-publish.mjs +21 -10
- package/local-qualify.mjs +9 -3
- package/managed-cargo.mjs +54 -18
- package/ownership-lockfiles.mjs +14 -3
- package/ownership.mjs +5 -1
- package/package.json +17 -11
- package/protected-credentials.mjs +13 -5
- package/publication-gate.mjs +9 -4
- package/python-lock.mjs +209 -0
- package/qa-admission-policy.json +32 -0
- package/qa-layout.mjs +229 -0
- package/qa-runner.mjs +156 -0
- package/release-artifact-path.mjs +29 -3
- package/release-config.mjs +1 -1
- package/release-qa-command.mjs +58 -8
- package/release-qa-policy.mjs +5 -3
- package/release-source-identity.mjs +1 -0
- package/release.mjs +10 -2
- package/rightkit-ownership.json +1465 -79
- package/rightkit-registry-resolver.mjs +7 -3
- package/rightkit-versions.json +173 -36
- package/runtime-budget-classes.json +4 -0
- package/runtime-budgets.mjs +5 -1
- package/shell-contract.mjs +1 -1
- package/snapshot-broker.mjs +107 -9
- package/snapshot-check.mjs +2 -0
- package/snapshot-request.mjs +20 -3
- package/snapshot.mjs +11 -4
- package/stage-commands.mjs +2 -1
- package/stage-ledger.mjs +15 -0
- package/stage-sidecar.mjs +17 -3
- package/suite-signing.mjs +40 -4
- package/swift-lock.mjs +334 -0
- package/test-command.mjs +13 -3
- package/tool-build.mjs +156 -0
- package/unit-gate.mjs +9 -2
- package/windows-identity-plan.mjs +119 -0
- package/windows-identity.mjs +136 -0
package/README.md
CHANGED
|
@@ -220,7 +220,7 @@ Adrian, 2026-10-26: the apps lost every build route on 2026-10-25 and build agai
|
|
|
220
220
|
|
|
221
221
|
## The gate on a host without the broker, and tests that reach it
|
|
222
222
|
|
|
223
|
-
The gate chooses its executor itself (`gate-executor.mjs` `resolveExecutor`), never the caller: the RustRight broker on a managed Mac or Dell (chosen by host identity, not by `rustright` on PATH), a refusal on a broker-managed machine whose broker cannot be reached, and direct `cargo` on every Linux host and any other host (a cloud session, a CI runner). Every host runs the same gates in the same order (app rules, class A, then the compile scans); an unmanaged host is never sent to a broker and nothing is deferred to one. Commit and push run no gate and no local hook check, and `install-hook` writes no git hook (below); when git's ref lines are nevertheless given on stdin (the form a pre-push hook receives), every ref is judged in any position (split on single ASCII spaces, so a Unicode space in a ref name cannot hide one), and a line that is not four fields is refused, never dropped, so the pushed commit is always compared with HEAD.
|
|
223
|
+
The gate chooses its executor itself (`gate-executor.mjs` `resolveExecutor`), never the caller: the RustRight broker on a managed Mac or Dell (chosen by host identity, not by `rustright` on PATH), a refusal on a broker-managed machine whose broker cannot be reached, and direct `cargo` on every Linux host and any other host (a cloud session, a CI runner). `rightkit-linux-setup` (`linux-setup.mjs`: `readPins`, `setup`) provisions such a Linux host from the app's pins. Every host runs the same gates in the same order (app rules, class A, then the compile scans); an unmanaged host is never sent to a broker and nothing is deferred to one. Commit and push run no gate and no local hook check, and `install-hook` writes no git hook (below); when git's ref lines are nevertheless given on stdin (the form a pre-push hook receives), every ref is judged in any position (split on single ASCII spaces, so a Unicode space in a ref name cannot hide one), and a line that is not four fields is refused, never dropped, so the pushed commit is always compared with HEAD.
|
|
224
224
|
|
|
225
225
|
`scriptBrokerCall` reads `package.json` scripts only: it follows `pnpm <script>`, `pnpm run`, `npm run`, `yarn` and the wrapper words, not `node -e`, a node script, `sh -c`, or a run in another package (`pnpm --dir`, `--filter`, `-r`). A unit whose test reaches the broker that way says so in the app's own `ci/gate.config.json`, in the `npm` entry the unit's `quietTests` already uses (the key is the unit name: the package name, or the directory with `/` as `-` for a unit of a pnpm root below the repository root):
|
|
226
226
|
|
|
@@ -231,6 +231,10 @@ The gate chooses its executor itself (`gate-executor.mjs` `resolveExecutor`), ne
|
|
|
231
231
|
|
|
232
232
|
The `reason` is required and is printed. The file is read from the gated commit, so the declaration is a reviewed change in the diff that adds it. Where the Rust gate is deferred, the unit's `test:npm:<unit>` scan is deferred with it and named `declared in ci/gate.config.json npm.<unit>.requiresBroker: <reason>`, never reported as passed; on a host with the broker, in CI, on a protected ref and with the opt-out it runs as it did. A declaration of any other shape (`true`, a string, an empty or blank `reason`, an array) is ignored with a note and the test runs where it can: a malformed entry never skips a test. `false` or `null` is no declaration, and a call the scripts do show is reported from the scripts. The gate does not read node scripts for a literal `rustright` or `cargo`: a literal cannot tell a spawn from a command table, a mention or a test fixture, so the declaration is the way.
|
|
233
233
|
|
|
234
|
+
## Tests: unit class and broker class
|
|
235
|
+
|
|
236
|
+
`test-support/suites.json` declares every `*.test.mjs` of this package as `unit` or `broker`. `pnpm test` runs the **unit** class: it needs nothing installed beyond Node, git and a Rust toolchain, and passes with no skip on a Linux host with no RustRight broker (the qualify-direct gate runs exactly this). The **broker** class (`pnpm run test:broker`) is the files that start the installed RustRight broker through `test-support/real-broker.mjs`; it runs only where a broker is installed (Mac, Dell, or `rustright` on PATH), stops with an error where there is none, and is never skipped or simulated. `pnpm run test:all` runs both. **`pnpm run test:broker` on a Mac or Dell is required evidence before this package is published.** `suites.test.mjs` fails when a test file is missing from the manifest or a unit file imports `real-broker.mjs`. The shard runner also removes the gate's own variables (build ownership, RustRight carrier) from the test processes, so a run inside a gate stage behaves as a shell run does.
|
|
237
|
+
|
|
234
238
|
## `install-hook` writes no git hook, and retires the ones an earlier release wrote
|
|
235
239
|
|
|
236
240
|
Commit and push run no gate and no local hook check (`docs/GATE-CONTRACT.md`: the gate is for building; CI runs preflight and the full check on every push). `rightkit-gate install-hook` (a `prepare` script; `right-release hooks install` is an alias) registers the one-door agent hook in `.claude/settings.json` and writes no git hook: no `.githooks/pre-push`, no forwarder for the hooks in `.git/hooks`, no pre-commit ownership step, and it no longer sets `core.hooksPath`.
|
|
@@ -541,9 +545,9 @@ On the Mac and the Dell the gate refuses a gate-run suite or dev build whose con
|
|
|
541
545
|
|
|
542
546
|
## Entry points
|
|
543
547
|
|
|
544
|
-
Bins: `right-release` (`cli/right-release.mjs`)
|
|
548
|
+
Bins: `right-release` (`cli/right-release.mjs`), `rightkit-gate` (`bin/rightkit-gate.mjs`), `rightkit-linux-setup` (`bin/rightkit-linux-setup.mjs`) and `rightkit-agent-hook` (`bin/rightkit-agent-hook.mjs`). The CLI is the supported surface.
|
|
545
549
|
|
|
546
|
-
`package.json` carries an explicit `exports` map (plan item 2.10, C4-16): one `"./<file>"` entry per public file, no `"."` index, no wildcard. It lists the
|
|
550
|
+
`package.json` carries an explicit `exports` map (plan item 2.10, C4-16): one `"./<file>"` entry per public file, no `"."` index, no wildcard. It lists the bin files, `./package.json`, the modules this README documents as SDK (`./release-dependencies.mjs`, `./engine-locator.mjs`, `./pe-content.mjs`, `./dmg-build.mjs`, `./door.mjs`) and the modules that product repositories and RightKit's own tooling import by deep path today. Every other file is private: `import "@rightkit/release/release.mjs"` fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`, and so does `import "@rightkit/release"`. `docs/RELEASE-EXPORTS.md` in the RightKit repository is the inventory (every consumer import with file:line) and `release-exports.test.mjs` fails when the map, that inventory or a checked-out product repository disagree. A new public subpath needs an inventory row or a README SDK section in the same commit; the signing, notarization and packaging modules in the map are a shrinking baseline, not an invitation. A file read by path (`node_modules/@rightkit/release/<file>`) is outside the map and is listed in the inventory too.
|
|
547
551
|
|
|
548
552
|
## Dependencies
|
|
549
553
|
|
package/admission-host.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { brokerManagedHost } from "./cargo-contract.mjs";
|
|
8
|
+
import { CredentialProviderError, providerPlatformOf, updaterCredentialProvider } from "./credential-provider.mjs";
|
|
8
9
|
import { ManagedHostEnvSecretError, isManagedHost } from "./managed-host-secrets.mjs";
|
|
9
10
|
import { resolveMacosDeveloperIdIdentity } from "./macos-signing-identity.mjs";
|
|
10
11
|
import { notarytoolAuthArgs } from "./notary-auth.mjs";
|
|
@@ -215,14 +216,17 @@ export const HOST_ROWS = Object.freeze([
|
|
|
215
216
|
},
|
|
216
217
|
},
|
|
217
218
|
{
|
|
218
|
-
// protected-credentials.mjs execWithUpdaterCredential: the
|
|
219
|
+
// protected-credentials.mjs execWithUpdaterCredential: the updater key is read by the ENROLLED rightkit-credentials (credential-provider.mjs), not by this tool.
|
|
220
|
+
// A Mac or Windows host resolves it from its managed data root and re-hashes it; the finding is the very refusal execWithUpdaterCredential raises.
|
|
219
221
|
id: "host-updater-credential",
|
|
220
222
|
tier: "host",
|
|
221
223
|
run(ctx) {
|
|
222
|
-
if (
|
|
223
|
-
if (ctx.hostPlatform !==
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
if (!signsUpdater(ctx)) return { na: "the target does not sign updater artifacts" };
|
|
225
|
+
if (providerPlatformOf(ctx.hostPlatform) !== ctx.platform) return { notRun: `the updater credential provider is resolved on the ${ctx.platform === "win" ? "Windows" : "Mac"} host that signs` };
|
|
226
|
+
try { updaterCredentialProvider({ env: ctx.env, hostPlatform: ctx.hostPlatform }); } catch (error) {
|
|
227
|
+
if (error instanceof CredentialProviderError) return [error.message];
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
226
230
|
return undefined;
|
|
227
231
|
},
|
|
228
232
|
},
|
package/app-closure.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// Executing scans follow the selected unit's committed dependency closure. File-only scans stay repository-wide.
|
|
1
|
+
// Executing scans follow the selected unit's committed dependency closure. File-only scans stay repository-wide. A pnpm root's lockfile
|
|
2
|
+
// install and audit are workspace scans (they read that root's whole install graph and the network advisory data): they follow the closure.
|
|
2
3
|
// A Cargo scan (metadata, package list, deny, audit) executes cargo, through the broker on a broker host: it is an executing scan,
|
|
3
4
|
// never a file-only one, and follows the Rust closure (no Rust unit in the closure, no Cargo scan).
|
|
4
5
|
// Unknown local dependency edges refuse; they never silently omit checks or authorize every repository unit.
|
|
@@ -169,7 +170,10 @@ export const isCargoScan = (s) => CARGO_WORKSPACE_SCAN.test(String(s.id)) || CAR
|
|
|
169
170
|
export const isExecutingScan = (s) => s.executes === true || s.kind === "test" || s.id === "suite-api" || isCargoScan(s);
|
|
170
171
|
|
|
171
172
|
/** Keep file-only checks; filter every executing unit check (Cargo scans included) & refuse unclassified repository execution. */
|
|
172
|
-
export function scopeScans(scans, closure, { rustUnits = [] } = {}) {
|
|
173
|
+
export function scopeScans(scans, closure, { rustUnits = [], npmUnits = [] } = {}) {
|
|
174
|
+
// The pnpm roots that hold a unit of the closure: a root's lockfile install and audit (pnpm-lockfile[:<root>], pnpm-audit[:<root>])
|
|
175
|
+
// read that root's whole install graph, so they run only for these (GC-A03). A Rust-only closure, or a sample app's own root, has none.
|
|
176
|
+
const closureNpmRoots = new Set(npmUnits.filter((u) => closure.npm.has(u.name)).map((u) => cleanWorkspace(u.root ?? ".")));
|
|
173
177
|
const names = rustUnits.map((u) => u.name).sort((a, b) => b.length - a.length);
|
|
174
178
|
// The Cargo workspaces that hold a unit of the closure: a workspace-level Cargo scan (metadata, deny, audit) runs only for these.
|
|
175
179
|
const closureWorkspaces = new Set(rustUnits.filter((u) => closure.rust.has(u.name)).map((u) => cleanWorkspace(u.cargoDir)));
|
|
@@ -179,12 +183,14 @@ export function scopeScans(scans, closure, { rustUnits = [] } = {}) {
|
|
|
179
183
|
const rust = /^(?:clippy|check|check-features|check-dependent|doc|test:rust|test:rust-serial):(.+)$/.exec(s.id);
|
|
180
184
|
const cargoList = CARGO_PACKAGE_LIST.exec(s.id);
|
|
181
185
|
let include = true;
|
|
182
|
-
if (npm) include = closure.npm.has(npm
|
|
186
|
+
if (s.internal === "refuse" && s.unit?.npm) include = closure.npm.has(s.unit.npm);
|
|
187
|
+
else if (npm) include = closure.npm.has(npm[1]);
|
|
183
188
|
else if (cargoList) {
|
|
184
189
|
if (!names.includes(cargoList[1])) throw problem(`scan ${s.id} has no known Rust owner`);
|
|
185
190
|
include = closure.rust.has(cargoList[1]);
|
|
186
191
|
}
|
|
187
192
|
else if (CARGO_WORKSPACE_SCAN.test(s.id)) include = closureWorkspaces.has(cleanWorkspace(s.cwd));
|
|
193
|
+
else if (/^pnpm-(?:lockfile|audit)(?::.+)?$/.test(s.id)) include = closureNpmRoots.has(cleanWorkspace(s.cwd));
|
|
188
194
|
else if (/^cargo-/.test(s.id)) throw problem(`executing scan ${s.id} has no exact scope owner`);
|
|
189
195
|
else if (Array.isArray(s.batch?.units)) {
|
|
190
196
|
const selected = s.batch.units.filter((n) => closure.rust.has(n));
|
|
Binary file
|