@rightkit/release 0.2.142 → 0.2.144
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/build-release.mjs +13 -2
- package/cli/right-release.mjs +3 -0
- package/github-release.mjs +9 -0
- package/install-app.mjs +132 -22
- package/ownership-approval.mjs +14 -1
- package/ownership-command.mjs +48 -2
- package/ownership-declaration.json +175 -4
- package/ownership-dependency-allowlist-seed.mjs +86 -0
- package/ownership-dependency-allowlist.json +1087 -0
- package/ownership-dependency-allowlist.mjs +124 -0
- package/ownership-evidence.mjs +13 -2
- package/ownership-key-command.mjs +55 -13
- package/ownership-key-elevation.mjs +114 -8
- package/ownership-key-trust.mjs +25 -4
- package/ownership-policy-bundle.mjs +155 -0
- package/ownership-report-command.mjs +1 -1
- package/ownership-trust-summary.mjs +119 -0
- package/ownership-windows-presence.mjs +171 -0
- package/ownership.mjs +42 -6
- package/package.json +1 -1
- package/protected-credentials.mjs +6 -1
- package/publish-update.mjs +8 -1
- package/release-qa-command.mjs +145 -0
- package/release-qa-floor.json +9 -0
- package/release-qa-receipt.mjs +276 -0
- package/release.mjs +1 -1
- package/rightkit-drift.mjs +1 -1
- package/rightkit-ownership.json +2276 -429
- package/rightkit-sync.mjs +3 -0
- package/rightkit-versions.json +9 -6
- package/upload-release.mjs +8 -1
|
@@ -3,12 +3,183 @@
|
|
|
3
3
|
"capabilities": [
|
|
4
4
|
{
|
|
5
5
|
"capability": "release-tooling",
|
|
6
|
-
"summary": "Portable release CLI/SDK with fail-closed public GitHub Releases and private R2 + RightApps distribution
|
|
7
|
-
"fingerprints": [
|
|
8
|
-
|
|
6
|
+
"summary": "Portable release CLI/SDK with fail-closed public GitHub Releases and private R2 + RightApps distribution.",
|
|
7
|
+
"fingerprints": [
|
|
8
|
+
{
|
|
9
|
+
"id": "release.sign.codesign-signtool",
|
|
10
|
+
"type": "source",
|
|
11
|
+
"pattern": "\\b(?:Command\\s*::\\s*new|spawn\\w*|execFile\\w*|exec\\w*)\\s*\\(\\s*(?:[\"`]\\s*(?:codesign\\b[^\"`';]{0,160}--sign|signtool(?:\\.exe)?\\s+sign\\b)|[\"'](?:codesign|signtool(?:\\.exe)?)[\"'][^;]{0,300}?[\"'](?:--sign|sign)[\"'])",
|
|
12
|
+
"codeOnly": true,
|
|
13
|
+
"extensions": [
|
|
14
|
+
".ts",
|
|
15
|
+
".tsx",
|
|
16
|
+
".js",
|
|
17
|
+
".mjs",
|
|
18
|
+
".cjs",
|
|
19
|
+
".jsx",
|
|
20
|
+
".rs",
|
|
21
|
+
".py"
|
|
22
|
+
],
|
|
23
|
+
"tier": "advise",
|
|
24
|
+
"usageContext": {
|
|
25
|
+
"hosts": [
|
|
26
|
+
"macos",
|
|
27
|
+
"windows"
|
|
28
|
+
],
|
|
29
|
+
"scope": "Executable code only; authenticated owner provenance required for exclusions"
|
|
30
|
+
},
|
|
31
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "release.notarize.notarytool",
|
|
35
|
+
"type": "source",
|
|
36
|
+
"pattern": "\\b(?:Command\\s*::\\s*new|spawn\\w*|execFile\\w*|exec\\w*)\\s*\\([^;]{0,200}?[\"'`\\s]notarytool\\b",
|
|
37
|
+
"codeOnly": true,
|
|
38
|
+
"extensions": [
|
|
39
|
+
".ts",
|
|
40
|
+
".tsx",
|
|
41
|
+
".js",
|
|
42
|
+
".mjs",
|
|
43
|
+
".cjs",
|
|
44
|
+
".jsx",
|
|
45
|
+
".rs",
|
|
46
|
+
".py"
|
|
47
|
+
],
|
|
48
|
+
"tier": "advise",
|
|
49
|
+
"usageContext": {
|
|
50
|
+
"hosts": [
|
|
51
|
+
"macos",
|
|
52
|
+
"windows"
|
|
53
|
+
],
|
|
54
|
+
"scope": "Executable code only; authenticated owner provenance required for exclusions"
|
|
55
|
+
},
|
|
56
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": "release.npm.electron-builder",
|
|
60
|
+
"type": "dependency",
|
|
61
|
+
"ecosystem": "npm",
|
|
62
|
+
"name": "electron-builder",
|
|
63
|
+
"tier": "advise",
|
|
64
|
+
"usageContext": {
|
|
65
|
+
"hosts": [
|
|
66
|
+
"macos",
|
|
67
|
+
"windows"
|
|
68
|
+
],
|
|
69
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
70
|
+
},
|
|
71
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "release.npm.electron-notarize",
|
|
75
|
+
"type": "dependency",
|
|
76
|
+
"ecosystem": "npm",
|
|
77
|
+
"name": "electron-notarize",
|
|
78
|
+
"tier": "advise",
|
|
79
|
+
"usageContext": {
|
|
80
|
+
"hosts": [
|
|
81
|
+
"macos",
|
|
82
|
+
"windows"
|
|
83
|
+
],
|
|
84
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
85
|
+
},
|
|
86
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "release.npm.electron-notarize-scoped",
|
|
90
|
+
"type": "dependency",
|
|
91
|
+
"ecosystem": "npm",
|
|
92
|
+
"name": "@electron/notarize",
|
|
93
|
+
"tier": "advise",
|
|
94
|
+
"usageContext": {
|
|
95
|
+
"hosts": [
|
|
96
|
+
"macos",
|
|
97
|
+
"windows"
|
|
98
|
+
],
|
|
99
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
100
|
+
},
|
|
101
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "release.npm.electron-osx-sign",
|
|
105
|
+
"type": "dependency",
|
|
106
|
+
"ecosystem": "npm",
|
|
107
|
+
"name": "electron-osx-sign",
|
|
108
|
+
"tier": "advise",
|
|
109
|
+
"usageContext": {
|
|
110
|
+
"hosts": [
|
|
111
|
+
"macos",
|
|
112
|
+
"windows"
|
|
113
|
+
],
|
|
114
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
115
|
+
},
|
|
116
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "release.npm.electron-osx-sign-scoped",
|
|
120
|
+
"type": "dependency",
|
|
121
|
+
"ecosystem": "npm",
|
|
122
|
+
"name": "@electron/osx-sign",
|
|
123
|
+
"tier": "advise",
|
|
124
|
+
"usageContext": {
|
|
125
|
+
"hosts": [
|
|
126
|
+
"macos",
|
|
127
|
+
"windows"
|
|
128
|
+
],
|
|
129
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
130
|
+
},
|
|
131
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"id": "release.npm.create-dmg",
|
|
135
|
+
"type": "dependency",
|
|
136
|
+
"ecosystem": "npm",
|
|
137
|
+
"name": "create-dmg",
|
|
138
|
+
"tier": "advise",
|
|
139
|
+
"usageContext": {
|
|
140
|
+
"hosts": [
|
|
141
|
+
"macos",
|
|
142
|
+
"windows"
|
|
143
|
+
],
|
|
144
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
145
|
+
},
|
|
146
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": "release.npm.appdmg",
|
|
150
|
+
"type": "dependency",
|
|
151
|
+
"ecosystem": "npm",
|
|
152
|
+
"name": "appdmg",
|
|
153
|
+
"tier": "advise",
|
|
154
|
+
"usageContext": {
|
|
155
|
+
"hosts": [
|
|
156
|
+
"macos",
|
|
157
|
+
"windows"
|
|
158
|
+
],
|
|
159
|
+
"scope": "npm direct competing dependency; transitive findings require authenticated reachability"
|
|
160
|
+
},
|
|
161
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"id": "release.cargo.apple-codesign",
|
|
165
|
+
"type": "dependency",
|
|
166
|
+
"ecosystem": "cargo",
|
|
167
|
+
"name": "apple-codesign",
|
|
168
|
+
"tier": "advise",
|
|
169
|
+
"usageContext": {
|
|
170
|
+
"hosts": [
|
|
171
|
+
"macos",
|
|
172
|
+
"windows"
|
|
173
|
+
],
|
|
174
|
+
"scope": "cargo direct competing dependency; transitive findings require authenticated reachability"
|
|
175
|
+
},
|
|
176
|
+
"tierReason": "No recorded published-version qualification for this usage context on both macOS & Windows."
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"detection": "fingerprinted",
|
|
9
180
|
"policyNotes": [
|
|
10
181
|
"Package contract retained; dependency declarations do not verify integration.",
|
|
11
|
-
"
|
|
182
|
+
"Fingerprints identify review candidates (competing dependencies and distinctive implementation code); published two-host replacement qualification is not recorded."
|
|
12
183
|
]
|
|
13
184
|
}
|
|
14
185
|
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Propose or regenerate dependency-allowlist baselines from each registered repository's CURRENT direct
|
|
3
|
+
// dependencies. This only edits the committed proposal file; it takes effect solely through Adrian's trust-sync.
|
|
4
|
+
// node ownership-dependency-allowlist-seed.mjs --workspace <dir> [--write]
|
|
5
|
+
// Existing approvals are never removed (union with the current file); block-tier catalog dependencies
|
|
6
|
+
// and RightKit packages are never recorded as approvals.
|
|
7
|
+
import { existsSync, readdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { spawnSync } from "./background-process.mjs";
|
|
11
|
+
import { canonicalRepositoryIdentity } from "./ownership-approval.mjs";
|
|
12
|
+
import { directDependencies } from "./ownership.mjs";
|
|
13
|
+
import { ALLOWLIST_FILE, entryKey, isRightKitPackage, sourceKind, validateAllowlist } from "./ownership-dependency-allowlist.mjs";
|
|
14
|
+
|
|
15
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const readJson = (name) => JSON.parse(readFileSync(path.join(here, name), "utf8"));
|
|
17
|
+
|
|
18
|
+
// Universally approved tooling: tiny on purpose. Everything else is per-repository.
|
|
19
|
+
export const SEED_GLOBAL = Object.freeze(["npm:@types/node", "npm:typescript", "npm:vitest"]);
|
|
20
|
+
// A renamed repository that has no checkout of its own reuses the baseline of its current name.
|
|
21
|
+
export const SEED_ALIASES = Object.freeze({ "https://github.com/orthic-labs/cockpit": "https://github.com/orthic-labs/pulse" });
|
|
22
|
+
|
|
23
|
+
function localCheckouts(workspace) {
|
|
24
|
+
const found = new Map();
|
|
25
|
+
for (const name of readdirSync(workspace)) {
|
|
26
|
+
const dir = path.join(workspace, name);
|
|
27
|
+
if (!existsSync(path.join(dir, ".git"))) continue;
|
|
28
|
+
const origin = spawnSync("git", ["-C", dir, "config", "--get", "remote.origin.url"], { encoding: "utf8", windowsHide: true });
|
|
29
|
+
if (origin.status !== 0) continue;
|
|
30
|
+
try { found.set(canonicalRepositoryIdentity(origin.stdout.trim()), dir); } catch { /* not a canonical remote */ }
|
|
31
|
+
}
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function seedRepository(root, manifest) {
|
|
36
|
+
const blocked = new Set(manifest.capabilities.flatMap((c) => c.fingerprints.filter((f) => f.type === "dependency" && (f.tier ?? c.tier ?? "block") === "block").map((f) => `${f.ecosystem}:${f.name}`)));
|
|
37
|
+
const owners = manifest.capabilities.map((c) => c.package);
|
|
38
|
+
const entries = new Set(); let skippedBlock = 0, skippedFirstParty = 0, skippedRightKit = 0;
|
|
39
|
+
const deps = directDependencies(root);
|
|
40
|
+
for (const d of deps) {
|
|
41
|
+
const kind = sourceKind(d.source);
|
|
42
|
+
if (kind === "path") { skippedFirstParty += 1; continue; }
|
|
43
|
+
if (isRightKitPackage(d.name, owners)) { skippedRightKit += 1; continue; }
|
|
44
|
+
if (blocked.has(`${d.ecosystem}:${d.name}`)) { skippedBlock += 1; continue; }
|
|
45
|
+
entries.add(entryKey(d.ecosystem, d.name, kind));
|
|
46
|
+
}
|
|
47
|
+
return { entries: [...entries].sort(), direct: deps.length, skippedBlock, skippedFirstParty, skippedRightKit, unscanned: deps.coverage?.length ?? 0 };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildSeed({ workspace, registry = readJson("ownership-repositories.json"), manifest = readJson("rightkit-ownership.json"), existing = null, log = () => {} } = {}) {
|
|
51
|
+
const checkouts = localCheckouts(workspace);
|
|
52
|
+
const previous = new Map((existing?.repositories ?? []).map((entry) => [entry.repositoryIdentity, entry]));
|
|
53
|
+
const seeded = new Map(), stats = [];
|
|
54
|
+
for (const { repositoryIdentity } of registry.repositories) {
|
|
55
|
+
const root = checkouts.get(repositoryIdentity);
|
|
56
|
+
if (!root) continue;
|
|
57
|
+
const result = seedRepository(root, manifest);
|
|
58
|
+
seeded.set(repositoryIdentity, result.entries);
|
|
59
|
+
stats.push({ repositoryIdentity, root, ...result });
|
|
60
|
+
}
|
|
61
|
+
const repositories = registry.repositories.map(({ repositoryIdentity }) => {
|
|
62
|
+
const prior = previous.get(repositoryIdentity)?.dependencies ?? [];
|
|
63
|
+
let note;
|
|
64
|
+
let fresh = seeded.get(repositoryIdentity);
|
|
65
|
+
if (!fresh && SEED_ALIASES[repositoryIdentity] && seeded.has(SEED_ALIASES[repositoryIdentity])) { fresh = seeded.get(SEED_ALIASES[repositoryIdentity]); note = `seeded from ${SEED_ALIASES[repositoryIdentity]} (same repository, renamed)`; stats.push({ repositoryIdentity, alias: SEED_ALIASES[repositoryIdentity], entries: fresh }); }
|
|
66
|
+
if (!fresh) { fresh = []; note = "no local checkout when seeded; baseline is empty until proposed"; stats.push({ repositoryIdentity, unseeded: true, entries: [] }); }
|
|
67
|
+
return { repositoryIdentity, ...(note ? { note } : {}), dependencies: [...new Set([...prior, ...fresh])].sort() };
|
|
68
|
+
});
|
|
69
|
+
const allowlist = { schema: 1, global: [...new Set([...(existing?.global ?? []), ...SEED_GLOBAL])].sort(), repositories };
|
|
70
|
+
const check = validateAllowlist(allowlist);
|
|
71
|
+
if (!check.ok) throw new Error(`generated allowlist is invalid: ${check.problems.join("; ")}`);
|
|
72
|
+
log(stats);
|
|
73
|
+
return { allowlist, stats };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const realOrSelf = (file) => { try { return realpathSync(file); } catch { return path.resolve(file); } };
|
|
77
|
+
if (process.argv[1] && realOrSelf(process.argv[1]) === realOrSelf(fileURLToPath(import.meta.url))) {
|
|
78
|
+
const args = process.argv.slice(2);
|
|
79
|
+
const flag = (name) => { const i = args.indexOf(name); return i < 0 ? undefined : args[i + 1]; };
|
|
80
|
+
const workspace = path.resolve(flag("--workspace") ?? path.resolve(here, "../../.."));
|
|
81
|
+
const file = path.join(here, ALLOWLIST_FILE);
|
|
82
|
+
const existing = existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : null;
|
|
83
|
+
const { allowlist, stats } = buildSeed({ workspace, existing });
|
|
84
|
+
for (const s of stats) process.stdout.write(`${s.repositoryIdentity}: ${s.entries.length} entries${s.direct !== undefined ? ` (direct ${s.direct}, first-party ${s.skippedFirstParty}, rightkit ${s.skippedRightKit}, block-tier ${s.skippedBlock}, unscanned ${s.unscanned})` : s.alias ? ` (alias of ${s.alias})` : " (UNSEEDED)"}\n`);
|
|
85
|
+
if (args.includes("--write")) { writeFileSync(file, `${JSON.stringify(allowlist, null, 2)}\n`); process.stdout.write(`wrote ${file}\n`); }
|
|
86
|
+
}
|