Skip to content

Seal stored secrets in the adapter that stores them - #327

Merged
SaladDay merged 2 commits into
mainfrom
refactor/adapter-sealing
Sep 30, 2026
Merged

SaladDay merged 2 commits into
mainfrom
refactor/adapter-sealing

Conversation

@SaladDay

@SaladDay SaladDay commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #1 (store layering). The adapter that stores a secret now seals and opens it.

Encryption was split two ways. templatepg, skillpg and agentpg sealed inside the adapter; vaults and modelconfiguration sealed in the domain Service. The wave-3 Session PRs will freeze and open configuration in sessionpg under the same rule, so the two outliers change first.

  • vaults / vaultpg:
    • vaults.NewService(storage, refresher) no longer takes the key; vaultpg.New(units, cipher) does.
    • Storage inputs and results carry plaintext: NewCredential.Token/OAuth, StaticToken, OAuthTx.LoadOAuthGrant/ApplyOAuthRefresh/ApplyOAuthReplacement.
    • The binding, the OAuth payload encoding and the metadata authentication moved to vaultpg/seal.go. The pure OAuth rules stay in vaults.
    • The OAuth refresh still holds the row lock across the external call, bounded by oauthRefreshTimeout.
  • modelconfiguration / modelconfigurationpg:
    • modelconfiguration.NewService(storage); modelconfigurationpg.New(units, cipher).
    • LoadSealed became LoadBundle, which returns the opened bundle and its revision.
  • agentpg: a bundle that fails to open or decode is an internal error, not credentialcrypto.ErrUnavailable.
  • IMPLEMENTATION.md: one sentence stating the encryption rule, and updated owner notes.

Ciphertext format and bindings are unchanged. New adapter tests seal the way the old code path did and check that the result still opens.

Behaviour changes:

  • A missing key is still 503 credential_storage_unavailable.
  • A deployment model bundle or Agent model bundle that fails to open or decode is now 500 instead of 503. A decryption failure no longer looks like a missing key.

Checks on the head (0a517bb + 2):

  • go build ./... and go vet ./services/core/... across the whole module
  • In full: vaults, vaultpg, modelconfiguration, modelconfigurationpg, agentpg
  • api, cmd/server, execution and store: the dependency, route, observer, fixture-user and MCP credential tests, by -run
  • scripts/check-names.py

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@SaladDay
SaladDay merged commit f7af413 into main Sep 30, 2026
1 check passed
@SaladDay
SaladDay deleted the refactor/adapter-sealing branch September 30, 2026 18:26
vaultpg and modelconfigurationpg now take the credential key and seal and
open the secrets they store; vaults and modelconfiguration services no
longer take a cipher and their storage interfaces carry plaintext.
Ciphertext format and bindings are unchanged, so existing rows still open.
A bundle that fails to open is now an internal error instead of a
missing credential key.
agentpg returned credentialcrypto.ErrUnavailable when a saved Agent's
bundle failed to open or decode, so a wrong key or binding looked like a
missing key. A missing key stays ErrUnavailable; a failed open or decode
is now an internal error.
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.

1 participant