@bluenotelogic/harness 0.1.0 → 0.2.0
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/CHANGELOG.md +114 -0
- package/NOTICE +5 -0
- package/README.md +175 -20
- package/assets/antigravity-plugin/README.md +69 -0
- package/assets/antigravity-plugin/hooks.json +77 -0
- package/assets/antigravity-plugin/plugin.json +5 -0
- package/assets/antigravity-plugin/rules/proofmem.md +9 -0
- package/assets/antigravity-plugin/scripts/antigravity-hook.mjs +630 -0
- package/assets/antigravity-plugin/scripts/resolve-bash.mjs +48 -0
- package/dist/antigravity.d.ts +26 -0
- package/dist/antigravity.js +118 -0
- package/dist/antigravity.js.map +1 -0
- package/dist/bundle.d.ts +22 -0
- package/dist/bundle.js +36 -1
- package/dist/bundle.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +398 -64
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +44 -3
- package/dist/oauth.js +106 -11
- package/dist/oauth.js.map +1 -1
- package/dist/writers.d.ts +57 -15
- package/dist/writers.js +258 -58
- package/dist/writers.js.map +1 -1
- package/package.json +10 -4
package/dist/writers.js
CHANGED
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* `--dry-run` shows precisely what would happen and the merge logic is unit-testable
|
|
14
14
|
* without touching a filesystem.
|
|
15
15
|
*/
|
|
16
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
17
|
-
import { dirname } from "node:path";
|
|
16
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, statSync, unlinkSync } from "node:fs";
|
|
17
|
+
import { dirname, join } from "node:path";
|
|
18
|
+
import { execFileSync } from "node:child_process";
|
|
18
19
|
/** True when the change would actually alter the file. */
|
|
19
20
|
export function isNoop(c) {
|
|
20
21
|
return c.after === null || c.after === c.before;
|
|
@@ -54,88 +55,136 @@ export function planMcpJson(path, existing, servers) {
|
|
|
54
55
|
doc["mcpServers"] = { ...current, ...servers };
|
|
55
56
|
return { path, before: existing, after: JSON.stringify(doc, null, 2) + "\n" };
|
|
56
57
|
}
|
|
57
|
-
/**
|
|
58
|
-
* `.claude/settings.local.json` — an `env` block Claude Code applies to every session.
|
|
59
|
-
*
|
|
60
|
-
* WHY THIS EXISTS AT ALL: the VS Code extension launches `claude` without sourcing a shell
|
|
61
|
-
* env file, so a `${VAR}` reference in `.mcp.json` would not expand there. This file is how
|
|
62
|
-
* the harness works from the VS Code button rather than only from `source .env && claude`.
|
|
63
|
-
* Only written when a token was minted — the OAuth path needs no env at all.
|
|
64
|
-
*/
|
|
65
|
-
export function planSettingsLocal(path, existing, env) {
|
|
66
|
-
let doc = {};
|
|
67
|
-
if (existing !== null && existing.trim() !== "") {
|
|
68
|
-
try {
|
|
69
|
-
const parsed = JSON.parse(existing);
|
|
70
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
71
|
-
throw new Error("not a JSON object");
|
|
72
|
-
}
|
|
73
|
-
doc = parsed;
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
return {
|
|
77
|
-
path,
|
|
78
|
-
before: existing,
|
|
79
|
-
after: null,
|
|
80
|
-
skipped: `existing settings.local.json is not valid JSON (${e.message}) — left untouched.`,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const currentEnv = typeof doc["env"] === "object" && doc["env"] !== null && !Array.isArray(doc["env"])
|
|
85
|
-
? doc["env"]
|
|
86
|
-
: {};
|
|
87
|
-
doc["env"] = { ...currentEnv, ...env };
|
|
88
|
-
return {
|
|
89
|
-
path,
|
|
90
|
-
before: existing,
|
|
91
|
-
after: JSON.stringify(doc, null, 2) + "\n",
|
|
92
|
-
note: "holds a plaintext token — make sure .claude/settings.local.json is gitignored",
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
58
|
/**
|
|
96
59
|
* Codex `config.toml`.
|
|
97
60
|
*
|
|
98
|
-
* We do NOT parse TOML (that would mean a dependency, and this package has none).
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* tables are order-independent, and appending can never corrupt what is already there.
|
|
61
|
+
* We do NOT parse TOML (that would mean a dependency, and this package has none). The active
|
|
62
|
+
* writer below owns one explicit marked block, replaces only that block, and refuses ambiguous
|
|
63
|
+
* unowned conflicts while preserving all unrelated TOML.
|
|
102
64
|
*
|
|
103
65
|
* The token itself never goes in here — it goes to `~/.codex/.env`, referenced by
|
|
104
66
|
* `bearer_token_env_var`, so the config file stays safe to read over someone's shoulder.
|
|
105
67
|
*/
|
|
68
|
+
/** Stable Codex approval surface. Token grants still enforce the daily/maintainer boundary. */
|
|
69
|
+
export const CODEX_MAINTAINER_APPROVED_TOOLS = [
|
|
70
|
+
"memory_bootstrap", "memory_context", "memory_recall", "memory_recall_repo",
|
|
71
|
+
"memory_propose", "memory_feedback",
|
|
72
|
+
"memory_scratch_set", "memory_scratch_get", "memory_scratch_delete",
|
|
73
|
+
"memory_episodic_log", "memory_episodic_recall",
|
|
74
|
+
"harness_run_start", "harness_run_step", "harness_run_complete", "harness_run_list",
|
|
75
|
+
"memory_review", "memory_v3_status", "harness_run_release",
|
|
76
|
+
];
|
|
77
|
+
/** Codex config writer for the one block owned by this installer. */
|
|
106
78
|
export function planCodexConfig(path, existing, serverName, mcpUrl, tokenEnvVar) {
|
|
79
|
+
const start = "# BEGIN @bluenotelogic/harness managed MCP";
|
|
80
|
+
const end = "# END @bluenotelogic/harness managed MCP";
|
|
107
81
|
const table = `[mcp_servers.${serverName}]`;
|
|
108
|
-
const
|
|
109
|
-
|
|
82
|
+
const approvals = CODEX_MAINTAINER_APPROVED_TOOLS.map((tool) => `\n[mcp_servers.${serverName}.tools.${tool}]\napproval_mode = "approve"\n`).join("");
|
|
83
|
+
const block = `${start}\n` +
|
|
84
|
+
`# Credentials are environment-only; the owner-restricted value lives in ~/.codex/.env.\n` +
|
|
110
85
|
`${table}\n` +
|
|
111
86
|
`url = "${mcpUrl}"\n` +
|
|
112
|
-
`bearer_token_env_var = "${tokenEnvVar}"\n
|
|
113
|
-
|
|
87
|
+
`bearer_token_env_var = "${tokenEnvVar}"\n` +
|
|
88
|
+
`default_tools_approval_mode = "prompt"\n` +
|
|
89
|
+
approvals +
|
|
90
|
+
`${end}\n`;
|
|
91
|
+
const base = existing ?? "";
|
|
92
|
+
const startCount = base.split(start).length - 1;
|
|
93
|
+
const endCount = base.split(end).length - 1;
|
|
94
|
+
if (startCount !== endCount || startCount > 1) {
|
|
95
|
+
return { path, before: existing, after: null, skipped: "ambiguous @bluenotelogic/harness managed-block markers; left untouched" };
|
|
96
|
+
}
|
|
97
|
+
if (startCount === 1) {
|
|
98
|
+
const from = base.indexOf(start);
|
|
99
|
+
const through = base.indexOf(end, from) + end.length;
|
|
100
|
+
const after = `${base.slice(0, from)}${block}${base.slice(through).replace(/^\r?\n/, "")}`;
|
|
101
|
+
return { path, before: existing, after };
|
|
102
|
+
}
|
|
103
|
+
const legacy = /\n?# Added by @bluenotelogic\/harness\. Codex cannot do OAuth yet, so it reads a token\r?\n# from the environment; the value lives in ~\/\.codex\/\.env, never in this file\.\r?\n\[mcp_servers\.([^\]\r\n]+)\]\r?\nurl = "[^"\r\n]+"\r?\nbearer_token_env_var = "[A-Za-z_][A-Za-z0-9_]*"\r?\n?/g;
|
|
104
|
+
const matches = [...base.matchAll(legacy)];
|
|
105
|
+
if (matches.length > 1) {
|
|
106
|
+
return { path, before: existing, after: null, skipped: "multiple legacy harness blocks are ambiguous; left untouched" };
|
|
107
|
+
}
|
|
108
|
+
if (matches.length === 1) {
|
|
109
|
+
const match = matches[0];
|
|
110
|
+
const index = match.index;
|
|
111
|
+
const without = `${base.slice(0, index)}${base.slice(index + match[0].length)}`.trimEnd();
|
|
112
|
+
return { path, before: existing, after: `${without}${without ? "\n\n" : ""}${block}` };
|
|
113
|
+
}
|
|
114
|
+
// `codex mcp add` writes this exact, tokenless three-line table. It is safe to adopt only
|
|
115
|
+
// when its URL and env reference already match the requested installation and the table has
|
|
116
|
+
// no child settings; any different or extended table remains an ambiguous unowned conflict.
|
|
117
|
+
const childTablePrefix = `[mcp_servers.${serverName}.`;
|
|
118
|
+
if (base.includes(childTablePrefix)) {
|
|
114
119
|
return {
|
|
115
120
|
path,
|
|
116
121
|
before: existing,
|
|
117
122
|
after: null,
|
|
118
|
-
skipped: `${table}
|
|
119
|
-
block.trim(),
|
|
123
|
+
skipped: `${table} has unowned child settings; ownership is ambiguous, so it was left untouched.`,
|
|
120
124
|
};
|
|
121
125
|
}
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
const exactCliTable = new RegExp(`(?:^|\\r?\\n)${escapeRe(table)}\\r?\\n` +
|
|
127
|
+
`url = "${escapeRe(mcpUrl)}"\\r?\\n` +
|
|
128
|
+
`bearer_token_env_var = "${escapeRe(tokenEnvVar)}"\\r?\\n?` +
|
|
129
|
+
`(?=\\r?\\n\\[|$)`);
|
|
130
|
+
const cliMatch = base.match(exactCliTable);
|
|
131
|
+
if (cliMatch?.index !== undefined) {
|
|
132
|
+
const without = `${base.slice(0, cliMatch.index)}${base.slice(cliMatch.index + cliMatch[0].length)}`.trimEnd();
|
|
133
|
+
return { path, before: existing, after: `${without}${without ? "\n\n" : ""}${block}` };
|
|
134
|
+
}
|
|
135
|
+
if (base.includes(table)) {
|
|
136
|
+
return {
|
|
137
|
+
path,
|
|
138
|
+
before: existing,
|
|
139
|
+
after: null,
|
|
140
|
+
skipped: `${table} exists outside the @bluenotelogic/harness managed block; ownership is ambiguous, so it was left untouched.`,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const withoutTrailing = base.trimEnd();
|
|
144
|
+
return { path, before: existing, after: `${withoutTrailing}${withoutTrailing ? "\n\n" : ""}${block}` };
|
|
125
145
|
}
|
|
126
|
-
/**
|
|
127
|
-
export function
|
|
146
|
+
/** The names (never the values) of `names` that a dotenv file defines, in the order given. */
|
|
147
|
+
export function legacyEnvVarsPresent(existing, names) {
|
|
148
|
+
if (existing === null)
|
|
149
|
+
return [];
|
|
150
|
+
return names.filter((name) => new RegExp(`^${escapeRe(name)}=`, "m").test(existing));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Set `key` in a dotenv file, leaving every other line as it was.
|
|
154
|
+
*
|
|
155
|
+
* `legacyAliases` are earlier names for the same credential. They are NOT removed: this used to
|
|
156
|
+
* delete them, but BNL staff machines still run tools that read BNL_MEMORY_MCP_TOKEN /
|
|
157
|
+
* CAVEAU_MCP_TOKEN, so a re-install would have broken those tools. The ones present are named
|
|
158
|
+
* in a notice instead, so the user can remove them once nothing uses them.
|
|
159
|
+
*/
|
|
160
|
+
export function planEnvVar(path, existing, key, value, legacyAliases = []) {
|
|
128
161
|
const line = `${key}=${value}`;
|
|
129
162
|
const base = existing ?? "";
|
|
130
163
|
const re = new RegExp(`^${escapeRe(key)}=.*$`, "m");
|
|
131
164
|
const after = re.test(base)
|
|
132
165
|
? base.replace(re, line)
|
|
133
166
|
: base + (base === "" || base.endsWith("\n") ? "" : "\n") + line + "\n";
|
|
167
|
+
const legacy = legacyEnvVarsPresent(existing, legacyAliases.filter((alias) => alias !== key));
|
|
168
|
+
const them = legacy.length > 1 ? "them" : "it";
|
|
134
169
|
return {
|
|
135
170
|
path,
|
|
136
171
|
before: existing,
|
|
137
172
|
after,
|
|
138
173
|
note: "holds a plaintext token — never commit it",
|
|
174
|
+
...(legacy.length
|
|
175
|
+
? { notice: `legacy ${legacy.join(", ")} left in place; ${key} is now used, so remove ${them} once nothing uses ${them}` }
|
|
176
|
+
: {}),
|
|
177
|
+
sensitive: true,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** Plan one owner-only credential file whose entire contents are the supplied value. */
|
|
181
|
+
export function planCredentialFile(path, existing, value, note = "holds a plaintext token — never commit or share it") {
|
|
182
|
+
return {
|
|
183
|
+
path,
|
|
184
|
+
before: existing,
|
|
185
|
+
after: `${value.replace(/[\r\n]+$/g, "")}\n`,
|
|
186
|
+
note,
|
|
187
|
+
sensitive: true,
|
|
139
188
|
};
|
|
140
189
|
}
|
|
141
190
|
function escapeRe(s) {
|
|
@@ -163,8 +212,8 @@ export function assertNoSecret(c) {
|
|
|
163
212
|
const found = c.after.match(/\b(cmem|mcp)_[A-Za-z0-9_-]{16,}/);
|
|
164
213
|
if (found) {
|
|
165
214
|
throw new Error(`refusing to write what looks like a live token into ${c.path} ` +
|
|
166
|
-
`(matched ${found[0].slice(0, 8)}…). Tokens belong in ~/.codex/.env
|
|
167
|
-
|
|
215
|
+
`(matched ${found[0].slice(0, 8)}…). Tokens belong only in ~/.codex/.env, never in a ` +
|
|
216
|
+
`repository file.`);
|
|
168
217
|
}
|
|
169
218
|
}
|
|
170
219
|
export function readIfExists(path) {
|
|
@@ -175,6 +224,137 @@ export function readIfExists(path) {
|
|
|
175
224
|
return null;
|
|
176
225
|
}
|
|
177
226
|
}
|
|
227
|
+
const UNSAFE_WINDOWS_PRINCIPALS = ["Everyone", "BUILTIN\\Users", "Authenticated Users", "Users"];
|
|
228
|
+
/**
|
|
229
|
+
* Confirms `icacls <path>` output grants access to nobody broader than the given owner.
|
|
230
|
+
* Exported (rather than folded into secureCredentialFileWindows) so this has real unit
|
|
231
|
+
* coverage without shelling out to icacls in a test -- icacls output is the only part of
|
|
232
|
+
* Windows ACL handling that is pure and deterministic; the actual system calls are not.
|
|
233
|
+
*
|
|
234
|
+
* Match a complete principal immediately before `:(`. A plain substring check is unsafe here:
|
|
235
|
+
* the sandbox-local `CodexSandboxUsers` principal ends in `Users`, so searching for `Users:(`
|
|
236
|
+
* incorrectly treats that narrow execution group as the broad built-in Users group. The left
|
|
237
|
+
* boundary deliberately excludes every character valid inside the account names we encounter,
|
|
238
|
+
* including backslash and hyphen; this also keeps `DAVE-NEW\david` intact.
|
|
239
|
+
*/
|
|
240
|
+
export function assertWindowsAclIsOwnerOnly(icaclsOutput, owner, path) {
|
|
241
|
+
const hasPrincipal = (principal) => {
|
|
242
|
+
const escaped = escapeRe(principal);
|
|
243
|
+
return new RegExp(`(?:^|[^A-Za-z0-9_.\\\\-])${escaped}:\\(`, "im").test(icaclsOutput);
|
|
244
|
+
};
|
|
245
|
+
const unsafe = UNSAFE_WINDOWS_PRINCIPALS.filter(hasPrincipal);
|
|
246
|
+
if (unsafe.length > 0) {
|
|
247
|
+
throw new Error(`${path} still grants access to ${unsafe.join(", ")} after tightening its ACL`);
|
|
248
|
+
}
|
|
249
|
+
// An ACL that granted nothing to anyone would pass the check above while leaving the file
|
|
250
|
+
// unreadable by its own owner -- a different bug this must not let through silently.
|
|
251
|
+
if (!hasPrincipal(owner)) {
|
|
252
|
+
throw new Error(`${path}'s ACL does not grant the current user (${owner}) after tightening it`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Proves a DACL (SDDL form, from Get-Acl) is OWNER-ONLY: protected from inheritance, and every
|
|
257
|
+
* allow ACE names the current user's SID. This is the authoritative check; the icacls one above
|
|
258
|
+
* is a denylist of English group names, so it waved through a German `VORDEFINIERT\Benutzer`,
|
|
259
|
+
* a stray explicit grant to another account, and sandbox groups. SIDs read the same in every
|
|
260
|
+
* language.
|
|
261
|
+
*/
|
|
262
|
+
export function assertWindowsSddlIsOwnerOnly(sddl, userSid, path) {
|
|
263
|
+
const dacl = /D:([A-Z]*)((?:\([^)]*\))*)/.exec(sddl);
|
|
264
|
+
if (!dacl)
|
|
265
|
+
throw new Error(`could not read the access control list of ${path}`);
|
|
266
|
+
if (!(dacl[1] ?? "").includes("P")) {
|
|
267
|
+
throw new Error(`${path} still inherits permissions from its folder after tightening its ACL`);
|
|
268
|
+
}
|
|
269
|
+
const allows = [...(dacl[2] ?? "").matchAll(/\(([^)]*)\)/g)]
|
|
270
|
+
.map((m) => (m[1] ?? "").split(";"))
|
|
271
|
+
.filter((fields) => fields[0] === "A" || fields[0] === "OA");
|
|
272
|
+
const others = allows
|
|
273
|
+
.map((fields) => fields[5] ?? "")
|
|
274
|
+
.filter((sid) => sid.toUpperCase() !== userSid.toUpperCase());
|
|
275
|
+
if (others.length > 0) {
|
|
276
|
+
throw new Error(`${path} still grants access to ${others.join(", ")} besides the current user after tightening ` +
|
|
277
|
+
`its ACL (if this runs inside a sandbox, run the installer from a normal terminal)`);
|
|
278
|
+
}
|
|
279
|
+
if (allows.length === 0) {
|
|
280
|
+
throw new Error(`${path}'s ACL does not grant the current user after tightening it`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
function currentWindowsUserSid() {
|
|
284
|
+
// By absolute path: from Git Bash, a bare `whoami` resolves to MSYS coreutils, which has no /user.
|
|
285
|
+
const whoami = join(process.env["SystemRoot"] || "C:\\Windows", "System32", "whoami.exe");
|
|
286
|
+
const out = execFileSync(whoami, ["/user", "/fo", "csv", "/nh"], { encoding: "utf8", windowsHide: true });
|
|
287
|
+
const sid = /S-1-\d+(?:-\d+)+/.exec(out)?.[0];
|
|
288
|
+
if (!sid)
|
|
289
|
+
throw new Error("cannot determine the current Windows user's SID (whoami /user)");
|
|
290
|
+
return sid;
|
|
291
|
+
}
|
|
292
|
+
function powershell(command, extraEnv) {
|
|
293
|
+
// Values travel in the environment, never interpolated into the command text.
|
|
294
|
+
return execFileSync(join(process.env["SystemRoot"] || "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe"), ["-NoProfile", "-NonInteractive", "-Command", command], { encoding: "utf8", env: { ...process.env, ...extraEnv }, windowsHide: true }).trim();
|
|
295
|
+
}
|
|
296
|
+
function windowsSddl(path) {
|
|
297
|
+
return powershell("(Get-Acl -LiteralPath $env:BNL_HARNESS_ACL_PATH).Sddl", { BNL_HARNESS_ACL_PATH: path });
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Replace the DACL with exactly one entry, the current user. `icacls /grant:r` cannot do this: it
|
|
301
|
+
* replaces only the NAMED user's entry. Measured on a machine with Codex's Windows sandbox: every
|
|
302
|
+
* new file there arrives with an explicit `CodexSandboxUsers:(RX)` entry, which survived
|
|
303
|
+
* `/inheritance:r /grant:r` and left the credential readable by the sandbox group that runs
|
|
304
|
+
* agent commands.
|
|
305
|
+
*/
|
|
306
|
+
function setOwnerOnlyDacl(path, userSid) {
|
|
307
|
+
// GetAccessControl/SetAccessControl on the Access section only. Set-Acl rewrites the audit
|
|
308
|
+
// section too and fails without SeSecurityPrivilege.
|
|
309
|
+
powershell("$s = [System.Security.AccessControl.AccessControlSections]::Access; " +
|
|
310
|
+
"$i = Get-Item -LiteralPath $env:BNL_HARNESS_ACL_PATH; $a = $i.GetAccessControl($s); " +
|
|
311
|
+
"$a.SetSecurityDescriptorSddlForm('D:PAI(A;;FA;;;' + $env:BNL_HARNESS_ACL_SID + ')', $s); " +
|
|
312
|
+
"$i.SetAccessControl($a)", { BNL_HARNESS_ACL_PATH: path, BNL_HARNESS_ACL_SID: userSid });
|
|
313
|
+
}
|
|
314
|
+
function currentWindowsUser() {
|
|
315
|
+
const user = process.env["USERNAME"];
|
|
316
|
+
if (!user)
|
|
317
|
+
throw new Error("cannot determine the current Windows user (USERNAME is unset)");
|
|
318
|
+
const domain = process.env["USERDOMAIN"];
|
|
319
|
+
return domain ? `${domain}\\${user}` : user;
|
|
320
|
+
}
|
|
321
|
+
function secureCredentialFileWindows(path) {
|
|
322
|
+
const owner = currentWindowsUser();
|
|
323
|
+
// /inheritance:r drops whatever ACEs the file inherited from its parent directory;
|
|
324
|
+
// /grant:r REPLACES any existing explicit grants with exactly this one, rather than adding
|
|
325
|
+
// to them -- so re-running this on an already-tightened file converges instead of piling up.
|
|
326
|
+
execFileSync("icacls", [path, "/inheritance:r", "/grant:r", `${owner}:F`], { stdio: "ignore" });
|
|
327
|
+
const userSid = currentWindowsUserSid();
|
|
328
|
+
setOwnerOnlyDacl(path, userSid);
|
|
329
|
+
const verify = execFileSync("icacls", [path], { encoding: "utf8" });
|
|
330
|
+
assertWindowsAclIsOwnerOnly(verify, owner, path);
|
|
331
|
+
assertWindowsSddlIsOwnerOnly(windowsSddl(path), userSid, path);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Restrict a just-written credential file to the current user only, and PROVE it before
|
|
335
|
+
* returning -- a credential file whose protection could not be verified is worse than none,
|
|
336
|
+
* and the caller (apply()) deletes what it just wrote when this throws.
|
|
337
|
+
*/
|
|
338
|
+
export function secureCredentialFile(path) {
|
|
339
|
+
if (process.platform === "win32") {
|
|
340
|
+
secureCredentialFileWindows(path);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
chmodSync(path, 0o600);
|
|
344
|
+
const mode = statSync(path).mode & 0o777;
|
|
345
|
+
if (mode !== 0o600) {
|
|
346
|
+
throw new Error(`chmod 0600 did not take effect on ${path} (mode is 0${mode.toString(8)})`);
|
|
347
|
+
}
|
|
348
|
+
// Best-effort: the file's own 0600 is the load-bearing protection. A parent directory this
|
|
349
|
+
// process does not own (so chmod fails) is still reported by the outer try/catch in apply(),
|
|
350
|
+
// just not treated as fatal on its own -- only the file's own mode is asserted above.
|
|
351
|
+
try {
|
|
352
|
+
chmodSync(dirname(path), 0o700);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
/* best-effort */
|
|
356
|
+
}
|
|
357
|
+
}
|
|
178
358
|
export function apply(changes, dryRun) {
|
|
179
359
|
for (const c of changes) {
|
|
180
360
|
if (c.after === null || isNoop(c))
|
|
@@ -184,7 +364,27 @@ export function apply(changes, dryRun) {
|
|
|
184
364
|
const dir = dirname(c.path);
|
|
185
365
|
if (!existsSync(dir))
|
|
186
366
|
mkdirSync(dir, { recursive: true });
|
|
187
|
-
|
|
367
|
+
// A credential file is recreated, not rewritten in place: overwriting keeps the old file's
|
|
368
|
+
// ACL, and `icacls /grant:r` replaces only the named user's entry, so an explicit grant some
|
|
369
|
+
// earlier tool left on it would survive the tightening.
|
|
370
|
+
if (c.sensitive && existsSync(c.path))
|
|
371
|
+
unlinkSync(c.path);
|
|
372
|
+
writeFileSync(c.path, c.after, c.sensitive ? { encoding: "utf8", mode: 0o600 } : "utf8");
|
|
373
|
+
if (c.sensitive) {
|
|
374
|
+
try {
|
|
375
|
+
secureCredentialFile(c.path);
|
|
376
|
+
}
|
|
377
|
+
catch (e) {
|
|
378
|
+
try {
|
|
379
|
+
unlinkSync(c.path);
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
/* best-effort -- the thrown error below is what the user sees regardless */
|
|
383
|
+
}
|
|
384
|
+
throw new Error(`wrote ${c.path} but could not verify it is protected, so it was removed: ` +
|
|
385
|
+
`${e.message}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
188
388
|
}
|
|
189
389
|
}
|
|
190
390
|
//# sourceMappingURL=writers.js.map
|
package/dist/writers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writers.js","sourceRoot":"","sources":["../src/writers.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"writers.js","sourceRoot":"","sources":["../src/writers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bluenotelogic/harness",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "One command to
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "One command to connect Claude Code, Codex, VS Code, and Google Antigravity to ProofMEM with tokenless native OAuth MCP configuration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"bnl-harness": "dist/index.js"
|
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
+
"assets",
|
|
12
13
|
"README.md",
|
|
13
|
-
"
|
|
14
|
+
"CHANGELOG.md",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"NOTICE"
|
|
14
17
|
],
|
|
15
18
|
"scripts": {
|
|
16
19
|
"build": "tsc",
|
|
@@ -31,7 +34,8 @@
|
|
|
31
34
|
},
|
|
32
35
|
"repository": {
|
|
33
36
|
"type": "git",
|
|
34
|
-
"url": "https://git.bluenotelogic.com/bnl/bnlgit-harness"
|
|
37
|
+
"url": "https://git.bluenotelogic.com/bnl/bnlgit-harness",
|
|
38
|
+
"directory": "packages/cli"
|
|
35
39
|
},
|
|
36
40
|
"keywords": [
|
|
37
41
|
"mcp",
|
|
@@ -39,6 +43,8 @@
|
|
|
39
43
|
"oauth",
|
|
40
44
|
"claude-code",
|
|
41
45
|
"codex",
|
|
46
|
+
"antigravity",
|
|
47
|
+
"proofmem",
|
|
42
48
|
"bnlgit"
|
|
43
49
|
],
|
|
44
50
|
"license": "Apache-2.0",
|