revert: TableVirtualKey.Value from SecretVar back to string, dropping env/vault reference support - #4665
Conversation
|
Warning Review limit reached
More reviews will be available in 29 minutes and 33 seconds. Learn how PR review limits work. To continue reviewing without waiting, enable usage-based billing in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (26)
📝 WalkthroughWalkthrough
ChangesSecretVar Removal from VirtualKey.Value
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
TableVirtualKey.Value from SecretVar back to string, dropping env/vault reference support
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@transports/bifrost-http/handlers/governance.go`:
- Around line 145-147: The CreateVirtualKeyRequest path is still accepting
legacy "value" input silently, so update the governance handler to reject
requests containing that field instead of proceeding with generated keys; locate
the request decoding and virtual key creation flow in CreateVirtualKeyRequest
and the associated handler, and either switch to strict JSON decoding with
disallowed unknown fields or explicitly detect a provided value and return a 400
before key generation.
In `@transports/bifrost-http/lib/config.go`:
- Around line 2251-2270: Recompute the virtual key hash only after the value
normalization in configData.Governance.VirtualKeys, because fileVKHash is
currently derived before env resolution and fallback key generation, so
ConfigHash can end up reflecting env.FOO or a placeholder instead of the stored
effective value. Update the flow around the virtual key processing in the
existing loop (including the GenerateVirtualKeyHash and ConfigHash assignment
logic) so Value is first resolved via envutils.ProcessEnvValue or generated with
governance.GenerateVirtualKey, then the hash is regenerated from the final Value
before persisting or comparing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 36d8174d-8eeb-4014-88a6-99f85bd6adc9
📒 Files selected for processing (26)
framework/configstore/clientconfig.goframework/configstore/encryption_test.goframework/configstore/migrations_test.goframework/configstore/rdb_deadlock_postgres_test.goframework/configstore/rdb_mcp_sessions_test.goframework/configstore/rdb_test.goframework/configstore/tables/encryption_test.goframework/configstore/tables/virtualkey.goframework/configstore/tables/virtualkey_secretvar_test.goframework/logstore/asyncjob_test.goplugins/governance/store.goplugins/governance/store_test.goplugins/governance/test_utils.gotransports/bifrost-http/handlers/governance.gotransports/bifrost-http/handlers/governance_test.gotransports/bifrost-http/handlers/list_models_vk_test.gotransports/bifrost-http/handlers/mcpserver.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/server.goui/app/workspace/mcp-registry/views/mcpUsageGuide/commandBuilders.tsui/app/workspace/mcp-registry/views/mcpUsageGuide/mcpUsageGuideSheet.tsxui/app/workspace/virtual-keys/views/virtualKeysTable.tsxui/components/prompts/components/apiKeySelectorView.tsxui/components/prompts/fragments/settingsPanel.tsxui/lib/types/governance.ts
💤 Files with no reviewable changes (1)
- framework/configstore/tables/virtualkey_secretvar_test.go
TableVirtualKey.Value from SecretVar back to string, dropping env/vault reference supportTableVirtualKey.Value from SecretVar back to string, dropping env/vault reference support
Confidence Score: 4/5Safe to merge with awareness of one behavioral change: env-var-sourced VK values are resolved once at first sync and do not update if the env var is later rotated, unless another VK field changes concurrently. The config hash used for change-detection is computed from the raw config-file entry ( transports/bifrost-http/lib/config.go — the env var hash/resolution ordering; transports/bifrost-http/lib/config_test.go — no test exercises the new env.X resolution path for virtual keys Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant CF as Config File
participant MG as mergeGovernanceConfig
participant EU as envutils.ProcessEnvValue
participant DB as Database (GORM)
participant IM as In-Memory Store
CF->>MG: "VirtualKey{value: "env.MY_VK"}"
MG->>MG: "GenerateVirtualKeyHash(rawEntry)<br/>(hashes "env.MY_VK" literal)"
alt value starts with "env."
MG->>EU: ProcessEnvValue("env.MY_VK")
EU-->>MG: "sk-bf-resolved-value"
MG->>MG: "Value = "sk-bf-resolved-value""
end
MG->>MG: Validate VirtualKeyPrefix
MG->>DB: "CreateVirtualKey / UpdateVirtualKey<br/>(BeforeSave: HashSHA256 + encryptString)"
DB-->>MG: "stored with EncryptionStatus=encrypted"
MG->>IM: "Store(vk.Value, &vk)"
note over MG,DB: On next sync: fileVKHash == storedHash<br/>(both hash "env.MY_VK" literal)<br/>update skipped, DB value stays stale<br/>if env var changes
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant CF as Config File
participant MG as mergeGovernanceConfig
participant EU as envutils.ProcessEnvValue
participant DB as Database (GORM)
participant IM as In-Memory Store
CF->>MG: "VirtualKey{value: "env.MY_VK"}"
MG->>MG: "GenerateVirtualKeyHash(rawEntry)<br/>(hashes "env.MY_VK" literal)"
alt value starts with "env."
MG->>EU: ProcessEnvValue("env.MY_VK")
EU-->>MG: "sk-bf-resolved-value"
MG->>MG: "Value = "sk-bf-resolved-value""
end
MG->>MG: Validate VirtualKeyPrefix
MG->>DB: "CreateVirtualKey / UpdateVirtualKey<br/>(BeforeSave: HashSHA256 + encryptString)"
DB-->>MG: "stored with EncryptionStatus=encrypted"
MG->>IM: "Store(vk.Value, &vk)"
note over MG,DB: On next sync: fileVKHash == storedHash<br/>(both hash "env.MY_VK" literal)<br/>update skipped, DB value stays stale<br/>if env var changes
|
d536943 to
5284d5e
Compare
5284d5e to
d536943
Compare
Merge activity
|
…opping env/vault reference support (maximhq#4665) ## Summary `TableVirtualKey.Value` was previously typed as `schemas.SecretVar` to support `env.X` and `vault.X` references that resolve at read time. This abstraction added complexity throughout the codebase without sufficient benefit for virtual keys specifically. This PR simplifies `TableVirtualKey.Value` to a plain `string`, with `env.X` references now resolved explicitly at the config-merge layer before being stored. ## Changes - `TableVirtualKey.Value` field changed from `schemas.SecretVar` to `string` across the Go backend and TypeScript frontend - `BeforeSave` and `AfterFind` GORM hooks updated to use `encryptString`/`decryptString` instead of `encryptSecretVar`/`decryptSecretVar` - Vault self-managed interface methods (`VaultPathKey`, `VaultStoreSelfManaged`) removed from `TableVirtualKey` since vault-sourced virtual key values are no longer supported - `env.X` references in config file virtual key values are now resolved explicitly via `envutils.ProcessEnvValue` during `mergeGovernanceConfig`, replacing the implicit resolution that `SecretVar` provided - `GenerateVirtualKeyHash` updated to hash `vk.Value` directly instead of calling `vk.Value.GetValue()` - `CreateVirtualKeyRequest` in the HTTP handler no longer accepts a caller-supplied `value` field; the value is always generated server-side - All in-memory governance store operations (`rebuildInMemoryStructures`, `CreateVirtualKeyInMemory`, `UpdateVirtualKeyInMemory`) updated to key on `vk.Value` directly - UI `VirtualKey` type updated so `value` is `string` instead of `string | SecretVar`; the `resolveVirtualKeyValue` helper function removed from all call sites and deleted - `virtualkey_secretvar_test.go` deleted as the `SecretVar`-specific behavior it tested no longer applies ## Type of change - [ ] Bug fix - [ ] Feature - [x] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh go test ./framework/configstore/... go test ./framework/configstore/tables/... go test ./plugins/governance/... go test ./transports/bifrost-http/... cd ui pnpm i pnpm build ``` Verify that virtual keys created via the API or config file are stored, encrypted, and retrieved correctly. Confirm that `env.X` values in config files are resolved to their plaintext equivalents before being persisted. ## Breaking changes - [x] Yes - [ ] No The `CreateVirtualKeyRequest` no longer accepts a `value` field. Callers that previously supplied a custom literal or `env.X` value via the API must now set the value through the config file or accept the server-generated value. Config file `env.X` references for virtual key values continue to work but are resolved at sync time rather than stored as references. ## Security considerations Virtual key values are still encrypted at rest using the existing `encryptString`/`decryptString` path and hashed via SHA-256 for lookup. Removing the `SecretVar` indirection eliminates a code path where a vault reference could be stored in the value column and resolved on every read, reducing the surface area for secret leakage through unresolved references. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
…opping env/vault reference support (maximhq#4665) ## Summary `TableVirtualKey.Value` was previously typed as `schemas.SecretVar` to support `env.X` and `vault.X` references that resolve at read time. This abstraction added complexity throughout the codebase without sufficient benefit for virtual keys specifically. This PR simplifies `TableVirtualKey.Value` to a plain `string`, with `env.X` references now resolved explicitly at the config-merge layer before being stored. ## Changes - `TableVirtualKey.Value` field changed from `schemas.SecretVar` to `string` across the Go backend and TypeScript frontend - `BeforeSave` and `AfterFind` GORM hooks updated to use `encryptString`/`decryptString` instead of `encryptSecretVar`/`decryptSecretVar` - Vault self-managed interface methods (`VaultPathKey`, `VaultStoreSelfManaged`) removed from `TableVirtualKey` since vault-sourced virtual key values are no longer supported - `env.X` references in config file virtual key values are now resolved explicitly via `envutils.ProcessEnvValue` during `mergeGovernanceConfig`, replacing the implicit resolution that `SecretVar` provided - `GenerateVirtualKeyHash` updated to hash `vk.Value` directly instead of calling `vk.Value.GetValue()` - `CreateVirtualKeyRequest` in the HTTP handler no longer accepts a caller-supplied `value` field; the value is always generated server-side - All in-memory governance store operations (`rebuildInMemoryStructures`, `CreateVirtualKeyInMemory`, `UpdateVirtualKeyInMemory`) updated to key on `vk.Value` directly - UI `VirtualKey` type updated so `value` is `string` instead of `string | SecretVar`; the `resolveVirtualKeyValue` helper function removed from all call sites and deleted - `virtualkey_secretvar_test.go` deleted as the `SecretVar`-specific behavior it tested no longer applies ## Type of change - [ ] Bug fix - [ ] Feature - [x] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh go test ./framework/configstore/... go test ./framework/configstore/tables/... go test ./plugins/governance/... go test ./transports/bifrost-http/... cd ui pnpm i pnpm build ``` Verify that virtual keys created via the API or config file are stored, encrypted, and retrieved correctly. Confirm that `env.X` values in config files are resolved to their plaintext equivalents before being persisted. ## Breaking changes - [x] Yes - [ ] No The `CreateVirtualKeyRequest` no longer accepts a `value` field. Callers that previously supplied a custom literal or `env.X` value via the API must now set the value through the config file or accept the server-generated value. Config file `env.X` references for virtual key values continue to work but are resolved at sync time rather than stored as references. ## Security considerations Virtual key values are still encrypted at rest using the existing `encryptString`/`decryptString` path and hashed via SHA-256 for lookup. Removing the `SecretVar` indirection eliminates a code path where a vault reference could be stored in the value column and resolved on every read, reducing the surface area for secret leakage through unresolved references. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable

Summary
TableVirtualKey.Valuewas previously typed asschemas.SecretVarto supportenv.Xandvault.Xreferences that resolve at read time. This abstraction added complexity throughout the codebase without sufficient benefit for virtual keys specifically. This PR simplifiesTableVirtualKey.Valueto a plainstring, withenv.Xreferences now resolved explicitly at the config-merge layer before being stored.Changes
TableVirtualKey.Valuefield changed fromschemas.SecretVartostringacross the Go backend and TypeScript frontendBeforeSaveandAfterFindGORM hooks updated to useencryptString/decryptStringinstead ofencryptSecretVar/decryptSecretVarVaultPathKey,VaultStoreSelfManaged) removed fromTableVirtualKeysince vault-sourced virtual key values are no longer supportedenv.Xreferences in config file virtual key values are now resolved explicitly viaenvutils.ProcessEnvValueduringmergeGovernanceConfig, replacing the implicit resolution thatSecretVarprovidedGenerateVirtualKeyHashupdated to hashvk.Valuedirectly instead of callingvk.Value.GetValue()CreateVirtualKeyRequestin the HTTP handler no longer accepts a caller-suppliedvaluefield; the value is always generated server-siderebuildInMemoryStructures,CreateVirtualKeyInMemory,UpdateVirtualKeyInMemory) updated to key onvk.ValuedirectlyVirtualKeytype updated sovalueisstringinstead ofstring | SecretVar; theresolveVirtualKeyValuehelper function removed from all call sites and deletedvirtualkey_secretvar_test.godeleted as theSecretVar-specific behavior it tested no longer appliesType of change
Affected areas
How to test
Verify that virtual keys created via the API or config file are stored, encrypted, and retrieved correctly. Confirm that
env.Xvalues in config files are resolved to their plaintext equivalents before being persisted.Breaking changes
The
CreateVirtualKeyRequestno longer accepts avaluefield. Callers that previously supplied a custom literal orenv.Xvalue via the API must now set the value through the config file or accept the server-generated value. Config fileenv.Xreferences for virtual key values continue to work but are resolved at sync time rather than stored as references.Security considerations
Virtual key values are still encrypted at rest using the existing
encryptString/decryptStringpath and hashed via SHA-256 for lookup. Removing theSecretVarindirection eliminates a code path where a vault reference could be stored in the value column and resolved on every read, reducing the surface area for secret leakage through unresolved references.Checklist
docs/contributing/README.mdand followed the guidelines