Files
hermes-agent/apps/desktop/scripts/mac-sign.mjs
ethernet 5eec230f48 fix(bundle): record tool digests after signing transforms
Staging digests became stale after PE repair or payload signing.
Refresh all tool facts atomically while preserving their identity.
Windows refreshes after the batch signer. The macOS wrapper delegates
to the installed signer and refreshes after children, before the outer
app signature. Entitlements and file selection remain intact.

The real builder dispatcher caught the rejected factory shape. Tests
execute the installed signing walk with only codesign intercepted,
then compare the recorded bytes at the outer signing boundary.
Corrupt facts abort that boundary. Enabling batching fails the tests.

Verification: 80 Python tests passed with 3 host skips. 36 JavaScript
tests passed with 1 host skip. Lint, config typecheck and schema pass.
No real Apple/Azure signature, native package install or release run.
2026-09-09 23:35:59 -04:00

29 lines
1.2 KiB
JavaScript

import path from 'node:path'
import { rehashPayloadDigests } from './payload-digests.mjs'
/**
* @param {Pick<import('app-builder-lib').ElectronSignOptions, 'entitlements' | 'entitlementsInherit' | 'hardenedRuntime'> & { ignore: (file: string) => boolean }} policy
* @returns {(opts: import('@electron/osx-sign').SignOptions, packager: import('app-builder-lib').MacPackager) => Promise<void>}
*/
export function createMacSigner(policy) {
return async (opts, packager) => {
const target = opts.platform === 'mas' ? (opts.type === 'development' ? 'mas-dev' : 'mas') : 'mac'
const optionsForFile = await packager.helper.getOptionsForFile(opts.app, target, policy)
const inheritedIgnore = opts.ignore
const { sign } = await import('@electron/osx-sign')
await sign({
...opts,
ignore: file => (typeof inheritedIgnore === 'function' && inheritedIgnore(file)) || policy.ignore(file),
// Batching defers child signatures until after all option callbacks.
batchCodesignCalls: false,
optionsForFile: file => {
if (file === opts.app) {
rehashPayloadDigests(path.join(opts.app, 'Contents', 'Resources', 'agent-payload'))
}
return optionsForFile(file)
}
})
}
}