fix: make Host environment updates fast and recoverable
GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build Linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build Linux x64 Agent (push) Canceled after 0s
Cross-platform packages / Validate source (push) Canceled after 0s
GoodBuddy Agent Release / Authorize Agent release (push) Canceled after 0s
GoodBuddy Agent Release / Publish Agent to GitHub and OSS (push) Canceled after 0s
Cross-platform packages / Authorize desktop packaging (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub and OSS release (push) Canceled after 0s
GoodBuddy Agent Release / Build Linux arm64 compound package (push) Canceled after 0s
GoodBuddy Agent Release / Build Linux x64 compound package (push) Canceled after 0s
GoodBuddy Agent Release / Sign cumulative Agent catalog (push) Canceled after 0s

Published Host updates could fail while the desktop reverified Runtime against
its bundled lock and repeatedly traversed remote payloads. Host preparation now
verifies and extracts once, adopts Agent and Runtime on one pinned connection,
and uses registered metadata for normal health, capability, and prompt paths.
Interrupted commits and adoption retain bounded recovery and rollback state.

Desktop and Agent versions are 0.11.8. Remote Projects remain a technical
preview; the Agent targets Linux x64 and arm64, with no LoongArch preview.

Release note: 修复正式环境 Host 更新失败并移除重复远端包体扫描;中断恢复与清理失败不再破坏已健康环境。
This commit is contained in:
mesalogo
2026-08-29 17:20:25 +08:00
parent ff4fde282f
commit a99b90cc02
42 changed files with 3292 additions and 5559 deletions
+43 -1
View File
@@ -192,11 +192,13 @@ describe('Agent CLI fixed command contract', () => {
state: 'ready' as const,
installationId
}))
const verifyInstallation = vi.fn(async () => verified)
const dependencies: AgentCliDependencies = {
installationPaths: () => installationPaths,
releaseKeyRegistry,
installationRegistry,
verifyInstallation: async () => verified,
verifyInstallation,
loadRegisteredInstallation: async () => verified,
createLifecycle: (() => ({
status,
bootstrap
@@ -227,6 +229,21 @@ describe('Agent CLI fixed command contract', () => {
).toBe(0)
expect(status).toHaveBeenCalledOnce()
expect(bootstrap).toHaveBeenCalledOnce()
expect(
installationRegistry.snapshot().current?.installationId
).toBe(installationId)
expect(
await runAgentCli(
buildFixedAgentCliArgv(installationId, {
kind: 'lifecycle',
action: 'adopt'
}),
{ ...dependencies, io: cliIo() }
)
).toBe(0)
expect(verifyInstallation).toHaveBeenCalledOnce()
expect(bootstrap).toHaveBeenCalledTimes(2)
})
it('dispatches generated attach argv using only derived managed paths', async () => {
@@ -469,6 +486,31 @@ describe('Agent CLI fixed command contract', () => {
architecture: 'x64',
runtimeVersion: '1.18.9'
})
expect(
await runAgentCli(
buildFixedAgentCliArgv(
verifyAgentInstallationId('install-1'),
{
kind: 'runtime-activate',
runtimeId: 'opencode',
bundleDigest,
architecture: 'x64',
forceVerification: true
}
),
{
runtimePaths: () => paths,
runtimeReleaseKeyRegistry: releaseKeyRegistry,
runtimeLock: {} as RemoteRuntimeLock,
runtimeRegistry: registry,
verifyRuntime,
currentArchitecture: () => 'x64',
io: cliIo()
}
)
).toBe(0)
expect(verifyRuntime).toHaveBeenCalledTimes(2)
})
it('derives Runtime paths and rejects activation argv injection', async () => {
+183 -40
View File
@@ -39,6 +39,7 @@ import {
RuntimeBundleRegistry
} from './runtime-bundle-registry'
import {
loadRegisteredRuntimeBundle,
readRemoteRuntimeLock,
verifyRuntimeBundle,
type VerifiedRuntimeBundle
@@ -111,6 +112,7 @@ export type ManagedRuntimePaths = {
}
const LIFECYCLE_ACTIONS = new Set([
'adopt',
'bootstrap',
'status',
'health',
@@ -225,7 +227,8 @@ async function runRuntime(
'installation-id',
'runtime-id',
'bundle-digest',
'architecture'
'architecture',
'force-verification'
])
requireOptions(options, [
'installation-id',
@@ -243,6 +246,16 @@ async function runRuntime(
const architecture = validateRuntimeArchitecture(
options.architecture!
)
const forceVerification =
options['force-verification'] === 'true'
if (
options['force-verification'] !== undefined &&
!forceVerification
) {
throw new Error(
'Invalid Runtime force-verification option'
)
}
const hostArchitecture =
dependencies.currentArchitecture?.() ??
currentAgentArchitecture()
@@ -271,15 +284,30 @@ async function runRuntime(
runtimeRoot: paths.runtimeRoot,
storagePath: paths.registryPath
})
const verified = await (
dependencies.verifyRuntime ?? verifyRuntimeBundle
)(paths.bundleDirectory, {
const verificationOptions = {
architecture,
releaseKeyRegistry,
runtimeLock,
verificationEnvironment:
dependencies.runtimeVerificationEnvironment ?? 'production'
})
} as const
const registered = registry.find(
runtimeId,
bundleDigest,
architecture
)
const verified =
registered === undefined || forceVerification
? await (
dependencies.verifyRuntime ?? verifyRuntimeBundle
)(paths.bundleDirectory, verificationOptions)
: await loadRegisteredRuntimeBundle(
registered.bundleDirectory,
{
...verificationOptions,
registered: registered.entry
}
)
assertActivatedRuntimeIdentity(
verified,
runtimeId,
@@ -352,7 +380,8 @@ async function runDaemon(
installationId,
paths,
dependencies,
'registered'
'registered',
verified
).recordCurrentDaemonReady(daemon.status().daemonBootId)
await (dependencies.waitForShutdown?.() ?? waitForShutdownSignal())
} finally {
@@ -374,7 +403,7 @@ async function runAttach(
installationId,
dependencies
)
await loadManagedInstallation(
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
@@ -399,7 +428,8 @@ async function runAttach(
installationId,
paths,
dependencies,
'registered'
'registered',
verified
).bootstrap()
}
})
@@ -451,10 +481,17 @@ async function runDoctor(
options['installation-id']!
)
const paths = resolveInstallationPaths(installationId, dependencies)
const status = await createDetachedLifecycle(
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
)
const status = await createDetachedLifecycle(
installationId,
paths,
dependencies,
'registered',
verified
).status()
io.output.write(`${JSON.stringify({
platform: process.platform,
@@ -479,48 +516,150 @@ async function runLifecycle(
options['installation-id']!
)
const paths = resolveInstallationPaths(installationId, dependencies)
const { verified, registry } = await verifyManagedInstallation(
installationId,
paths,
dependencies
)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies
)
switch (action) {
case 'bootstrap': {
registry.stageCandidate(verified)
prepareManagedSocketDirectory(paths)
const status = await lifecycle.bootstrap()
io.output.write(`${JSON.stringify(status)}\n`)
break
}
case 'status': {
registry.assertVerifiedRole(verified, ['current', 'candidate'])
io.output.write(`${JSON.stringify(await lifecycle.status())}\n`)
break
}
case 'health': {
registry.assertVerifiedRole(verified, ['current', 'candidate'])
const status = await lifecycle.health()
if (
registry.snapshot().candidate?.installationId ===
case 'adopt': {
const { verified, registry } =
await verifyManagedInstallation(
installationId,
paths,
dependencies
)
const alreadyCurrent =
registry.snapshot().current?.installationId ===
installationId
) {
if (!alreadyCurrent) {
registry.stageCandidate(verified)
}
prepareManagedSocketDirectory(paths)
const status = await createDetachedLifecycle(
installationId,
paths,
dependencies,
'verified',
verified
).bootstrap()
if (!alreadyCurrent) {
registry.promoteCandidate(installationId)
}
io.output.write(`${JSON.stringify(status)}\n`)
break
}
case 'bootstrap': {
const agentRoot = dirname(
dirname(dirname(paths.executablePath))
)
const registry =
dependencies.installationRegistry ??
new InstallationRegistry({
storagePath: resolve(agentRoot, 'registry.json')
})
const snapshot = registry.snapshot()
const current = snapshot.current?.installationId ===
installationId
? snapshot.current
: undefined
const candidate = snapshot.candidate?.installationId ===
installationId
? snapshot.candidate
: undefined
const registered = current ?? candidate
const isNewInstallation = registered === undefined
const verified = isNewInstallation
? (
await verifyManagedInstallation(
installationId,
paths,
dependencies
)
).verified
: await (
dependencies.loadRegisteredInstallation ??
loadRegisteredAgentBundle
)(dirname(paths.executablePath), {
installationId,
architecture: currentAgentArchitecture(),
registered
})
if (isNewInstallation) {
registry.stageCandidate(verified)
}
prepareManagedSocketDirectory(paths)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies,
'verified',
verified
)
const status = await lifecycle.bootstrap()
if (current === undefined) {
registry.promoteCandidate(installationId)
}
io.output.write(`${JSON.stringify(status)}\n`)
break
}
case 'status': {
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies,
'registered',
verified
)
io.output.write(`${JSON.stringify(await lifecycle.status())}\n`)
break
}
case 'health': {
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies,
'registered',
verified
)
const status = await lifecycle.health()
io.output.write(`${JSON.stringify(status)}\n`)
break
}
case 'stop': {
registry.assertVerifiedRole(verified, ['current', 'candidate'])
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies,
'registered',
verified
)
io.output.write(`${JSON.stringify(await lifecycle.stop())}\n`)
break
}
case 'retire': {
registry.assertVerifiedRole(verified, ['current', 'candidate'])
const { verified } = await loadManagedInstallation(
installationId,
paths,
dependencies
)
const lifecycle = createDetachedLifecycle(
installationId,
paths,
dependencies,
'registered',
verified
)
io.output.write(`${JSON.stringify(await lifecycle.retire())}\n`)
break
}
@@ -531,7 +670,8 @@ function createDetachedLifecycle(
installationId: string,
paths: ManagedInstallationPaths,
dependencies: AgentCliDependencies,
identitySource: 'verified' | 'registered' = 'verified'
identitySource: 'verified' | 'registered' = 'verified',
verifiedInstallation?: VerifiedInstalledAgentBundle
): DetachedAgentLifecycle {
const options: DetachedAgentLifecycleOptions = {
installationId,
@@ -539,6 +679,9 @@ function createDetachedLifecycle(
stateDirectory: paths.stateDirectory,
socketPath: paths.socketPath,
verifyInstallation: async () => {
if (verifiedInstallation !== undefined) {
return verifiedInstallation
}
if (identitySource === 'registered') {
return (
await loadManagedInstallation(
@@ -116,7 +116,8 @@ describe('Agent installation registry', () => {
installationId: 'install-a',
agentVersion: '0.11.0',
manifestSha256: 'a'.repeat(64),
arch: 'x64'
arch: 'x64',
protocol: { major: 1, minor: 0 }
}
})
expect(readFileSync(storagePath, 'utf8')).toBe(legacyBytes)
+2 -1
View File
@@ -221,7 +221,8 @@ function entryFromVerified(
installationId: verified.installationId,
agentVersion: verified.manifest.agentVersion,
manifestSha256: verified.manifestSha256,
arch: verified.manifest.arch
arch: verified.manifest.arch,
protocol: verified.manifest.protocol
})
}
+10 -1
View File
@@ -310,7 +310,16 @@ async function loadRegisteredAgentBundleUnchecked(
manifestBytes
) ||
manifest.agentVersion !== registered.agentVersion ||
manifest.arch !== registered.arch
manifest.arch !== registered.arch ||
(
registered.protocol !== undefined &&
(
manifest.protocol.major !==
registered.protocol.major ||
manifest.protocol.minor !==
registered.protocol.minor
)
)
) {
throw new Error(
'Agent manifest does not match the Host-managed registry'
+1 -1
View File
@@ -268,7 +268,7 @@ function harness(input: {
const backend = new RuntimeAcpBackend({
journal,
resolveRuntimeBundle: vi.fn(async () => resolved),
reverifyRuntimeBundle: vi.fn(async () => verifiedBundle()),
loadRegisteredRuntimeBundle: vi.fn(async () => verifiedBundle()),
resolveWorkspace: vi.fn(async (preparation) => ({
workspaceIdentity: preparation.workspaceIdentity,
workspaceDirectory: '/workspace',
+2 -2
View File
@@ -227,7 +227,7 @@ export type RuntimeAcpBackendOptions = {
runtimeId: string,
runtimeBundleDigest: string
): RuntimeAcpResolvedBundle | Promise<RuntimeAcpResolvedBundle>
reverifyRuntimeBundle(
loadRegisteredRuntimeBundle(
resolved: RuntimeAcpResolvedBundle,
preparation: RemotePromptOperationPreparation
): RuntimeAcpVerifiedBundle | Promise<RuntimeAcpVerifiedBundle>
@@ -947,7 +947,7 @@ export class RuntimeAcpBackend {
let verified: RuntimeAcpVerifiedBundle
try {
verified = await this.#options.reverifyRuntimeBundle(
verified = await this.#options.loadRegisteredRuntimeBundle(
binding.resolvedBundle,
preparation
)
+75 -43
View File
@@ -25,7 +25,7 @@ import {
} from './managed-paths'
import type { InstalledBundleVerificationEnvironment } from './installed-bundle-verifier'
import {
verifyRuntimeBundle,
loadRegisteredRuntimeBundle,
type VerifiedRuntimeBundle
} from './runtime-bundle-verifier'
@@ -120,6 +120,27 @@ export class RuntimeBundleRegistry {
entry: RuntimeRegistryEntry
bundleDirectory: string
} {
const resolved = this.find(
runtimeIdInput,
bundleDigestInput,
architecture
)
if (resolved === undefined) {
throw new Error(
'Runtime bundle is not the verified current bundle'
)
}
return resolved
}
find(
runtimeIdInput: string,
bundleDigestInput: string,
architecture: AgentArchitecture
): {
entry: RuntimeRegistryEntry
bundleDirectory: string
} | undefined {
const runtimeId = agentIdentifierSchema.parse(runtimeIdInput)
const bundleDigest = sha256DigestSchema.parse(bundleDigestInput)
this.#state = this.#load({ createIfMissing: false })
@@ -130,9 +151,7 @@ export class RuntimeBundleRegistry {
candidate.architecture === architecture
)
if (entry === undefined) {
throw new Error(
'Runtime bundle is not the verified current bundle'
)
return undefined
}
return {
entry: { ...entry },
@@ -231,7 +250,7 @@ export class RuntimeBundleRegistry {
}
}
export function createVerifiedRuntimeCapabilitySource(options: {
type VerifiedRuntimeCapabilitySourceOptions = {
registry: RuntimeBundleRegistry
architecture: AgentArchitecture
releaseKeyRegistry: AgentReleaseKeyRegistry
@@ -241,53 +260,65 @@ export function createVerifiedRuntimeCapabilitySource(options: {
filesystemPlatform?: NodeJS.Platform
uid?: number
reportError?: (message: string, error: unknown) => void
}): () => Promise<DaemonCapabilities['runtimes']> {
loadRegistered?: (
entry: RuntimeRegistryEntry,
bundleDirectory: string
) => Promise<VerifiedRuntimeBundle>
}
export function createVerifiedRuntimeCapabilitySource(
options: VerifiedRuntimeCapabilitySourceOptions
): () => Promise<DaemonCapabilities['runtimes']> {
return async () => await loadVerifiedRuntimeCapabilities(options)
}
async function loadVerifiedRuntimeCapabilities(options: {
registry: RuntimeBundleRegistry
architecture: AgentArchitecture
releaseKeyRegistry: AgentReleaseKeyRegistry
runtimeLock: RemoteRuntimeLock
verificationEnvironment?: InstalledBundleVerificationEnvironment
enforceFilesystemMode?: boolean
filesystemPlatform?: NodeJS.Platform
uid?: number
reportError?: (message: string, error: unknown) => void
}): Promise<DaemonCapabilities['runtimes']> {
async function loadVerifiedRuntimeCapabilities(
options: VerifiedRuntimeCapabilitySourceOptions
): Promise<DaemonCapabilities['runtimes']> {
const capabilities: DaemonCapabilities['runtimes'] = []
for (const entry of options.registry.current(options.architecture)) {
try {
const verified = await verifyRuntimeBundle(
const bundleDirectory =
options.registry.bundleDirectory(
entry.runtimeId,
entry.bundleDigest
),
{
architecture: options.architecture,
releaseKeyRegistry: options.releaseKeyRegistry,
runtimeLock: options.runtimeLock,
...(options.verificationEnvironment === undefined
? {}
: {
verificationEnvironment:
options.verificationEnvironment
}),
...(options.enforceFilesystemMode === undefined
? {}
: {
enforceFilesystemMode:
options.enforceFilesystemMode
}),
...(options.filesystemPlatform === undefined
? {}
: {
filesystemPlatform: options.filesystemPlatform
}),
...(options.uid === undefined ? {} : { uid: options.uid })
}
)
)
const verified = options.loadRegistered === undefined
? await loadRegisteredRuntimeBundle(
bundleDirectory,
{
registered: entry,
architecture: options.architecture,
releaseKeyRegistry:
options.releaseKeyRegistry,
runtimeLock: options.runtimeLock,
...(options.verificationEnvironment === undefined
? {}
: {
verificationEnvironment:
options.verificationEnvironment
}),
...(options.enforceFilesystemMode === undefined
? {}
: {
enforceFilesystemMode:
options.enforceFilesystemMode
}),
...(options.filesystemPlatform === undefined
? {}
: {
filesystemPlatform:
options.filesystemPlatform
}),
...(options.uid === undefined
? {}
: { uid: options.uid })
}
)
: await options.loadRegistered(
entry,
bundleDirectory
)
if (
verified.manifest.runtimeVersion !== entry.runtimeVersion ||
verified.manifestDigest !== entry.manifestDigest ||
@@ -326,6 +357,7 @@ function entryFromVerified(
architecture: verified.manifest.architecture,
bundleDigest: verified.manifest.bundleDigest,
manifestDigest: verified.manifestDigest,
runtimeAdapterDigest: verified.manifest.adapterDigest,
acpCapabilitiesDigest:
verified.manifest.acpCapabilitiesDigest
})
@@ -155,7 +155,7 @@ describe('Remote Runtime bundle verifier', () => {
).rejects.toThrow(/managed directory/iu)
})
it('advertises only a bundle that still verifies against its registry', async () => {
it('uses registered metadata without rereading Runtime payload files', async () => {
const fixture = await createBundle()
const runtimeRoot = dirname(dirname(fixture.bundleDirectory))
const registry = new RuntimeBundleRegistry({
@@ -198,6 +198,18 @@ describe('Remote Runtime bundle verifier', () => {
join(fixture.bundleDirectory, 'licenses', 'opencode.txt'),
'mutated'
)
await expect(capabilities()).resolves.toHaveLength(1)
expect(reportError).not.toHaveBeenCalled()
writeFileSync(
join(fixture.bundleDirectory, 'bin', 'opencode'),
Buffer.concat([
readFileSync(
join(fixture.bundleDirectory, 'bin', 'opencode')
),
Buffer.from('changed')
])
)
await expect(capabilities()).resolves.toEqual([])
expect(reportError).toHaveBeenCalledWith(
'Verified Runtime unavailable: opencode',
@@ -1,5 +1,6 @@
export {
canonicalRuntimeManifestBytes,
loadRegisteredRuntimeBundle,
readRemoteRuntimeLock,
runtimeManifestSignaturePayload,
verifyRuntimeBundle,
@@ -8,5 +9,6 @@ export {
export type {
VerifiedRuntimeBundle,
LoadRegisteredRuntimeBundleOptions,
VerifyRuntimeBundleOptions
} from '../shared/node/runtime-bundle-verifier'
+3 -6
View File
@@ -37,7 +37,7 @@ afterEach(() => {
})
describe('production Runtime composition', () => {
it('keeps ACP live and reloads managed metadata installed after daemon startup', async () => {
it('loads metadata installed after startup and caches the registered Runtime identity', async () => {
const fixture = await createRuntimeBundleTestFixture()
const root = fixture.root
temporaryPaths.push(root)
@@ -121,11 +121,8 @@ describe('production Runtime composition', () => {
}, null, 2)}\n`,
{ mode: 0o600 }
)
await expect(protocol.runtimes()).resolves.toEqual([])
expect(reportError).toHaveBeenCalledWith(
'Verified Runtime unavailable: opencode',
expect.any(Error)
)
await expect(protocol.runtimes()).resolves.toHaveLength(1)
expect(reportError).not.toHaveBeenCalled()
await expect(protocol.dispose()).resolves.toBeUndefined()
events.close()
+88 -31
View File
@@ -7,6 +7,9 @@ import type {
AgentReleaseKeyRegistry
} from '../shared/agent-installation-contracts'
import type { AgentFrame } from '../shared/agent-protocol'
import type {
RuntimeRegistryEntry
} from '../shared/remote-environment-registry-contracts'
import type { RemoteRuntimeLock } from '../shared/remote-runtime-launch-contracts'
import type { EventJournal } from './event-journal'
import {
@@ -22,7 +25,8 @@ import {
} from './runtime-bundle-registry'
import {
readRemoteRuntimeLock,
verifyRuntimeBundle
loadRegisteredRuntimeBundle,
type VerifiedRuntimeBundle
} from './runtime-bundle-verifier'
import { RuntimeAcpBackend } from './runtime-acp-backend'
import type { ProtocolMethodContext } from './protocol-server'
@@ -111,37 +115,90 @@ export async function createProductionRuntimeProtocol(
}
return registry
}
const currentVerificationOptions = async () => {
const metadataOptions =
options.filesystemPlatform === undefined
? {}
: { filesystemPlatform: options.filesystemPlatform }
const [releaseKeyRegistry, runtimeLock] = await Promise.all([
options.releaseKeyRegistry ??
readManagedAgentReleaseKeyRegistry(
join(runtimeRoot, 'release-keys.json'),
metadataOptions
),
options.runtimeLock ??
readRemoteRuntimeLock(
join(runtimeRoot, 'remote-runtime-lock.json'),
metadataOptions
)
])
return {
architecture: options.architecture,
releaseKeyRegistry,
runtimeLock,
verificationEnvironment,
...(options.filesystemPlatform === undefined
? {}
: { filesystemPlatform: options.filesystemPlatform })
} as const
let verificationOptionsPromise:
| Promise<{
architecture: AgentArchitecture
releaseKeyRegistry: AgentReleaseKeyRegistry
runtimeLock: RemoteRuntimeLock
verificationEnvironment: 'production' | 'test'
filesystemPlatform?: NodeJS.Platform
}>
| undefined
const currentVerificationOptions = () => {
verificationOptionsPromise ??= (async () => {
const metadataOptions =
options.filesystemPlatform === undefined
? {}
: {
filesystemPlatform:
options.filesystemPlatform
}
const [releaseKeyRegistry, runtimeLock] =
await Promise.all([
options.releaseKeyRegistry ??
readManagedAgentReleaseKeyRegistry(
join(runtimeRoot, 'release-keys.json'),
metadataOptions
),
options.runtimeLock ??
readRemoteRuntimeLock(
join(
runtimeRoot,
'remote-runtime-lock.json'
),
metadataOptions
)
])
return {
architecture: options.architecture,
releaseKeyRegistry,
runtimeLock,
verificationEnvironment,
...(options.filesystemPlatform === undefined
? {}
: {
filesystemPlatform:
options.filesystemPlatform
})
}
})()
void verificationOptionsPromise.catch(() => {
verificationOptionsPromise = undefined
})
return verificationOptionsPromise
}
const verifiedRuntimeCache =
new Map<string, Promise<VerifiedRuntimeBundle>>()
const loadRegistered = (
entry: RuntimeRegistryEntry,
bundleDirectory: string
): Promise<VerifiedRuntimeBundle> => {
const key = `${bundleDirectory}\0${JSON.stringify(entry)}`
const cached = verifiedRuntimeCache.get(key)
if (cached !== undefined) {
return cached
}
const loading = (async () =>
await loadRegisteredRuntimeBundle(
bundleDirectory,
{
...(await currentVerificationOptions()),
registered: entry
}
))()
verifiedRuntimeCache.set(key, loading)
void loading.catch(() => {
if (verifiedRuntimeCache.get(key) === loading) {
verifiedRuntimeCache.delete(key)
}
})
return loading
}
const verifiedCapabilities = async () => {
const source = createVerifiedRuntimeCapabilitySource({
registry: currentRegistry(),
...(await currentVerificationOptions()),
loadRegistered,
reportError: options.reportError
})
return await source()
@@ -182,10 +239,10 @@ export async function createProductionRuntimeProtocol(
bundleDigest,
options.architecture
),
reverifyRuntimeBundle: async (resolved) => {
const verified = await verifyRuntimeBundle(
resolved.bundleDirectory,
await currentVerificationOptions()
loadRegisteredRuntimeBundle: async (resolved) => {
const verified = await loadRegistered(
resolved.entry,
resolved.bundleDirectory
)
if (
verified.manifestDigest !== resolved.entry.manifestDigest ||