@scopebond/agent 0.5.6 → 0.6.1
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/dist/agent.d.ts +6 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +10 -3
- package/dist/agent.js.map +1 -1
- package/dist/allowance-sender.js +10 -4
- package/dist/allowance-sender.js.map +1 -1
- package/dist/apps-entry.d.ts +46 -0
- package/dist/apps-entry.d.ts.map +1 -0
- package/dist/apps-entry.js +118 -0
- package/dist/apps-entry.js.map +1 -0
- package/dist/autostart.d.ts +11 -5
- package/dist/autostart.d.ts.map +1 -1
- package/dist/autostart.js +60 -6
- package/dist/autostart.js.map +1 -1
- package/dist/awake.d.ts +31 -0
- package/dist/awake.d.ts.map +1 -0
- package/dist/awake.js +57 -0
- package/dist/awake.js.map +1 -0
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli-main.js +28 -1
- package/dist/cli-main.js.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/ipc.d.ts +9 -4
- package/dist/ipc.d.ts.map +1 -1
- package/dist/ipc.js +15 -9
- package/dist/ipc.js.map +1 -1
- package/dist/log-file.js.map +1 -1
- package/dist/native-update.d.ts +83 -7
- package/dist/native-update.d.ts.map +1 -1
- package/dist/native-update.js +230 -33
- package/dist/native-update.js.map +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +1 -0
- package/dist/prompt.js.map +1 -1
- package/dist/selfcheck.d.ts.map +1 -1
- package/dist/selfcheck.js +4 -1
- package/dist/selfcheck.js.map +1 -1
- package/dist/service.d.ts +20 -3
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +141 -44
- package/dist/service.js.map +1 -1
- package/dist/setup.d.ts +12 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +42 -13
- package/dist/setup.js.map +1 -1
- package/dist/tray-model.d.ts +2 -0
- package/dist/tray-model.d.ts.map +1 -1
- package/dist/tray-model.js +2 -0
- package/dist/tray-model.js.map +1 -1
- package/dist/update.d.ts +56 -12
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +209 -38
- package/dist/update.js.map +1 -1
- package/dist/upkeep.d.ts +16 -0
- package/dist/upkeep.d.ts.map +1 -0
- package/dist/upkeep.js +55 -0
- package/dist/upkeep.js.map +1 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-update.js","sourceRoot":"","sources":["../src/native-update.ts"],"names":[],"mappings":"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","sourcesContent":["// Updates for the signed Windows install (the single executable from the installer). npm installs keep updating with npm.\n//\n// A per-user install updates itself, but only with an installer it has checked three ways: the release manifest is signed\n// with the updater key (a separate Ed25519 key; its public half is built into this program), the installer's SHA-256 and\n// size are the manifest's, and the installer's Authenticode signature is valid and names Avouro LLC. Anything else and\n// nothing is installed: the agent says the update could not be verified. An install for every user (Program Files) never\n// updates itself; the organisation that deployed it updates it.\n\nimport { createHash, createPublicKey, verify } from \"node:crypto\";\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { isSingleExecutable } from \"@scopebond/hook\";\n\n/** Where the signed releases are published. */\nexport const RELEASE_BASE = \"https://github.com/avouro-com/scopebond/releases/download\";\n/** The domain the updater key signs in: a manifest, never anything else. */\nexport const MANIFEST_DOMAIN = \"scopebond:agent-release/v1\\n\";\n/** The publisher an installer must be signed by. */\nexport const PUBLISHER = /(^|,\\s*)O=Avouro LLC(,|$)/;\n\n/** Set by the single executable's build from the updater's public key (base64 SPKI); absent from npm builds. */\ndeclare const __SCOPEBOND_UPDATER_KEY__: string | undefined;\n\nexport function updaterPublicKey(): string | null {\n return typeof __SCOPEBOND_UPDATER_KEY__ === \"string\" && __SCOPEBOND_UPDATER_KEY__ ? __SCOPEBOND_UPDATER_KEY__ : null;\n}\n\nexport type InstallKind = \"npm\" | \"per-user\" | \"per-machine\";\n\n/** How this agent was installed: from npm, by the installer for this user, or for every user (Program Files). */\nexport function installKind(execPath = process.execPath, single = isSingleExecutable(), programFiles = process.env.ProgramFiles ?? \"C:\\\\Program Files\"): InstallKind {\n if (!single) return \"npm\";\n // The folder without trailing separators (a loop, not a regular expression, on a value from the environment).\n let folder = programFiles.toLowerCase();\n while (folder.endsWith(\"\\\\\") || folder.endsWith(\"/\")) folder = folder.slice(0, -1);\n return execPath.toLowerCase().startsWith(`${folder}\\\\`) ? \"per-machine\" : \"per-user\";\n}\n\nexport interface ReleaseManifest { type: \"scopebond:agent-release\"; version: string; files: Array<{ name: string; sha256: string; size: number }> }\n\n/** The manifest when its signature is the updater key's over exactly these bytes, else null. */\nexport function verifyManifest(text: string, signatureB64: string, publicKeyB64: string): ReleaseManifest | null {\n try {\n const key = createPublicKey({ key: Buffer.from(publicKeyB64, \"base64\"), format: \"der\", type: \"spki\" });\n if (!verify(null, Buffer.from(MANIFEST_DOMAIN + text, \"utf8\"), key, Buffer.from(signatureB64.trim(), \"base64\"))) return null;\n const manifest = JSON.parse(text) as ReleaseManifest;\n if (manifest.type !== \"scopebond:agent-release\" || typeof manifest.version !== \"string\" || !Array.isArray(manifest.files)) return null;\n return manifest;\n } catch { return null; }\n}\n\nexport const installerName = (version: string) => `scopebond-agent-${version}-x64.msi`;\n\n/** The Authenticode check: Windows' own verdict on the file, and the signer's subject. */\nexport function authenticode(file: string): { valid: boolean; subject: string } {\n const script = `$s = Get-AuthenticodeSignature -LiteralPath $env:SB_FILE; [Console]::Out.Write((@{ status = \"$($s.Status)\"; subject = \"$($s.SignerCertificate.Subject)\" } | ConvertTo-Json -Compress))`;\n const run = spawnSync(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script], { encoding: \"utf8\", env: { ...process.env, SB_FILE: file }, windowsHide: true, timeout: 60_000 });\n try { const r = JSON.parse(run.stdout) as { status: string; subject: string }; return { valid: r.status === \"Valid\", subject: r.subject }; }\n catch { return { valid: false, subject: \"\" }; }\n}\n\nexport interface VerifiedInstaller { ok: true; path: string; version: string }\nexport interface Refused { ok: false; reason: string }\n\n/** Download the installer for `version` and check it three ways. Nothing is kept unless every check passes. */\nexport async function fetchVerifiedInstaller(version: string, o: {\n dir: string; fetchImpl?: typeof fetch; publicKey?: string | null; check?: (file: string) => { valid: boolean; subject: string }; base?: string;\n}): Promise<VerifiedInstaller | Refused> {\n const publicKey = o.publicKey === undefined ? updaterPublicKey() : o.publicKey;\n if (!publicKey) return { ok: false, reason: \"this build has no updater key\" };\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(version)) return { ok: false, reason: \"not a version\" };\n const fetchImpl = o.fetchImpl ?? fetch;\n const base = `${o.base ?? RELEASE_BASE}/agent-native-v${version}`;\n const get = async (name: string): Promise<Buffer | null> => {\n try {\n const res = await fetchImpl(`${base}/${name}`, { redirect: \"follow\", signal: AbortSignal.timeout(5 * 60_000) });\n return res.ok ? Buffer.from(await res.arrayBuffer()) : null;\n } catch { return null; }\n };\n const [text, signature] = await Promise.all([get(`scopebond-agent-${version}.manifest.json`), get(`scopebond-agent-${version}.manifest.json.sig`)]);\n if (!text || !signature) return { ok: false, reason: \"the release has no signed manifest\" };\n const manifest = verifyManifest(text.toString(\"utf8\"), signature.toString(\"utf8\"), publicKey);\n if (!manifest) return { ok: false, reason: \"the release manifest is not signed by the updater key\" };\n if (manifest.version !== version) return { ok: false, reason: `the manifest is for ${manifest.version}, not ${version}` };\n const entry = manifest.files.find((f) => f.name === installerName(version));\n if (!entry) return { ok: false, reason: \"the manifest names no installer\" };\n const bytes = await get(entry.name);\n if (!bytes) return { ok: false, reason: \"the installer could not be downloaded\" };\n if (bytes.length !== entry.size || createHash(\"sha256\").update(bytes).digest(\"hex\") !== entry.sha256) return { ok: false, reason: \"the installer is not the one the manifest names\" };\n const folder = join(o.dir, \"updates\");\n mkdirSync(folder, { recursive: true });\n const path = join(folder, entry.name);\n writeFileSync(path, bytes);\n const signed = (o.check ?? authenticode)(path);\n if (!signed.valid) return { ok: false, reason: \"the installer's signature is not valid\" };\n if (!PUBLISHER.test(signed.subject)) return { ok: false, reason: `the installer is signed by ${signed.subject || \"someone else\"}, not Avouro LLC` };\n return { ok: true, path, version };\n}\n\n/** Install it once this agent has exited, then start the agent again through autostart's launcher. A detached helper does it,\n * because the installer replaces this very file. */\nexport function installAfterExit(installer: string, pid: number, launcher: string | null): void {\n const script = [\n \"$ErrorActionPreference = 'SilentlyContinue'\",\n \"Wait-Process -Id ([int]$env:SB_PID) -Timeout 60\",\n \"Start-Process -FilePath msiexec.exe -ArgumentList @('/i', ('\\\"' + $env:SB_MSI + '\\\"'), '/qn', '/norestart') -Wait\",\n \"if ($env:SB_LAUNCHER) { Start-Process -FilePath cmd.exe -ArgumentList @('/d', '/s', '/c', ('\\\"\\\"' + $env:SB_LAUNCHER + '\\\"\\\"')) -WindowStyle Hidden }\",\n ].join(\"; \");\n const child = spawn(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-WindowStyle\", \"Hidden\", \"-Command\", script], {\n detached: true, stdio: \"ignore\", windowsHide: true, env: { ...process.env, SB_PID: String(pid), SB_MSI: installer, SB_LAUNCHER: launcher ?? \"\" },\n });\n child.on(\"error\", () => { /* the next sign-in starts the agent */ });\n child.unref();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"native-update.js","sourceRoot":"","sources":["../src/native-update.ts"],"names":[],"mappings":"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","sourcesContent":["// Updates for the signed Windows install (the single executable from the installer). npm installs keep updating with npm.\n//\n// A per-user install updates itself, but only with an installer it has checked three ways: the release manifest is signed\n// with an updater key (a separate Ed25519 key; the public halves it trusts are built into this program, each with a key id\n// and an optional last day of use, so the key can be rotated), the installer's SHA-256 and size are the manifest's, and\n// the installer's Authenticode signature is valid and names Avouro LLC. The helper that runs msiexec after this agent has\n// exited checks the digest, size and signature again from a handle that keeps the file from being changed, and only then\n// starts msiexec. Anything else and nothing is installed: the agent says the update could not be verified. An install for\n// every user (Program Files) never updates itself; the organisation that deployed it updates it.\n\nimport { createHash, createPublicKey, verify } from \"node:crypto\";\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, win32 } from \"node:path\";\nimport { isSingleExecutable } from \"@scopebond/hook\";\n\n/** Where the signed releases are published. */\nexport const RELEASE_BASE = \"https://github.com/avouro-com/scopebond/releases/download\";\n/** The domain the updater key signs in: a manifest, never anything else. */\nexport const MANIFEST_DOMAIN = \"scopebond:agent-release/v1\\n\";\n/** The publisher an installer must be signed by. */\nexport const PUBLISHER = /(^|,\\s*)O=Avouro LLC(,|$)/;\n\n/** One trusted updater key: its id (the first 16 hex digits of the SHA-256 of its SPKI bytes), its public half (base64\n * SPKI), and the last day it may sign (an ISO date, inclusive), or null for no end. */\nexport interface UpdaterKey { kid: string; key: string; not_after: string | null }\n\n/** Set by the single executable's build from updater-keys.json (or updater-public-key.txt): a JSON list of UpdaterKey.\n * Absent from npm builds. */\ndeclare const __SCOPEBOND_UPDATER_KEYS__: string | undefined;\n\n/** A public key's id: the first 16 hex digits of the SHA-256 of its SPKI bytes. */\nexport function keyId(publicKeyB64: string): string {\n return createHash(\"sha256\").update(Buffer.from(publicKeyB64, \"base64\")).digest(\"hex\").slice(0, 16);\n}\n\n/** The updater keys this build trusts (empty when it has none). */\nexport function updaterKeys(): UpdaterKey[] {\n if (typeof __SCOPEBOND_UPDATER_KEYS__ !== \"string\" || !__SCOPEBOND_UPDATER_KEYS__) return [];\n try { return normalizeKeys(JSON.parse(__SCOPEBOND_UPDATER_KEYS__) as unknown); } catch { return []; }\n}\n\nfunction normalizeKeys(value: unknown): UpdaterKey[] {\n if (typeof value === \"string\") return value ? [{ kid: keyId(value), key: value, not_after: null }] : [];\n if (!Array.isArray(value)) return [];\n return value.flatMap((k): UpdaterKey[] => {\n const e = k as Partial<UpdaterKey>;\n if (!e || typeof e.key !== \"string\" || !e.key) return [];\n return [{ kid: typeof e.kid === \"string\" && e.kid ? e.kid : keyId(e.key), key: e.key, not_after: typeof e.not_after === \"string\" ? e.not_after : null }];\n });\n}\n\n/** Whether a key may still sign at `now`: no end, or `now` is on or before its last day. An unreadable date counts as past. */\nfunction inDate(key: UpdaterKey, now: number): boolean {\n if (key.not_after === null) return true;\n const end = /^\\d{4}-\\d{2}-\\d{2}$/.test(key.not_after) ? Date.parse(`${key.not_after}T23:59:59.999Z`) : Date.parse(key.not_after);\n return Number.isFinite(end) && now <= end;\n}\n\nexport type InstallKind = \"npm\" | \"per-user\" | \"per-machine\";\n\n/** How this agent was installed: from npm, by the installer for this user, or for every user (Program Files). */\nexport function installKind(execPath = process.execPath, single = isSingleExecutable(), programFiles = process.env.ProgramFiles ?? \"C:\\\\Program Files\"): InstallKind {\n if (!single) return \"npm\";\n // The folder without trailing separators (a loop, not a regular expression, on a value from the environment).\n let folder = programFiles.toLowerCase();\n while (folder.endsWith(\"\\\\\") || folder.endsWith(\"/\")) folder = folder.slice(0, -1);\n return execPath.toLowerCase().startsWith(`${folder}\\\\`) ? \"per-machine\" : \"per-user\";\n}\n\nexport interface ReleaseManifest { type: \"scopebond:agent-release\"; version: string; kid?: string; files: Array<{ name: string; sha256: string; size: number }> }\n\n/** The manifest when its signature is one trusted, in-date updater key's over exactly these bytes, else null. A manifest\n * that names its key id (`kid`) is checked with that key only. */\nexport function verifyManifest(text: string, signatureB64: string, keys: string | UpdaterKey[], now = Date.now()): ReleaseManifest | null {\n try {\n const ring = normalizeKeys(keys).filter((k) => inDate(k, now));\n if (!ring.length) return null;\n const parsed = JSON.parse(text) as ReleaseManifest;\n const named = typeof parsed?.kid === \"string\" ? parsed.kid : null;\n const candidates = named === null ? ring : ring.filter((k) => k.kid === named);\n const message = Buffer.from(MANIFEST_DOMAIN + text, \"utf8\");\n const signature = Buffer.from(signatureB64.trim(), \"base64\");\n const signed = candidates.some((k) => {\n try { return verify(null, message, createPublicKey({ key: Buffer.from(k.key, \"base64\"), format: \"der\", type: \"spki\" }), signature); }\n catch { return false; }\n });\n if (!signed) return null;\n if (parsed.type !== \"scopebond:agent-release\" || typeof parsed.version !== \"string\" || !Array.isArray(parsed.files)) return null;\n return parsed;\n } catch { return null; }\n}\n\nexport const installerName = (version: string) => `scopebond-agent-${version}-x64.msi`;\n\n/** The environment for Windows PowerShell (powershell.exe, 5.1): this one's, without `PSModulePath`, plus `extra`. An\n * agent started from PowerShell 7 inherits its module path, and Windows PowerShell then cannot load its own security\n * module (Get-AuthenticodeSignature), so every check would fail; without the variable it uses its own default. */\nexport function powershellEnv(extra: Record<string, string>, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {};\n for (const [key, value] of Object.entries(base)) if (key.toLowerCase() !== \"psmodulepath\") env[key] = value;\n return { ...env, ...extra };\n}\n\n/** A Windows tool by its full path under the system folder, never by a name looked up on PATH. */\nexport function windowsTool(name: \"powershell\" | \"msiexec\" | \"cmd\"): string {\n const root = process.env.SystemRoot || process.env.windir || \"C:\\\\Windows\";\n if (name === \"powershell\") return win32.join(root, \"System32\", \"WindowsPowerShell\", \"v1.0\", \"powershell.exe\");\n return win32.join(root, \"System32\", `${name}.exe`);\n}\n\n/** The Authenticode check: Windows' own verdict on the file, and the signer's subject. */\nexport function authenticode(file: string): { valid: boolean; subject: string } {\n const script = `$s = Get-AuthenticodeSignature -LiteralPath $env:SB_FILE; [Console]::Out.Write((@{ status = \"$($s.Status)\"; subject = \"$($s.SignerCertificate.Subject)\" } | ConvertTo-Json -Compress))`;\n const run = spawnSync(windowsTool(\"powershell\"), [\"-NoProfile\", \"-NonInteractive\", \"-Command\", script], { encoding: \"utf8\", env: powershellEnv({ SB_FILE: file }), windowsHide: true, timeout: 60_000 });\n try { const r = JSON.parse(run.stdout) as { status: string; subject: string }; return { valid: r.status === \"Valid\", subject: r.subject }; }\n catch { return { valid: false, subject: \"\" }; }\n}\n\nexport interface VerifiedInstaller { ok: true; path: string; version: string; sha256: string; size: number }\nexport interface Refused { ok: false; reason: string }\n\n/** Download the installer for `version` and check it three ways. Nothing is kept unless every check passes. */\nexport async function fetchVerifiedInstaller(version: string, o: {\n dir: string; fetchImpl?: typeof fetch; publicKey?: string | UpdaterKey[] | null; check?: (file: string) => { valid: boolean; subject: string }; base?: string; now?: number;\n}): Promise<VerifiedInstaller | Refused> {\n const keys = o.publicKey === undefined ? updaterKeys() : o.publicKey === null ? [] : normalizeKeys(o.publicKey);\n if (!keys.length) return { ok: false, reason: \"this build has no updater key\" };\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(version)) return { ok: false, reason: \"not a version\" };\n const fetchImpl = o.fetchImpl ?? fetch;\n const base = `${o.base ?? RELEASE_BASE}/agent-native-v${version}`;\n const get = async (name: string): Promise<Buffer | null> => {\n try {\n const res = await fetchImpl(`${base}/${name}`, { redirect: \"follow\", signal: AbortSignal.timeout(5 * 60_000) });\n return res.ok ? Buffer.from(await res.arrayBuffer()) : null;\n } catch { return null; }\n };\n const [text, signature] = await Promise.all([get(`scopebond-agent-${version}.manifest.json`), get(`scopebond-agent-${version}.manifest.json.sig`)]);\n if (!text || !signature) return { ok: false, reason: \"the release has no signed manifest\" };\n const manifest = verifyManifest(text.toString(\"utf8\"), signature.toString(\"utf8\"), keys, o.now);\n if (!manifest) return { ok: false, reason: \"the release manifest is not signed by the updater key\" };\n if (manifest.version !== version) return { ok: false, reason: `the manifest is for ${manifest.version}, not ${version}` };\n const entry = manifest.files.find((f) => f.name === installerName(version));\n if (!entry) return { ok: false, reason: \"the manifest names no installer\" };\n const bytes = await get(entry.name);\n if (!bytes) return { ok: false, reason: \"the installer could not be downloaded\" };\n if (bytes.length !== entry.size || createHash(\"sha256\").update(bytes).digest(\"hex\") !== entry.sha256) return { ok: false, reason: \"the installer is not the one the manifest names\" };\n const folder = join(o.dir, \"updates\");\n mkdirSync(folder, { recursive: true });\n const path = join(folder, entry.name);\n writeFileSync(path, bytes);\n const signed = (o.check ?? authenticode)(path);\n if (!signed.valid) return { ok: false, reason: \"the installer's signature is not valid\" };\n if (!PUBLISHER.test(signed.subject)) return { ok: false, reason: `the installer is signed by ${signed.subject || \"someone else\"}, not Avouro LLC` };\n return { ok: true, path, version, sha256: entry.sha256, size: entry.size };\n}\n\n/** What the helper that installs after this agent exits records, beside the installer. */\nexport const INSTALL_RESULT = \"install-result.json\";\n\nexport interface InstallResult { at: string; version: string; installed: boolean; reason: string | null; exit_code: number | null }\n\n/** The helper's script. It is constant text: every value (the installer, its digest and size, the publisher rule, where to\n * record the outcome) reaches it through environment variables, never through the script itself.\n *\n * Between the download and the install the agent exits and up to a minute passes, so the helper checks the installer again\n * right before it runs msiexec, the same way the agent did: its size and SHA-256 are the signed manifest's, its Authenticode\n * signature is valid and its signer matches the same anchored publisher rule (PUBLISHER). It holds the file open, denying\n * writes and deletes, from that check until msiexec has finished, so the file checked is the file installed. Any mismatch\n * installs nothing and records why in INSTALL_RESULT; the agent is started again either way. */\nexport const INSTALL_HELPER_SCRIPT = [\n \"$ErrorActionPreference = 'Stop'\",\n \"function Write-Result([bool] $installed, $reason, $code) {\",\n \" try {\",\n \" $json = [ordered]@{ at = [DateTime]::UtcNow.ToString('o'); version = $env:SB_VERSION; installed = $installed; reason = $reason; exit_code = $code } | ConvertTo-Json -Compress\",\n \" [IO.File]::WriteAllText($env:SB_RESULT, $json, (New-Object Text.UTF8Encoding $false))\",\n \" } catch { }\",\n \"}\",\n // The native tray first: it would start the old agent again, and the installer replaces its file. Only this install's.\n \"if ($env:SB_TRAY) { try { Get-Process -Name scopebond-tray -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $env:SB_TRAY } | Stop-Process -Force -ErrorAction SilentlyContinue } catch { } }\",\n \"try { Wait-Process -Id ([int]$env:SB_PID) -Timeout 60 -ErrorAction SilentlyContinue } catch { }\",\n \"$lock = $null\",\n \"$reason = $null\",\n \"try {\",\n \" $lock = New-Object IO.FileStream($env:SB_MSI, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)\",\n \" if ($lock.Length -ne [long]$env:SB_SIZE) { $reason = \\\"the installer is $($lock.Length) bytes, not the manifest's $($env:SB_SIZE)\\\" }\",\n \" else {\",\n \" $sha = [Security.Cryptography.SHA256]::Create()\",\n \" $digest = ([BitConverter]::ToString($sha.ComputeHash($lock)) -replace '-', '').ToLowerInvariant()\",\n \" if ($digest -cne $env:SB_SHA256.ToLowerInvariant()) { $reason = 'the installer changed after it was checked: its SHA-256 is not the manifest''s' }\",\n \" else {\",\n \" $sig = Get-AuthenticodeSignature -LiteralPath $env:SB_MSI\",\n \" $subject = \\\"$($sig.SignerCertificate.Subject)\\\"\",\n \" if (\\\"$($sig.Status)\\\" -ne 'Valid') { $reason = \\\"the installer's signature is not valid ($($sig.Status))\\\" }\",\n \" elseif (-not ($subject -cmatch $env:SB_PUBLISHER)) { $reason = \\\"the installer is signed by $subject, not the expected publisher\\\" }\",\n \" }\",\n \" }\",\n \"} catch { $reason = \\\"the installer could not be checked: $($_.Exception.Message)\\\" }\",\n \"try {\",\n \" if ($reason) { Write-Result $false $reason $null }\",\n \" else {\",\n \" try {\",\n // Windows' own msiexec by its full path (SB_MSIEXEC only replaces it in tests).\n \" $msiexec = if ($env:SB_MSIEXEC) { $env:SB_MSIEXEC } else { Join-Path $env:SystemRoot 'System32\\\\msiexec.exe' }\",\n \" $p = Start-Process -FilePath $msiexec -ArgumentList @('/i', ('\\\"' + $env:SB_MSI + '\\\"'), '/qn', '/norestart') -Wait -PassThru\",\n \" $code = [int]$p.ExitCode\",\n \" if ($code -eq 0 -or $code -eq 3010) { Write-Result $true $null $code } else { Write-Result $false \\\"msiexec ended with exit code $code\\\" $code }\",\n \" } catch { Write-Result $false \\\"msiexec could not start: $($_.Exception.Message)\\\" $null }\",\n \" }\",\n \"} finally { if ($lock) { $lock.Dispose() } }\",\n // Installed or not, the tray starts again (it starts the agent), or else the agent through autostart's launcher.\n \"if ($env:SB_TRAY) { Start-Process -FilePath $env:SB_TRAY } elseif ($env:SB_LAUNCHER) { Start-Process -FilePath (Join-Path $env:SystemRoot 'System32\\\\cmd.exe') -ArgumentList @('/d', '/s', '/c', ('\\\"\\\"' + $env:SB_LAUNCHER + '\\\"\\\"')) -WindowStyle Hidden }\",\n].join(\"\\n\");\n\n/** The helper's script (INSTALL_HELPER_SCRIPT): stop the native tray, wait for this agent to exit, check the installer\n * again, install, then start the tray again (or the agent through autostart's launcher). */\nexport function installAfterExitScript(): string {\n return INSTALL_HELPER_SCRIPT;\n}\n\n/** The native Scopebond tray the installer puts beside the single executable (`scopebond-tray.exe`), when it is there. It\n * starts the agent at sign-in and keeps it running, so the agent leaves the tray to it. */\nexport function nativeTrayPath(execPath = process.execPath, single = isSingleExecutable(), exists: (path: string) => boolean = existsSync): string | null {\n if (!single) return null;\n const tray = win32.join(win32.dirname(execPath), \"scopebond-tray.exe\");\n return exists(tray) ? tray : null;\n}\n\n/** The helper's program, arguments and environment values (pure, so it can be tested). */\nexport function installHelper(installer: { path: string; version: string; sha256: string; size: number }, pid: number, launcher: string | null, o: { msiexec?: string; publisher?: RegExp; tray?: string | null } = {}): { program: string; args: string[]; env: Record<string, string> } {\n return {\n program: windowsTool(\"powershell\"),\n args: [\"-NoProfile\", \"-NonInteractive\", \"-WindowStyle\", \"Hidden\", \"-Command\", INSTALL_HELPER_SCRIPT],\n env: {\n SB_PID: String(pid),\n SB_MSI: installer.path,\n SB_VERSION: installer.version,\n SB_SHA256: installer.sha256,\n SB_SIZE: String(installer.size),\n SB_PUBLISHER: (o.publisher ?? PUBLISHER).source,\n SB_RESULT: join(dirname(installer.path), INSTALL_RESULT),\n SB_MSIEXEC: o.msiexec ?? windowsTool(\"msiexec\"),\n SB_LAUNCHER: launcher ?? \"\",\n SB_TRAY: o.tray ?? \"\",\n },\n };\n}\n\n/** Install it once this agent has exited, then start the tray again (or the agent through autostart's launcher). A detached\n * helper does it, because the installer replaces this very file; it checks the installer again first (INSTALL_HELPER_SCRIPT). */\nexport function installAfterExit(installer: { path: string; version: string; sha256: string; size: number }, pid: number, launcher: string | null, tray: string | null = null): void {\n const helper = installHelper(installer, pid, launcher, { tray });\n const child = spawn(helper.program, helper.args, { detached: true, stdio: \"ignore\", windowsHide: true, env: powershellEnv(helper.env) });\n child.on(\"error\", () => { /* the next sign-in starts the agent */ });\n child.unref();\n}\n\n/** Whether the installer on disk is still the verified one: same size and SHA-256, and still validly signed by Avouro LLC. */\nexport function installerUnchanged(installer: Pick<VerifiedInstaller, \"path\" | \"sha256\" | \"size\">, check: (file: string) => { valid: boolean; subject: string } = authenticode): boolean {\n try {\n const bytes = readFileSync(installer.path);\n if (bytes.length !== installer.size || createHash(\"sha256\").update(bytes).digest(\"hex\") !== installer.sha256) return false;\n const signed = check(installer.path);\n return signed.valid && PUBLISHER.test(signed.subject);\n } catch { return false; }\n}\n\n/** PowerShell that opens $env:SB_MSI so nobody can change it while the handle is open, checks its size ($env:SB_SIZE),\n * SHA-256 ($env:SB_SHA256) and Authenticode signature (valid, Avouro LLC), and runs `whenGood` only if all hold. */\nfunction recheck(whenGood: string[]): string[] {\n return [\n \"$ok = $false\",\n \"$f = $null\",\n \"try {\",\n \" $f = [System.IO.File]::Open($env:SB_MSI, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read)\",\n \" if ($f.Length -eq [int64]$env:SB_SIZE) {\",\n \" $sha = [System.Security.Cryptography.SHA256]::Create()\",\n \" $h = -join ($sha.ComputeHash($f) | ForEach-Object { $_.ToString('x2') })\",\n \" if ($h -eq $env:SB_SHA256) {\",\n \" $s = Get-AuthenticodeSignature -LiteralPath $env:SB_MSI\",\n \" $ok = (\\\"$($s.Status)\\\" -eq 'Valid') -and (\\\"$($s.SignerCertificate.Subject)\\\" -match '(^|,\\\\s*)O=Avouro LLC(,|$)')\",\n \" }\",\n \" }\",\n ...whenGood.map((line) => ` if ($ok) { ${line} }`),\n \"} catch { $ok = $false } finally { if ($f) { $f.Dispose() } }\",\n ];\n}\n\n/** The helper's check alone: exit 0 when $env:SB_MSI is still the verified installer, 3 when it is not. */\nexport function installerRecheckScript(): string {\n return [...recheck([]), \"if ($ok) { exit 0 } else { exit 3 }\"].join(\"\\n\");\n}\n\n/** The helper script that installs after this agent exits (INSTALL_HELPER_SCRIPT). */\nexport function installHelperScript(): string {\n return INSTALL_HELPER_SCRIPT;\n}\n\n/** What the last install helper recorded, once: the file is removed when read. Null when there is nothing. */\nexport function takeInstallResult(dir: string): InstallResult | null {\n const file = join(dir, \"updates\", INSTALL_RESULT);\n try {\n const raw = readFileSync(file, \"utf8\").replace(/^\\uFEFF/, \"\");\n rmSync(file, { force: true });\n const r = JSON.parse(raw) as Partial<InstallResult>;\n return { at: String(r.at ?? \"\"), version: String(r.version ?? \"\"), installed: r.installed === true, reason: typeof r.reason === \"string\" ? r.reason : null, exit_code: typeof r.exit_code === \"number\" ? r.exit_code : null };\n } catch { return null; }\n}\n"]}
|
package/dist/prompt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,qGAAqG;IACrG,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;IACzB,6HAA6H;IAC7H,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9E;AACD,MAAM,WAAW,cAAc;IAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;CAAE;AAC5J,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,qGAAqG;IACrG,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;IACzB,6HAA6H;IAC7H,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9E;AACD,MAAM,WAAW,cAAc;IAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;CAAE;AAC5J,MAAM,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAM/E,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAmBnE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAIxD;AAiBD,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAmDzD;AAoDD,iHAAiH;AACjH,eAAO,MAAM,cAAc,EAAE,QAQ5B,CAAC;AAEF,uHAAuH;AACvH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAQvD"}
|
package/dist/prompt.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { userInfo } from "node:os";
|
|
7
7
|
const ID = /^[A-Za-z0-9._:-]{16,200}$/;
|
|
8
|
+
// eslint-disable-next-line no-control-regex -- deliberately replaces control characters in text shown in the window
|
|
8
9
|
const clip = (v, max) => (typeof v === "string" ? v.replace(/[\u0000-\u001f\u007f]/g, " ").slice(0, max) : "");
|
|
9
10
|
/** Check a request from the local channel. Anything malformed is refused before a window opens. */
|
|
10
11
|
export function parseQuestion(raw) {
|
package/dist/prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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","sourcesContent":["// The Scopebond window: asks the person at the computer whether to allow one action a workspace rule blocks, with a reason.\n// It is shown by this resident agent with the operating system's own tools (Windows PowerShell with Windows Forms, macOS\n// osascript, Linux zenity), never by the coding agent, and the answer comes only from the window. Text reaches each tool as\n// data (base64 for PowerShell, arguments for osascript and zenity), never spliced into code.\n\nimport { spawn } from \"node:child_process\";\nimport { userInfo } from \"node:os\";\n\nexport interface OverrideQuestion {\n action_id: string;\n rule: string;\n title: string;\n summary: string;\n reason_min: number;\n lasts: string;\n timeout_ms: number;\n /** D144: override = \"Block, person may allow\"; ask = \"Block, person may ask\" (only Ask an admin). */\n mode: \"override\" | \"ask\";\n /** Which choices the workspace allows: allow (once), fifteen (for 15 minutes), always (an allowance), ask (Ask an admin). */\n offers: { allow: boolean; always: boolean; ask: boolean; fifteen?: boolean };\n}\nexport interface OverrideAnswer { decision: \"allow\" | \"deny\" | \"unavailable\" | \"ask\"; reason?: string; os_user?: string; lasts?: \"once\" | \"15m\" | \"always\" }\nexport type Prompter = (question: OverrideQuestion) => Promise<OverrideAnswer>;\n\nconst ID = /^[A-Za-z0-9._:-]{16,200}$/;\nconst clip = (v: unknown, max: number) => (typeof v === \"string\" ? v.replace(/[\\u0000-\\u001f\\u007f]/g, \" \").slice(0, max) : \"\");\n\n/** Check a request from the local channel. Anything malformed is refused before a window opens. */\nexport function parseQuestion(raw: unknown): OverrideQuestion | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n if (typeof r.action_id !== \"string\" || !ID.test(r.action_id) || typeof r.rule !== \"string\" || !/^[a-z0-9-]{1,64}$/.test(r.rule)) return null;\n const reasonMin = Number(r.reason_min);\n const timeout = Number(r.timeout_ms);\n if (!Number.isInteger(reasonMin) || reasonMin < 10 || reasonMin > 200) return null;\n const mode = r.mode === \"ask\" ? \"ask\" : \"override\";\n const o = (r.offers && typeof r.offers === \"object\" ? r.offers : {}) as Record<string, unknown>;\n // A hook before D144 sends no offers: the window offers \"Allow once\", as it always did.\n const offers = r.offers === undefined ? { allow: true, always: false, ask: false }\n : { allow: mode === \"override\" && o.allow === true, always: mode === \"override\" && o.always === true, ask: o.ask === true,\n // A hook that does not say offers 15 minutes wherever it offers \"always\" (both came with allowances).\n fifteen: mode === \"override\" && (o.fifteen === true || (o.fifteen === undefined && o.always === true)) };\n return {\n action_id: r.action_id, rule: r.rule, title: clip(r.title, 120) || r.rule, summary: clip(r.summary, 200), reason_min: reasonMin,\n lasts: clip(r.lasts, 80) || \"this action only\", timeout_ms: Number.isFinite(timeout) ? Math.min(Math.max(timeout, 5_000), 55_000) : 45_000,\n mode, offers,\n };\n}\n\nexport function questionText(q: OverrideQuestion): string {\n const head = `Scopebond blocked this. Your workspace's rule \"${q.title}\" blocked this action:\\n\\n${q.summary}\\n\\n`;\n if (!q.offers.allow) return `${head}You may ask an admin to allow it. Say why, in at least ${q.reason_min} characters. The action stays blocked until an admin answers; your name, the reason and the action are recorded in your workspace.`;\n return `${head}You may allow it. Say why, in at least ${q.reason_min} characters. Your name, the reason and the action are recorded in your workspace.`;\n}\n\nfunction run(command: string, args: string[], timeoutMs: number): Promise<{ code: number | null; stdout: string }> {\n return new Promise((resolve) => {\n let stdout = \"\";\n let child;\n try { child = spawn(command, args, { windowsHide: false, stdio: [\"ignore\", \"pipe\", \"ignore\"] }); }\n catch { resolve({ code: null, stdout: \"\" }); return; }\n const timer = setTimeout(() => { child.kill(); resolve({ code: null, stdout }); }, timeoutMs + 3_000);\n child.stdout?.on(\"data\", (d) => { stdout += d; });\n child.on(\"error\", () => { clearTimeout(timer); resolve({ code: null, stdout: \"\" }); });\n child.on(\"close\", (code) => { clearTimeout(timer); resolve({ code, stdout }); });\n });\n}\n\nconst b64 = (s: string) => Buffer.from(s, \"utf8\").toString(\"base64\");\n\n/** Windows: a small topmost form from Windows' own signed PowerShell. Closes itself at the timeout. */\nexport function windowsScript(q: OverrideQuestion): string {\n return `\n$ErrorActionPreference = 'Stop'\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type -AssemblyName System.Drawing\nfunction T($s) { [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($s)) }\n$min = ${q.reason_min}\n$f = New-Object Windows.Forms.Form\n$f.Text = 'Scopebond'\n$f.TopMost = $true\n$f.StartPosition = 'CenterScreen'\n$f.FormBorderStyle = 'FixedDialog'\n$f.MaximizeBox = $false\n$f.MinimizeBox = $false\n$f.ClientSize = New-Object Drawing.Size(640, 250)\n$l = New-Object Windows.Forms.Label\n$l.Text = (T '${b64(questionText(q))}')\n$l.SetBounds(12, 10, 616, 130)\n$r = New-Object Windows.Forms.TextBox\n$r.SetBounds(12, 145, 616, 24)\n$script:answer = 'deny'\n$script:lasts = 'once'\n$needReason = @()\n$x = 628\nfunction Btn($label, $width, $decision, $lasts, $needs) {\n $b = New-Object Windows.Forms.Button\n $b.Text = (T $label)\n $script:x0 = $x - $width\n $b.SetBounds($x - $width, 200, $width, 30)\n $b.Add_Click({ $script:answer = $decision; $script:lasts = $lasts; $f.Close() }.GetNewClosure())\n if ($needs) { $b.Enabled = $false; $script:needReason += $b }\n $f.Controls.Add($b)\n $b\n}\n$d = Btn '${b64(\"Don't allow\")}' 100 'deny' 'once' $false; $x -= 108\n${q.offers.ask ? `[void](Btn '${b64(\"Ask an admin\")}' 110 'ask' 'once' $true); $x -= 118` : \"\"}\n${q.offers.always ? `[void](Btn '${b64(\"Always allow this here…\")}' 150 'allow' 'always' $true); $x -= 158` : \"\"}\n${q.offers.allow && q.offers.fifteen ? `[void](Btn '${b64(\"Allow for 15 min\")}' 120 'allow' '15m' $true); $x -= 128; ` : \"\"}${q.offers.allow ? `[void](Btn '${b64(\"Allow once\")}' 92 'allow' 'once' $true)` : \"\"}\n$r.Add_TextChanged({ foreach ($b in $script:needReason) { $b.Enabled = ($r.Text.Trim().Length -ge $min) } })\n$f.AcceptButton = $d\n$f.CancelButton = $d\n$f.Controls.AddRange(@($l, $r))\n$t = New-Object Windows.Forms.Timer\n$t.Interval = ${q.timeout_ms}\n$t.Add_Tick({ $t.Stop(); $f.Close() })\n$t.Start()\n$f.Add_Shown({ $f.Activate(); $r.Focus() })\n[void]$f.ShowDialog()\n$out = @{ decision = $script:answer; lasts = $script:lasts; reason = $(if ($script:answer -ne 'deny') { $r.Text.Trim() } else { '' }) }\n[Console]::Out.Write((ConvertTo-Json $out -Compress))\n`;\n}\n\nasync function promptWindows(q: OverrideQuestion): Promise<OverrideAnswer> {\n const encoded = Buffer.from(windowsScript(q), \"utf16le\").toString(\"base64\");\n const { code, stdout } = await run(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-STA\", \"-WindowStyle\", \"Hidden\", \"-EncodedCommand\", encoded], q.timeout_ms);\n if (code !== 0) return { decision: \"unavailable\" };\n try {\n const parsed = JSON.parse(stdout.trim()) as { decision?: string; reason?: string; lasts?: string };\n const lasts = parsed.lasts === \"15m\" || parsed.lasts === \"always\" ? parsed.lasts : \"once\";\n if (parsed.decision === \"allow\" && q.offers.allow && (lasts !== \"always\" || q.offers.always) && (lasts !== \"15m\" || q.offers.fifteen)) return { decision: \"allow\", reason: String(parsed.reason ?? \"\"), lasts };\n if (parsed.decision === \"ask\" && q.offers.ask) return { decision: \"ask\", reason: String(parsed.reason ?? \"\") };\n return { decision: \"deny\" };\n } catch { return { decision: \"unavailable\" }; }\n}\n\nconst MAC_SCRIPT = [\n \"on run argv\",\n \"set q to item 1 of argv\",\n \"set secs to (item 2 of argv) as integer\",\n \"set r to display dialog q default answer \\\"\\\" with title \\\"Scopebond\\\" buttons {\\\"Don't allow\\\", \\\"Allow once\\\"} default button \\\"Don't allow\\\" cancel button \\\"Don't allow\\\" giving up after secs\",\n \"if gave up of r then return \\\"timeout\\\"\",\n \"return \\\"allow\\\" & linefeed & (text returned of r)\",\n \"end run\",\n];\n\nasync function promptMac(q: OverrideQuestion): Promise<OverrideAnswer> {\n // macOS dialogs take three buttons: \"Allow once\" where allowing is offered, otherwise \"Ask an admin\".\n const asking = !q.offers.allow && q.offers.ask;\n if (!q.offers.allow && !asking) return { decision: \"unavailable\" };\n const script = asking ? MAC_SCRIPT.map((line) => line.replace(/Allow once/g, \"Ask an admin\").replace('return \"allow\"', 'return \"ask\"')) : MAC_SCRIPT;\n const args = script.flatMap((line) => [\"-e\", line]);\n const { code, stdout } = await run(\"osascript\", [...args, questionText(q), String(Math.round(q.timeout_ms / 1000))], q.timeout_ms);\n if (code === null) return { decision: \"unavailable\" };\n if (code !== 0) return { decision: \"deny\" }; // \"Don't allow\" is the cancel button\n const [first, ...rest] = stdout.replace(/\\r?\\n$/, \"\").split(\"\\n\");\n if (first === \"ask\") return { decision: \"ask\", reason: rest.join(\"\\n\") };\n return first === \"allow\" ? { decision: \"allow\", reason: rest.join(\"\\n\"), lasts: \"once\" } : { decision: \"deny\" };\n}\n\nasync function promptLinux(q: OverrideQuestion): Promise<OverrideAnswer> {\n const asking = !q.offers.allow && q.offers.ask;\n if (!q.offers.allow && !asking) return { decision: \"unavailable\" };\n const { code, stdout } = await run(\"zenity\", [\n \"--entry\", \"--title=Scopebond\", `--text=${questionText(q)}`, `--ok-label=${asking ? \"Ask an admin\" : \"Allow once\"}`, \"--cancel-label=Don't allow\",\n `--timeout=${Math.round(q.timeout_ms / 1000)}`,\n ], q.timeout_ms);\n if (code === null) return { decision: \"unavailable\" };\n if (code === 0) return asking ? { decision: \"ask\", reason: stdout.replace(/\\r?\\n$/, \"\") } : { decision: \"allow\", reason: stdout.replace(/\\r?\\n$/, \"\"), lasts: \"once\" };\n // 1: Don't allow; 5: timed out; anything else (no display, not installed): no window.\n return code === 1 || code === 5 ? { decision: \"deny\" } : { decision: \"unavailable\" };\n}\n\n/** The window for this operating system. A reason shorter than the workspace accepts is refused here as well. */\nexport const systemPrompter: Prompter = async (q) => {\n const answer = process.platform === \"win32\" ? await promptWindows(q) : process.platform === \"darwin\" ? await promptMac(q) : await promptLinux(q);\n if (answer.decision !== \"allow\" && answer.decision !== \"ask\") return answer;\n const reason = (answer.reason ?? \"\").trim();\n if (reason.length < q.reason_min) return { decision: \"deny\" };\n let os_user: string | undefined;\n try { os_user = userInfo().username; } catch { /* not known */ }\n return { ...answer, reason: reason.slice(0, 500), ...(os_user ? { os_user } : {}) };\n};\n\n/** One window at a time: a second request waits for the first, and gives up as no answer if it would wait too long. */\nexport function serialized(prompter: Prompter): Prompter {\n let chain: Promise<unknown> = Promise.resolve();\n return (q) => {\n const queuedAt = Date.now();\n const next = chain.then(() => (Date.now() - queuedAt > q.timeout_ms ? { decision: \"unavailable\" as const } : prompter(q)));\n chain = next.catch(() => undefined);\n return next;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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","sourcesContent":["// The Scopebond window: asks the person at the computer whether to allow one action a workspace rule blocks, with a reason.\n// It is shown by this resident agent with the operating system's own tools (Windows PowerShell with Windows Forms, macOS\n// osascript, Linux zenity), never by the coding agent, and the answer comes only from the window. Text reaches each tool as\n// data (base64 for PowerShell, arguments for osascript and zenity), never spliced into code.\n\nimport { spawn } from \"node:child_process\";\nimport { userInfo } from \"node:os\";\n\nexport interface OverrideQuestion {\n action_id: string;\n rule: string;\n title: string;\n summary: string;\n reason_min: number;\n lasts: string;\n timeout_ms: number;\n /** D144: override = \"Block, person may allow\"; ask = \"Block, person may ask\" (only Ask an admin). */\n mode: \"override\" | \"ask\";\n /** Which choices the workspace allows: allow (once), fifteen (for 15 minutes), always (an allowance), ask (Ask an admin). */\n offers: { allow: boolean; always: boolean; ask: boolean; fifteen?: boolean };\n}\nexport interface OverrideAnswer { decision: \"allow\" | \"deny\" | \"unavailable\" | \"ask\"; reason?: string; os_user?: string; lasts?: \"once\" | \"15m\" | \"always\" }\nexport type Prompter = (question: OverrideQuestion) => Promise<OverrideAnswer>;\n\nconst ID = /^[A-Za-z0-9._:-]{16,200}$/;\n// eslint-disable-next-line no-control-regex -- deliberately replaces control characters in text shown in the window\nconst clip = (v: unknown, max: number) => (typeof v === \"string\" ? v.replace(/[\\u0000-\\u001f\\u007f]/g, \" \").slice(0, max) : \"\");\n\n/** Check a request from the local channel. Anything malformed is refused before a window opens. */\nexport function parseQuestion(raw: unknown): OverrideQuestion | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n if (typeof r.action_id !== \"string\" || !ID.test(r.action_id) || typeof r.rule !== \"string\" || !/^[a-z0-9-]{1,64}$/.test(r.rule)) return null;\n const reasonMin = Number(r.reason_min);\n const timeout = Number(r.timeout_ms);\n if (!Number.isInteger(reasonMin) || reasonMin < 10 || reasonMin > 200) return null;\n const mode = r.mode === \"ask\" ? \"ask\" : \"override\";\n const o = (r.offers && typeof r.offers === \"object\" ? r.offers : {}) as Record<string, unknown>;\n // A hook before D144 sends no offers: the window offers \"Allow once\", as it always did.\n const offers = r.offers === undefined ? { allow: true, always: false, ask: false }\n : { allow: mode === \"override\" && o.allow === true, always: mode === \"override\" && o.always === true, ask: o.ask === true,\n // A hook that does not say offers 15 minutes wherever it offers \"always\" (both came with allowances).\n fifteen: mode === \"override\" && (o.fifteen === true || (o.fifteen === undefined && o.always === true)) };\n return {\n action_id: r.action_id, rule: r.rule, title: clip(r.title, 120) || r.rule, summary: clip(r.summary, 200), reason_min: reasonMin,\n lasts: clip(r.lasts, 80) || \"this action only\", timeout_ms: Number.isFinite(timeout) ? Math.min(Math.max(timeout, 5_000), 55_000) : 45_000,\n mode, offers,\n };\n}\n\nexport function questionText(q: OverrideQuestion): string {\n const head = `Scopebond blocked this. Your workspace's rule \"${q.title}\" blocked this action:\\n\\n${q.summary}\\n\\n`;\n if (!q.offers.allow) return `${head}You may ask an admin to allow it. Say why, in at least ${q.reason_min} characters. The action stays blocked until an admin answers; your name, the reason and the action are recorded in your workspace.`;\n return `${head}You may allow it. Say why, in at least ${q.reason_min} characters. Your name, the reason and the action are recorded in your workspace.`;\n}\n\nfunction run(command: string, args: string[], timeoutMs: number): Promise<{ code: number | null; stdout: string }> {\n return new Promise((resolve) => {\n let stdout = \"\";\n let child;\n try { child = spawn(command, args, { windowsHide: false, stdio: [\"ignore\", \"pipe\", \"ignore\"] }); }\n catch { resolve({ code: null, stdout: \"\" }); return; }\n const timer = setTimeout(() => { child.kill(); resolve({ code: null, stdout }); }, timeoutMs + 3_000);\n child.stdout?.on(\"data\", (d) => { stdout += d; });\n child.on(\"error\", () => { clearTimeout(timer); resolve({ code: null, stdout: \"\" }); });\n child.on(\"close\", (code) => { clearTimeout(timer); resolve({ code, stdout }); });\n });\n}\n\nconst b64 = (s: string) => Buffer.from(s, \"utf8\").toString(\"base64\");\n\n/** Windows: a small topmost form from Windows' own signed PowerShell. Closes itself at the timeout. */\nexport function windowsScript(q: OverrideQuestion): string {\n return `\n$ErrorActionPreference = 'Stop'\nAdd-Type -AssemblyName System.Windows.Forms\nAdd-Type -AssemblyName System.Drawing\nfunction T($s) { [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($s)) }\n$min = ${q.reason_min}\n$f = New-Object Windows.Forms.Form\n$f.Text = 'Scopebond'\n$f.TopMost = $true\n$f.StartPosition = 'CenterScreen'\n$f.FormBorderStyle = 'FixedDialog'\n$f.MaximizeBox = $false\n$f.MinimizeBox = $false\n$f.ClientSize = New-Object Drawing.Size(640, 250)\n$l = New-Object Windows.Forms.Label\n$l.Text = (T '${b64(questionText(q))}')\n$l.SetBounds(12, 10, 616, 130)\n$r = New-Object Windows.Forms.TextBox\n$r.SetBounds(12, 145, 616, 24)\n$script:answer = 'deny'\n$script:lasts = 'once'\n$needReason = @()\n$x = 628\nfunction Btn($label, $width, $decision, $lasts, $needs) {\n $b = New-Object Windows.Forms.Button\n $b.Text = (T $label)\n $script:x0 = $x - $width\n $b.SetBounds($x - $width, 200, $width, 30)\n $b.Add_Click({ $script:answer = $decision; $script:lasts = $lasts; $f.Close() }.GetNewClosure())\n if ($needs) { $b.Enabled = $false; $script:needReason += $b }\n $f.Controls.Add($b)\n $b\n}\n$d = Btn '${b64(\"Don't allow\")}' 100 'deny' 'once' $false; $x -= 108\n${q.offers.ask ? `[void](Btn '${b64(\"Ask an admin\")}' 110 'ask' 'once' $true); $x -= 118` : \"\"}\n${q.offers.always ? `[void](Btn '${b64(\"Always allow this here…\")}' 150 'allow' 'always' $true); $x -= 158` : \"\"}\n${q.offers.allow && q.offers.fifteen ? `[void](Btn '${b64(\"Allow for 15 min\")}' 120 'allow' '15m' $true); $x -= 128; ` : \"\"}${q.offers.allow ? `[void](Btn '${b64(\"Allow once\")}' 92 'allow' 'once' $true)` : \"\"}\n$r.Add_TextChanged({ foreach ($b in $script:needReason) { $b.Enabled = ($r.Text.Trim().Length -ge $min) } })\n$f.AcceptButton = $d\n$f.CancelButton = $d\n$f.Controls.AddRange(@($l, $r))\n$t = New-Object Windows.Forms.Timer\n$t.Interval = ${q.timeout_ms}\n$t.Add_Tick({ $t.Stop(); $f.Close() })\n$t.Start()\n$f.Add_Shown({ $f.Activate(); $r.Focus() })\n[void]$f.ShowDialog()\n$out = @{ decision = $script:answer; lasts = $script:lasts; reason = $(if ($script:answer -ne 'deny') { $r.Text.Trim() } else { '' }) }\n[Console]::Out.Write((ConvertTo-Json $out -Compress))\n`;\n}\n\nasync function promptWindows(q: OverrideQuestion): Promise<OverrideAnswer> {\n const encoded = Buffer.from(windowsScript(q), \"utf16le\").toString(\"base64\");\n const { code, stdout } = await run(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-STA\", \"-WindowStyle\", \"Hidden\", \"-EncodedCommand\", encoded], q.timeout_ms);\n if (code !== 0) return { decision: \"unavailable\" };\n try {\n const parsed = JSON.parse(stdout.trim()) as { decision?: string; reason?: string; lasts?: string };\n const lasts = parsed.lasts === \"15m\" || parsed.lasts === \"always\" ? parsed.lasts : \"once\";\n if (parsed.decision === \"allow\" && q.offers.allow && (lasts !== \"always\" || q.offers.always) && (lasts !== \"15m\" || q.offers.fifteen)) return { decision: \"allow\", reason: String(parsed.reason ?? \"\"), lasts };\n if (parsed.decision === \"ask\" && q.offers.ask) return { decision: \"ask\", reason: String(parsed.reason ?? \"\") };\n return { decision: \"deny\" };\n } catch { return { decision: \"unavailable\" }; }\n}\n\nconst MAC_SCRIPT = [\n \"on run argv\",\n \"set q to item 1 of argv\",\n \"set secs to (item 2 of argv) as integer\",\n \"set r to display dialog q default answer \\\"\\\" with title \\\"Scopebond\\\" buttons {\\\"Don't allow\\\", \\\"Allow once\\\"} default button \\\"Don't allow\\\" cancel button \\\"Don't allow\\\" giving up after secs\",\n \"if gave up of r then return \\\"timeout\\\"\",\n \"return \\\"allow\\\" & linefeed & (text returned of r)\",\n \"end run\",\n];\n\nasync function promptMac(q: OverrideQuestion): Promise<OverrideAnswer> {\n // macOS dialogs take three buttons: \"Allow once\" where allowing is offered, otherwise \"Ask an admin\".\n const asking = !q.offers.allow && q.offers.ask;\n if (!q.offers.allow && !asking) return { decision: \"unavailable\" };\n const script = asking ? MAC_SCRIPT.map((line) => line.replace(/Allow once/g, \"Ask an admin\").replace('return \"allow\"', 'return \"ask\"')) : MAC_SCRIPT;\n const args = script.flatMap((line) => [\"-e\", line]);\n const { code, stdout } = await run(\"osascript\", [...args, questionText(q), String(Math.round(q.timeout_ms / 1000))], q.timeout_ms);\n if (code === null) return { decision: \"unavailable\" };\n if (code !== 0) return { decision: \"deny\" }; // \"Don't allow\" is the cancel button\n const [first, ...rest] = stdout.replace(/\\r?\\n$/, \"\").split(\"\\n\");\n if (first === \"ask\") return { decision: \"ask\", reason: rest.join(\"\\n\") };\n return first === \"allow\" ? { decision: \"allow\", reason: rest.join(\"\\n\"), lasts: \"once\" } : { decision: \"deny\" };\n}\n\nasync function promptLinux(q: OverrideQuestion): Promise<OverrideAnswer> {\n const asking = !q.offers.allow && q.offers.ask;\n if (!q.offers.allow && !asking) return { decision: \"unavailable\" };\n const { code, stdout } = await run(\"zenity\", [\n \"--entry\", \"--title=Scopebond\", `--text=${questionText(q)}`, `--ok-label=${asking ? \"Ask an admin\" : \"Allow once\"}`, \"--cancel-label=Don't allow\",\n `--timeout=${Math.round(q.timeout_ms / 1000)}`,\n ], q.timeout_ms);\n if (code === null) return { decision: \"unavailable\" };\n if (code === 0) return asking ? { decision: \"ask\", reason: stdout.replace(/\\r?\\n$/, \"\") } : { decision: \"allow\", reason: stdout.replace(/\\r?\\n$/, \"\"), lasts: \"once\" };\n // 1: Don't allow; 5: timed out; anything else (no display, not installed): no window.\n return code === 1 || code === 5 ? { decision: \"deny\" } : { decision: \"unavailable\" };\n}\n\n/** The window for this operating system. A reason shorter than the workspace accepts is refused here as well. */\nexport const systemPrompter: Prompter = async (q) => {\n const answer = process.platform === \"win32\" ? await promptWindows(q) : process.platform === \"darwin\" ? await promptMac(q) : await promptLinux(q);\n if (answer.decision !== \"allow\" && answer.decision !== \"ask\") return answer;\n const reason = (answer.reason ?? \"\").trim();\n if (reason.length < q.reason_min) return { decision: \"deny\" };\n let os_user: string | undefined;\n try { os_user = userInfo().username; } catch { /* not known */ }\n return { ...answer, reason: reason.slice(0, 500), ...(os_user ? { os_user } : {}) };\n};\n\n/** One window at a time: a second request waits for the first, and gives up as no answer if it would wait too long. */\nexport function serialized(prompter: Prompter): Prompter {\n let chain: Promise<unknown> = Promise.resolve();\n return (q) => {\n const queuedAt = Date.now();\n const next = chain.then(() => (Date.now() - queuedAt > q.timeout_ms ? { decision: \"unavailable\" as const } : prompter(q)));\n chain = next.catch(() => undefined);\n return next;\n };\n}\n"]}
|
package/dist/selfcheck.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selfcheck.d.ts","sourceRoot":"","sources":["../src/selfcheck.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,OAAO,EAAE,KAAK,cAAc,EAClC,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"selfcheck.d.ts","sourceRoot":"","sources":["../src/selfcheck.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,OAAO,EAAE,KAAK,cAAc,EAClC,MAAM,iBAAiB,CAAC;AAIzB,MAAM,WAAW,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AAE3E,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,GAAG,SAAa,GAAG,aAAa,EAAE,CAmB5H;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,MAAM,EACnF,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3E,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,kBAAkB,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAyBzG"}
|
package/dist/selfcheck.js
CHANGED
|
@@ -9,6 +9,7 @@ import { canonical } from "@scopebond/gateway";
|
|
|
9
9
|
import { loadOrCreateAttester } from "@scopebond/gateway/node";
|
|
10
10
|
import { configuredHookCommands, duplicateHooks, hookCommandResolves, hookVersion, isScopebondHookCommand, queueStatus, readDeliveryState, userHarnessFile, } from "@scopebond/hook";
|
|
11
11
|
import { autostartHealth } from "./autostart.js";
|
|
12
|
+
import { installKind } from "./native-update.js";
|
|
12
13
|
export function selfCheckProof(credentialId, gatewayId, day) {
|
|
13
14
|
return canonical({ type: "scopebond:self-check", version: 1, credential_id: credentialId, gateway_id: gatewayId, day });
|
|
14
15
|
}
|
|
@@ -45,7 +46,9 @@ export async function runSelfCheck(dir, connection, harnesses, agentVersion, opt
|
|
|
45
46
|
const res = await (options.fetchImpl ?? fetch)(new URL("/v1/self-check", connection.url).toString(), {
|
|
46
47
|
method: "POST", redirect: "error", signal: AbortSignal.timeout(options.timeoutMs ?? 10_000),
|
|
47
48
|
headers: { authorization: `Bearer ${connection.credential}`, "content-type": "application/json" },
|
|
48
|
-
|
|
49
|
+
// install_kind: how this agent was installed (npm, per-user or per-machine signed installer), so the workspace can say
|
|
50
|
+
// how the computer updates and is removed. A workspace that does not read it ignores it.
|
|
51
|
+
body: JSON.stringify({ signature, day, checks, hook_version: hookVersion(), agent_version: agentVersion, install_kind: installKind() }),
|
|
49
52
|
});
|
|
50
53
|
// A workspace that does not offer the self-check yet answers 404: the computer's own checks still count; the signed
|
|
51
54
|
// workspace part is simply not available there.
|
package/dist/selfcheck.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selfcheck.js","sourceRoot":"","sources":["../src/selfcheck.ts"],"names":[],"mappings":"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","sourcesContent":["// The daily end-to-end self-check (SB347). The agent checks this computer's side (the hook entry\n// is present and starts, autostart works, nothing is stuck, the connection is not about to lapse),\n// then signs the day with the key it enrolled with and sends everything to the workspace, which\n// verifies the signature. A pass means the whole path works, end to end; a failure names what broke.\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { canonical } from \"@scopebond/gateway\";\nimport { loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport {\n configuredHookCommands, duplicateHooks, hookCommandResolves, hookVersion, isScopebondHookCommand, queueStatus, readDeliveryState, userHarnessFile,\n type Harness, type HookConnection,\n} from \"@scopebond/hook\";\nimport { autostartHealth } from \"./autostart.js\";\n\nexport interface SelfCheckItem { id: string; ok: boolean; detail?: string }\n\nexport function selfCheckProof(credentialId: string, gatewayId: string, day: string): string {\n return canonical({ type: \"scopebond:self-check\", version: 1, credential_id: credentialId, gateway_id: gatewayId, day });\n}\n\nexport function localChecks(dir: string, connection: HookConnection, harnesses: Harness[], now = Date.now()): SelfCheckItem[] {\n const checks: SelfCheckItem[] = [];\n const entries = harnesses.flatMap((h) => configuredHookCommands(userHarnessFile(h)).filter((c) => isScopebondHookCommand(c)));\n checks.push({ id: \"hook_entry\", ok: entries.length > 0, ...(entries.length ? {} : { detail: \"no agent setting holds the Scopebond hook\" }) });\n const broken = entries.filter((c) => !hookCommandResolves(c));\n checks.push({ id: \"hook_starts\", ok: entries.length > 0 && broken.length === 0, ...(broken.length ? { detail: `${broken.length} hook command(s) cannot start` } : {}) });\n // SB302: the hook twice in the user settings, or an enabled plugin beside them, signs and sends every action twice.\n const dupes = harnesses.flatMap((h) => duplicateHooks(h, homedir()) ? [h] : []);\n checks.push({ id: \"hook_duplicates\", ok: dupes.length === 0, ...(dupes.length ? { detail: `the Scopebond hook runs more than once per action for ${dupes.join(\", \")} (fix: ${process.platform === \"win32\" ? \"npx.cmd\" : \"npx\"} -y @scopebond/hook@${hookVersion()} dedupe)` } : {}) });\n const autostart = autostartHealth(dir);\n checks.push({ id: \"autostart\", ok: autostart.ok, ...(autostart.ok ? {} : { detail: autostart.detail }) });\n const { pending, oldest } = queueStatus(dir);\n const state = readDeliveryState(dir);\n const stuck = pending > 0 && oldest !== null && now - oldest > 60 * 60 * 1000;\n checks.push({ id: \"queue\", ok: !stuck, ...(stuck ? { detail: `${pending} record(s) waiting since ${new Date(oldest!).toISOString()}${state.last_error ? ` (${state.last_error.slice(0, 120)})` : \"\"}` } : {}) });\n const expires = Date.parse(connection.expires_at ?? \"\");\n const lapsing = Number.isFinite(expires) && expires - now < 7 * 24 * 60 * 60 * 1000;\n checks.push({ id: \"credential\", ok: !lapsing, ...(lapsing ? { detail: `the connection expires ${new Date(expires).toISOString()} and was not renewed` } : {}) });\n return checks;\n}\n\nexport async function runSelfCheck(\n dir: string, connection: HookConnection, harnesses: Harness[], agentVersion: string,\n options: { fetchImpl?: typeof fetch; now?: number; timeoutMs?: number } = {},\n): Promise<{ ok: boolean; signature_verified: boolean; failed: string[]; checks: SelfCheckItem[] } | null> {\n const now = options.now ?? Date.now();\n const checks = localChecks(dir, connection, harnesses, now);\n const keyFile = join(dir, \"attester.key\");\n if (!existsSync(keyFile)) return { ok: false, signature_verified: false, failed: [\"signing_key\"], checks };\n const day = new Date(now).toISOString().slice(0, 10);\n const { attester } = loadOrCreateAttester({ file: keyFile });\n const signature = await attester.sign(selfCheckProof(connection.credential_id, connection.gateway_id, day));\n try {\n const res = await (options.fetchImpl ?? fetch)(new URL(\"/v1/self-check\", connection.url).toString(), {\n method: \"POST\", redirect: \"error\", signal: AbortSignal.timeout(options.timeoutMs ?? 10_000),\n headers: { authorization: `Bearer ${connection.credential}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ signature, day, checks, hook_version: hookVersion(), agent_version: agentVersion }),\n });\n // A workspace that does not offer the self-check yet answers 404: the computer's own checks still count; the signed\n // workspace part is simply not available there.\n if (res.status === 404) { const failed = checks.filter((c) => !c.ok).map((c) => c.id); return { ok: failed.length === 0, signature_verified: false, failed, checks }; }\n if (!res.ok) return { ok: false, signature_verified: false, failed: [`workspace_http_${res.status}`], checks };\n const body = await res.json() as { ok?: boolean; signature_verified?: boolean; failed?: string[] };\n return { ok: !!body.ok, signature_verified: !!body.signature_verified, failed: Array.isArray(body.failed) ? body.failed : [], checks };\n } catch (error) {\n return { ok: false, signature_verified: false, failed: [`workspace_unreachable: ${(error as Error).message.slice(0, 80)}`], checks };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"selfcheck.js","sourceRoot":"","sources":["../src/selfcheck.ts"],"names":[],"mappings":"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","sourcesContent":["// The daily end-to-end self-check (SB347). The agent checks this computer's side (the hook entry\n// is present and starts, autostart works, nothing is stuck, the connection is not about to lapse),\n// then signs the day with the key it enrolled with and sends everything to the workspace, which\n// verifies the signature. A pass means the whole path works, end to end; a failure names what broke.\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { canonical } from \"@scopebond/gateway\";\nimport { loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport {\n configuredHookCommands, duplicateHooks, hookCommandResolves, hookVersion, isScopebondHookCommand, queueStatus, readDeliveryState, userHarnessFile,\n type Harness, type HookConnection,\n} from \"@scopebond/hook\";\nimport { autostartHealth } from \"./autostart.js\";\nimport { installKind } from \"./native-update.js\";\n\nexport interface SelfCheckItem { id: string; ok: boolean; detail?: string }\n\nexport function selfCheckProof(credentialId: string, gatewayId: string, day: string): string {\n return canonical({ type: \"scopebond:self-check\", version: 1, credential_id: credentialId, gateway_id: gatewayId, day });\n}\n\nexport function localChecks(dir: string, connection: HookConnection, harnesses: Harness[], now = Date.now()): SelfCheckItem[] {\n const checks: SelfCheckItem[] = [];\n const entries = harnesses.flatMap((h) => configuredHookCommands(userHarnessFile(h)).filter((c) => isScopebondHookCommand(c)));\n checks.push({ id: \"hook_entry\", ok: entries.length > 0, ...(entries.length ? {} : { detail: \"no agent setting holds the Scopebond hook\" }) });\n const broken = entries.filter((c) => !hookCommandResolves(c));\n checks.push({ id: \"hook_starts\", ok: entries.length > 0 && broken.length === 0, ...(broken.length ? { detail: `${broken.length} hook command(s) cannot start` } : {}) });\n // SB302: the hook twice in the user settings, or an enabled plugin beside them, signs and sends every action twice.\n const dupes = harnesses.flatMap((h) => duplicateHooks(h, homedir()) ? [h] : []);\n checks.push({ id: \"hook_duplicates\", ok: dupes.length === 0, ...(dupes.length ? { detail: `the Scopebond hook runs more than once per action for ${dupes.join(\", \")} (fix: ${process.platform === \"win32\" ? \"npx.cmd\" : \"npx\"} -y @scopebond/hook@${hookVersion()} dedupe)` } : {}) });\n const autostart = autostartHealth(dir);\n checks.push({ id: \"autostart\", ok: autostart.ok, ...(autostart.ok ? {} : { detail: autostart.detail }) });\n const { pending, oldest } = queueStatus(dir);\n const state = readDeliveryState(dir);\n const stuck = pending > 0 && oldest !== null && now - oldest > 60 * 60 * 1000;\n checks.push({ id: \"queue\", ok: !stuck, ...(stuck ? { detail: `${pending} record(s) waiting since ${new Date(oldest).toISOString()}${state.last_error ? ` (${state.last_error.slice(0, 120)})` : \"\"}` } : {}) });\n const expires = Date.parse(connection.expires_at ?? \"\");\n const lapsing = Number.isFinite(expires) && expires - now < 7 * 24 * 60 * 60 * 1000;\n checks.push({ id: \"credential\", ok: !lapsing, ...(lapsing ? { detail: `the connection expires ${new Date(expires).toISOString()} and was not renewed` } : {}) });\n return checks;\n}\n\nexport async function runSelfCheck(\n dir: string, connection: HookConnection, harnesses: Harness[], agentVersion: string,\n options: { fetchImpl?: typeof fetch; now?: number; timeoutMs?: number } = {},\n): Promise<{ ok: boolean; signature_verified: boolean; failed: string[]; checks: SelfCheckItem[] } | null> {\n const now = options.now ?? Date.now();\n const checks = localChecks(dir, connection, harnesses, now);\n const keyFile = join(dir, \"attester.key\");\n if (!existsSync(keyFile)) return { ok: false, signature_verified: false, failed: [\"signing_key\"], checks };\n const day = new Date(now).toISOString().slice(0, 10);\n const { attester } = loadOrCreateAttester({ file: keyFile });\n const signature = await attester.sign(selfCheckProof(connection.credential_id, connection.gateway_id, day));\n try {\n const res = await (options.fetchImpl ?? fetch)(new URL(\"/v1/self-check\", connection.url).toString(), {\n method: \"POST\", redirect: \"error\", signal: AbortSignal.timeout(options.timeoutMs ?? 10_000),\n headers: { authorization: `Bearer ${connection.credential}`, \"content-type\": \"application/json\" },\n // install_kind: how this agent was installed (npm, per-user or per-machine signed installer), so the workspace can say\n // how the computer updates and is removed. A workspace that does not read it ignores it.\n body: JSON.stringify({ signature, day, checks, hook_version: hookVersion(), agent_version: agentVersion, install_kind: installKind() }),\n });\n // A workspace that does not offer the self-check yet answers 404: the computer's own checks still count; the signed\n // workspace part is simply not available there.\n if (res.status === 404) { const failed = checks.filter((c) => !c.ok).map((c) => c.id); return { ok: failed.length === 0, signature_verified: false, failed, checks }; }\n if (!res.ok) return { ok: false, signature_verified: false, failed: [`workspace_http_${res.status}`], checks };\n const body = await res.json() as { ok?: boolean; signature_verified?: boolean; failed?: string[] };\n return { ok: !!body.ok, signature_verified: !!body.signature_verified, failed: Array.isArray(body.failed) ? body.failed : [], checks };\n } catch (error) {\n return { ok: false, signature_verified: false, failed: [`workspace_unreachable: ${(error as Error).message.slice(0, 80)}`], checks };\n }\n}\n"]}
|
package/dist/service.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type Harness } from "@scopebond/hook";
|
|
2
2
|
import { type CycleResult } from "./agent.js";
|
|
3
3
|
import { runSelfCheck } from "./selfcheck.js";
|
|
4
4
|
import { type Prompter } from "./prompt.js";
|
|
5
|
+
import { type UpkeepReport } from "./upkeep.js";
|
|
5
6
|
export declare const AGENT_VERSION: string;
|
|
6
7
|
export declare const AFTER_PID_ENV = "SCOPEBOND_AGENT_AFTER_PID";
|
|
8
|
+
/** Left in the Scopebond folder when this computer's user stops the agent (`scopebond-agent stop`), and removed when it
|
|
9
|
+
* starts: the native tray then leaves it stopped instead of starting it again. */
|
|
10
|
+
export declare const STOPPED_FILE = "agent-stopped.json";
|
|
7
11
|
/** The person's tray settings (D143: notifications about problems by default, none about blocks). */
|
|
8
12
|
export declare const TRAY_SETTINGS_FILE = "agent-settings.json";
|
|
9
13
|
export type NotificationSetting = "all" | "problems" | "off";
|
|
@@ -25,10 +29,17 @@ export interface ServiceOptions {
|
|
|
25
29
|
maintenance?: boolean;
|
|
26
30
|
/** Called after a successful update instead of restarting (tests). */
|
|
27
31
|
onUpdated?: (version: string) => void;
|
|
32
|
+
/** Confirms the newly installed agent starts and reports its version before this one hands over (tests replace it). */
|
|
33
|
+
startCheck?: (version: string) => Promise<{
|
|
34
|
+
ok: boolean;
|
|
35
|
+
output: string;
|
|
36
|
+
}>;
|
|
28
37
|
/** Shows the Scopebond window for an override (tests replace it). */
|
|
29
38
|
prompter?: Prompter;
|
|
30
39
|
/** The Windows tray icon (default on Windows; SCOPEBOND_AGENT_TRAY=off turns it off). */
|
|
31
40
|
tray?: boolean;
|
|
41
|
+
/** Runs one local store upkeep pass (default: `scopebond-agent upkeep` in a child process; tests replace it). */
|
|
42
|
+
upkeep?: (dir: string) => Promise<UpkeepReport>;
|
|
32
43
|
/** Called once the agent has stopped because `stop` (or `autostart off`) asked it to; the CLI exits. */
|
|
33
44
|
onStopped?: () => void;
|
|
34
45
|
/** Each delivery request's time limit (default 30 s) and one cycle's (default 10 minutes). A cycle that runs past its
|
|
@@ -55,7 +66,7 @@ export interface MaintenanceResult {
|
|
|
55
66
|
}>;
|
|
56
67
|
selfCheck: Awaited<ReturnType<typeof runSelfCheck>>;
|
|
57
68
|
/** The local store's upkeep this pass (D144): rows rewritten, receipts past retention removed, space returned. */
|
|
58
|
-
store?:
|
|
69
|
+
store?: UpkeepReport;
|
|
59
70
|
error: string | null;
|
|
60
71
|
}
|
|
61
72
|
/** Put the Scopebond hook back into agent settings that lost it. A visible change: each one is
|
|
@@ -96,7 +107,13 @@ export declare function spawnReplacement(dir: string, cli?: string): boolean;
|
|
|
96
107
|
/** The first thing a starting agent does: wait for the agent it replaces to exit, then, when asked, rewrite the older launcher
|
|
97
108
|
* that agent ran under (by now nothing runs it). The handover variables are dropped, so a later restart waits for nothing. */
|
|
98
109
|
export declare function takeOver(dir: string, cli: string, waitMs?: number): Promise<void>;
|
|
99
|
-
export declare function waitForExit(pid: number, timeoutMs: number): Promise<void>;
|
|
110
|
+
export declare function waitForExit(pid: number, timeoutMs: number, released?: () => boolean): Promise<void>;
|
|
111
|
+
/** Whether the one-agent lock names `pid`. */
|
|
112
|
+
export declare function lockHeldBy(dir: string, pid: number): boolean;
|
|
113
|
+
/** How long the agent that handed over waits for its replacement to answer before going back to its own version. */
|
|
114
|
+
export declare const HANDOVER_CONFIRM_MS: number;
|
|
115
|
+
/** Wait until an agent other than this process answers on the local channel reporting `version`. */
|
|
116
|
+
export declare function waitForAgentVersion(dir: string, version: string, timeoutMs: number): Promise<boolean>;
|
|
100
117
|
export declare const AGENT_LOCK = "agent.lock";
|
|
101
118
|
/** How long a lock whose agent never answered on its local channel still counts as an agent starting up. */
|
|
102
119
|
export declare const AGENT_LOCK_STARTING_MS = 60000;
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AASA,OAAO,EAA+
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|