Track project-relative native credentials during verification

Include relative configuration and certificate files from the captured native environment so changed credentials invalidate cached readiness. Verified with the main security and agent catalog test suites.
This commit is contained in:
Ryder Sun committed 2026-11-08 00:47:11 +08:00
1 parent 655b94b85d
commit 5de5f88b0b
2 files changed
+27 -1

No files matched your search

+9 -1
View File
@@ -4,6 +4,7 @@ const fs = require('node:fs')
const path = require('node:path')
const { redactSecrets } = require('./security/secret-redaction.cjs')
const { ensurePrivateDirectory } = require('./security/private-file.cjs')
const { projectVerificationIdentity } = require('./workspace/agent-verification-identity.cjs')
const { NATIVE_CONFIG_DIRECTORIES, NATIVE_CONFIG_IDENTITY_DIRECTORY, NATIVE_ENVIRONMENT_IDENTITY, NATIVE_AUTH_IDENTITY_FILES, NATIVE_PROJECT_CONFIG_PATHS,
nativeConfigEnvironment, nativeIdentityDirectory, nativeEnvironmentIdentity, nativeAuthIdentityFiles, nativeProjectConfigPaths, nativeNetworkIdentityFiles, validateNativeConfigDirectory } = require('./agents/native-config-directory.cjs')
const { AttachmentStore } = require('./attachments/attachment-store.cjs')
@@ -414,11 +415,18 @@ async function resolveProjectEnvironmentIdentities(workdir, kinds) {
}
const keys = nativeDeclaredCredentialKeys(kind, captured)
const env = nativeConfigEnvironment(kind, workspace?.state.agentPreferences, captured.env)
result[kind] = nativeEnvironmentIdentity({
const environmentIdentity = nativeEnvironmentIdentity({
...(env.PATH ? { PATH: env.PATH } : {}),
...networkEnvironment(env), ...configDirectoryEnvironment(env),
...nativeCredentialEnvironment(kind, env, keys),
})
const projectPaths = nativeProjectConfigPaths(kind, env)
if (projectPaths.length) {
const agent = { [NATIVE_PROJECT_CONFIG_PATHS]: projectPaths }
result[kind] = projectVerificationIdentity(kind, workdir, agent, environmentIdentity)
} else {
result[kind] = environmentIdentity
}
}
return result
}
@@ -908,6 +908,24 @@ test('native project identity changes when the CLI tool search path changes', as
assert.doesNotMatch(JSON.stringify([first, second]), /synthetic|tool-bin/)
})
test('native project identity follows relative credential files captured for the project', async t => {
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'meldwork-native-relative-identity-'))
t.after(() => fs.rmSync(directory, { recursive: true, force: true }))
const credentialFile = path.join(directory, 'credentials.json')
fs.writeFileSync(credentialFile, 'first synthetic credential')
const { harness } = loadMain(directory, {
nativeShellEnvironment: () => ({ source: 'native-shell', env: { GOOGLE_APPLICATION_CREDENTIALS: 'credentials.json' } }),
})
await harness.ready()
const resolve = harness.workspaceInstances[0].input.resolveProjectEnvironmentIdentities
const first = await resolve(directory, ['hermes'])
fs.writeFileSync(credentialFile, 'replacement synthetic credential')
const second = await resolve(directory, ['hermes'])
assert.match(first.hermes, /^[a-f0-9]{64}$/)
assert.notEqual(first.hermes, second.hermes)
assert.doesNotMatch(JSON.stringify([first, second]), /credentials|synthetic/)
})
test('Codex and Hermes project identities track only their own native credentials', async t => {
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'meldwork-native-project-identities-'))
t.after(() => fs.rmSync(directory, { recursive: true, force: true }))