diff --git a/secretstore/manifest_open.go b/secretstore/manifest_open.go index f8009d4..4b0051b 100644 --- a/secretstore/manifest_open.go +++ b/secretstore/manifest_open.go @@ -15,15 +15,16 @@ type ManifestLoader func(startDir string) (manifest.File, string, error) type ExecutableResolver func() (string, error) type OpenFromManifestOptions struct { - ServiceName string - LookupEnv func(string) (string, bool) - KWalletAppID string - KWalletFolder string - BitwardenCommand string - BitwardenDebug bool - Shell string - ManifestLoader ManifestLoader - ExecutableResolver ExecutableResolver + ServiceName string + LookupEnv func(string) (string, bool) + KWalletAppID string + KWalletFolder string + BitwardenCommand string + BitwardenDebug bool + DisableBitwardenCache bool + Shell string + ManifestLoader ManifestLoader + ExecutableResolver ExecutableResolver } func OpenFromManifest(options OpenFromManifestOptions) (Store, error) { @@ -33,14 +34,15 @@ func OpenFromManifest(options OpenFromManifestOptions) (Store, error) { } return Open(Options{ - ServiceName: options.ServiceName, - BackendPolicy: manifestPolicy.Policy, - LookupEnv: options.LookupEnv, - KWalletAppID: options.KWalletAppID, - KWalletFolder: options.KWalletFolder, - BitwardenCommand: strings.TrimSpace(options.BitwardenCommand), - BitwardenDebug: options.BitwardenDebug, - Shell: strings.TrimSpace(options.Shell), + ServiceName: options.ServiceName, + BackendPolicy: manifestPolicy.Policy, + LookupEnv: options.LookupEnv, + KWalletAppID: options.KWalletAppID, + KWalletFolder: options.KWalletFolder, + BitwardenCommand: strings.TrimSpace(options.BitwardenCommand), + BitwardenDebug: options.BitwardenDebug, + DisableBitwardenCache: disableBitwardenCacheOption(options.DisableBitwardenCache, manifestPolicy.BitwardenCache), + Shell: strings.TrimSpace(options.Shell), }) } @@ -53,8 +55,9 @@ func resolveManifestBackendPolicy(options OpenFromManifestOptions) (BackendPolic } type manifestPolicyResolution struct { - Policy BackendPolicy - Source string + Policy BackendPolicy + Source string + BitwardenCache bool } func resolveManifestPolicy(options OpenFromManifestOptions) (manifestPolicyResolution, error) { @@ -82,17 +85,24 @@ func resolveManifestPolicy(options OpenFromManifestOptions) (manifestPolicyResol if err != nil { if errors.Is(err, os.ErrNotExist) { return manifestPolicyResolution{ - Policy: BackendAuto, - Source: "", + Policy: BackendAuto, + Source: "", + BitwardenCache: true, }, nil } return manifestPolicyResolution{}, fmt.Errorf("load runtime manifest from %q: %w", startDir, err) } + bitwardenCache := true + if file.SecretStore.BitwardenCache != nil { + bitwardenCache = *file.SecretStore.BitwardenCache + } + if strings.TrimSpace(file.SecretStore.BackendPolicy) == "" { return manifestPolicyResolution{ - Policy: BackendAuto, - Source: strings.TrimSpace(manifestPath), + Policy: BackendAuto, + Source: strings.TrimSpace(manifestPath), + BitwardenCache: bitwardenCache, }, nil } @@ -106,7 +116,12 @@ func resolveManifestPolicy(options OpenFromManifestOptions) (manifestPolicyResol } return manifestPolicyResolution{ - Policy: policy, - Source: strings.TrimSpace(manifestPath), + Policy: policy, + Source: strings.TrimSpace(manifestPath), + BitwardenCache: bitwardenCache, }, nil } + +func disableBitwardenCacheOption(runtimeDisabled bool, manifestEnabled bool) bool { + return runtimeDisabled || !manifestEnabled +} diff --git a/secretstore/manifest_open_test.go b/secretstore/manifest_open_test.go index bfe783a..0a92d37 100644 --- a/secretstore/manifest_open_test.go +++ b/secretstore/manifest_open_test.go @@ -111,6 +111,33 @@ func TestOpenFromManifestReturnsExplicitErrorForInvalidManifestPolicy(t *testing } } +func TestResolveManifestPolicyPreservesBitwardenCacheDisable(t *testing.T) { + cacheDisabled := false + resolution, err := resolveManifestPolicy(OpenFromManifestOptions{ + ServiceName: "email-mcp", + ExecutableResolver: func() (string, error) { + return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil + }, + ManifestLoader: func(startDir string) (manifest.File, string, error) { + return manifest.File{ + SecretStore: manifest.SecretStore{ + BackendPolicy: string(BackendBitwardenCLI), + BitwardenCache: &cacheDisabled, + }, + }, filepath.Join(startDir, manifest.DefaultFile), nil + }, + }) + if err != nil { + t.Fatalf("resolveManifestPolicy returned error: %v", err) + } + if resolution.BitwardenCache { + t.Fatal("resolution BitwardenCache = true, want false") + } + if resolution.Policy != BackendBitwardenCLI { + t.Fatalf("resolution policy = %q, want %q", resolution.Policy, BackendBitwardenCLI) + } +} + func TestOpenFromManifestReturnsExecutableResolutionError(t *testing.T) { execErr := errors.New("boom") _, err := OpenFromManifest(OpenFromManifestOptions{ diff --git a/secretstore/runtime.go b/secretstore/runtime.go index 4d342d7..f0894a9 100644 --- a/secretstore/runtime.go +++ b/secretstore/runtime.go @@ -9,15 +9,16 @@ import ( const DefaultManifestSource = "default:auto (manifest not found)" type DescribeRuntimeOptions struct { - ServiceName string - LookupEnv func(string) (string, bool) - KWalletAppID string - KWalletFolder string - BitwardenCommand string - BitwardenDebug bool - Shell string - ManifestLoader ManifestLoader - ExecutableResolver ExecutableResolver + ServiceName string + LookupEnv func(string) (string, bool) + KWalletAppID string + KWalletFolder string + BitwardenCommand string + BitwardenDebug bool + DisableBitwardenCache bool + Shell string + ManifestLoader ManifestLoader + ExecutableResolver ExecutableResolver } type RuntimeDescription struct { @@ -47,14 +48,15 @@ type PreflightReport struct { func DescribeRuntime(options DescribeRuntimeOptions) (RuntimeDescription, error) { resolution, err := resolveManifestPolicy(OpenFromManifestOptions{ - ServiceName: options.ServiceName, - LookupEnv: options.LookupEnv, - KWalletAppID: options.KWalletAppID, - KWalletFolder: options.KWalletFolder, - BitwardenCommand: options.BitwardenCommand, - Shell: options.Shell, - ManifestLoader: options.ManifestLoader, - ExecutableResolver: options.ExecutableResolver, + ServiceName: options.ServiceName, + LookupEnv: options.LookupEnv, + KWalletAppID: options.KWalletAppID, + KWalletFolder: options.KWalletFolder, + BitwardenCommand: options.BitwardenCommand, + DisableBitwardenCache: options.DisableBitwardenCache, + Shell: options.Shell, + ManifestLoader: options.ManifestLoader, + ExecutableResolver: options.ExecutableResolver, }) if err != nil { return RuntimeDescription{}, err @@ -68,14 +70,15 @@ func DescribeRuntime(options DescribeRuntimeOptions) (RuntimeDescription, error) } store, openErr := Open(Options{ - ServiceName: options.ServiceName, - BackendPolicy: resolution.Policy, - LookupEnv: options.LookupEnv, - KWalletAppID: options.KWalletAppID, - KWalletFolder: options.KWalletFolder, - BitwardenCommand: options.BitwardenCommand, - BitwardenDebug: options.BitwardenDebug, - Shell: options.Shell, + ServiceName: options.ServiceName, + BackendPolicy: resolution.Policy, + LookupEnv: options.LookupEnv, + KWalletAppID: options.KWalletAppID, + KWalletFolder: options.KWalletFolder, + BitwardenCommand: options.BitwardenCommand, + BitwardenDebug: options.BitwardenDebug, + DisableBitwardenCache: disableBitwardenCacheOption(options.DisableBitwardenCache, resolution.BitwardenCache), + Shell: options.Shell, }) if openErr != nil { desc.Ready = false diff --git a/secretstore/store.go b/secretstore/store.go index 5d8d2a9..d88d3d2 100644 --- a/secretstore/store.go +++ b/secretstore/store.go @@ -31,14 +31,15 @@ const ( ) type Options struct { - ServiceName string - BackendPolicy BackendPolicy - LookupEnv func(string) (string, bool) - KWalletAppID string - KWalletFolder string - BitwardenCommand string - BitwardenDebug bool - Shell string + ServiceName string + BackendPolicy BackendPolicy + LookupEnv func(string) (string, bool) + KWalletAppID string + KWalletFolder string + BitwardenCommand string + BitwardenDebug bool + DisableBitwardenCache bool + Shell string } type Store interface {