feat: ship skill and MCP workflows with signed updater for v0.0.7
This commit is contained in:
1 parent
1b52df0603
commit
a01085c656
136 files changed
+18646
-217
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import fsp from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import {
|
||||
DEFAULT_PRIVATE_KEY,
|
||||
DEFAULT_PUBLIC_KEY,
|
||||
assertOutsideRepo,
|
||||
generateEd25519KeyPair,
|
||||
parseOptions,
|
||||
publicKeyFingerprint,
|
||||
resolvePath,
|
||||
runProcess,
|
||||
usageError,
|
||||
writeFileAtomic
|
||||
} from './lib.mjs'
|
||||
|
||||
const usage = `Usage:
|
||||
node scripts/updates/init-key.mjs [--private-key <path>] [--public-key <path>] [--force]
|
||||
|
||||
The private key must remain outside the repository. The default private key is:
|
||||
${DEFAULT_PRIVATE_KEY}
|
||||
`
|
||||
|
||||
function secureWindowsAcl(filename, isDirectory = false) {
|
||||
if (process.platform !== 'win32') return
|
||||
const identity = runProcess('whoami', []).trim()
|
||||
if (!identity) throw new Error('Unable to determine the current Windows identity')
|
||||
const permission = isDirectory ? `${identity}:(OI)(CI)F` : `${identity}:(F)`
|
||||
runProcess('icacls', [filename, '/inheritance:r', '/grant:r', permission])
|
||||
}
|
||||
|
||||
async function pathExists(filename) {
|
||||
try {
|
||||
await fsp.access(filename)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const options = parseOptions(process.argv.slice(2), {
|
||||
values: ['private-key', 'public-key'],
|
||||
booleans: ['force']
|
||||
})
|
||||
const privateKeyPath = await assertOutsideRepo(
|
||||
resolvePath(options['private-key'] || DEFAULT_PRIVATE_KEY),
|
||||
'Private key'
|
||||
)
|
||||
const publicKeyPath = resolvePath(options['public-key'] || DEFAULT_PUBLIC_KEY)
|
||||
|
||||
if (!options.force) {
|
||||
if (await pathExists(privateKeyPath)) throw new Error(`Refusing to overwrite existing private key: ${privateKeyPath}`)
|
||||
if (await pathExists(publicKeyPath)) throw new Error(`Refusing to overwrite existing public key: ${publicKeyPath}`)
|
||||
}
|
||||
|
||||
const keyPair = generateEd25519KeyPair()
|
||||
const directory = path.dirname(privateKeyPath)
|
||||
await fsp.mkdir(directory, { recursive: true, mode: 0o700 })
|
||||
try {
|
||||
await fsp.chmod(directory, 0o700)
|
||||
} catch {
|
||||
// Windows ACLs are applied below.
|
||||
}
|
||||
secureWindowsAcl(directory, true)
|
||||
|
||||
await writeFileAtomic(privateKeyPath, keyPair.privatePem, 0o600)
|
||||
try {
|
||||
await fsp.chmod(privateKeyPath, 0o600)
|
||||
} catch {
|
||||
// Windows ACLs are applied below.
|
||||
}
|
||||
secureWindowsAcl(privateKeyPath)
|
||||
await writeFileAtomic(publicKeyPath, keyPair.publicPem, 0o644)
|
||||
|
||||
console.log(`Private key: ${privateKeyPath}`)
|
||||
console.log(`Public key: ${publicKeyPath}`)
|
||||
console.log(`Public key SHA-256 fingerprint: ${publicKeyFingerprint(keyPair.publicPem)}`)
|
||||
console.log('Private key material was not printed. Back up the private key separately before rotating it.')
|
||||
}
|
||||
|
||||
main().catch((error) => usageError(usage, error))
|
||||
Reference in new issue
Block a user