Skip to content

fix(keys): KeysExist must respect WithKeyParts#2

Merged
couragehong merged 1 commit into
mainfrom
couragehong/fix/keys-exist-respects-parts
May 7, 2026
Merged

fix(keys): KeysExist must respect WithKeyParts#2
couragehong merged 1 commit into
mainfrom
couragehong/fix/keys-exist-respects-parts

Conversation

@couragehong

@couragehong couragehong commented May 7, 2026

Copy link
Copy Markdown
Contributor

다음 상황에서 발견되었습니다.

  1. rune-mcp boot loop 가 Vault.GetAgentManifest 호출
  2. Vault 가 manifest 응답 → 그 안에 EncKey 만 포함 (Eval/Sec 는 vault 가 보관)
  3. rune-mcp 가 EncKey 를 ~/.rune/keys//EncKey.json 에 저장
  4. rune의 envector adapter 가 envector.OpenKeysFromFile(..., WithKeyParts(KeyPartEnc))
  5. OpenKeysFromFile 의 첫 라인:
    if !KeysExist(opts...) { return ErrKeysNotFound }

수정 전 KeysExistEncKey + EvalKey + SecKey 모두 검사
→ EvalKey/SecKey 는 vault 가 보관 → 사용자의 dir 에는 없음
→ false → ErrKeysNotFound
→ boot loop bootRetry → 영원히 retry
→ state Active 도달 못 함

수정 후 KeysExistWithKeyParts(KeyPartEnc) 따라 EncKey 만 검사
→ 우리 dir 에 EncKey.json 있음 → true
→ OpenKeysFromFile 진행 → 정상 완료

Background
----------
Vault delivers only the Encryption-side material (EncKey) to clients via
the agent manifest — Eval/Sec stay inside Vault for FHE evaluation and
re-encryption. A consumer reading that bundle calls

    OpenKeysFromFile(WithKeyPath(...), ..., WithKeyParts(KeyPartEnc))

OpenKeysFromFile begins with a `KeysExist(opts...)` gate; if it returns
false, the open fails fast with ErrKeysNotFound.

Bug
---
KeysExist walked all three slots (Enc / Eval / Sec) unconditionally,
ignoring the caller's WithKeyParts. So the Vault-delivered Enc-only
bundle was rejected even when the caller had explicitly said "I only
need Enc".

Reproducer (the path the rune-mcp boot loop hit on first GetAgentManifest):

    dir := t.TempDir()
    os.WriteFile(filepath.Join(dir, "EncKey.json"), []byte("{}"), 0o600)

    KeysExist(
        WithKeyPath(dir),
        WithKeyID("k"), WithKeyDim(1024),
        WithKeyParts(KeyPartEnc),
    )
    // pre-fix: false  → bundle rejected
    // fixed:    true  → bundle accepted

Fix
---
KeysExist now resolves the requested KeyParts via the same helper
OpenKeysFromFile uses (resolveKeyParts) and only checks the slots the
caller actually requested. Default behavior (no WithKeyParts) is
preserved: resolveKeyParts returns enc=true,eval=true,sec=true, so a
bare KeysExist(WithKeyPath(...)) still requires all three.

Tests
-----
TestKeysExist_PartsAware covers:
  - enc-only dir + WithKeyParts(KeyPartEnc)  → true   (Vault use case)
  - enc-only dir + default parts             → false  (backward compat)
  - enc-only dir + WithKeyParts(KeyPartEval) → false  (other parts still missing)

Existing TestKeysExist_FalseWhenEmpty / TestGenerateKeys_CreatesAllThreeFiles
keep their prior expectations — both are exercised through the same
resolveKeyParts code path now.

Discovered while wiring rune-mcp v0.4 (Go port) against Vault's
GetAgentManifest flow; the boot loop's envector adapter opens keys with
KeyPartEnc only and was bouncing on this gate every retry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@couragehong couragehong self-assigned this May 7, 2026

@jh-lee-cryptolab jh-lee-cryptolab left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@couragehong couragehong merged commit e336b72 into main May 7, 2026
5 checks passed
@jh-lee-cryptolab jh-lee-cryptolab deleted the couragehong/fix/keys-exist-respects-parts branch May 19, 2026 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants