返回 DeepSeek-Reasonix
credentials_keyring_helper.go
根目录 / internal / config / credentials_keyring_helper.go
1 package config
2
3 import (
4 "context"
5 "strings"
6 "time"
7 )
8
9 // legacyKeyringStatus classifies one keyring probe outcome for migration.
10 // Only absent may write a migration-done marker.
11 type legacyKeyringStatus string
12
13 const (
14 legacyKeyringFound legacyKeyringStatus = "found"
15 legacyKeyringAbsent legacyKeyringStatus = "absent"
16 legacyKeyringError legacyKeyringStatus = "error"
17 legacyKeyringTimeout legacyKeyringStatus = "timeout"
18 )
19
20 // legacyKeyringOutcome is the four-state result for one env key.
21 // Value is populated only for found probes inside this process and is scrubbed
22 // before the outcome is returned to migration callers after store-if-absent.
23 type legacyKeyringOutcome struct {
24 Status legacyKeyringStatus
25 Value string
26 }
27
28 // lookupLegacyKeyringBatch probes keys under a single shared deadline in-process.
29 // There is no external helper entrypoint: secrets never leave the process via
30 // stdout or a caller-controlled REASONIX_HOME dump path.
31 func lookupLegacyKeyringBatch(keys []string, budget time.Duration) map[string]legacyKeyringOutcome {
32 out := make(map[string]legacyKeyringOutcome, len(keys))
33 if len(keys) == 0 {
34 return out
35 }
36 if budget <= 0 {
37 budget = time.Second
38 }
39 ctx, cancel := context.WithTimeout(context.Background(), budget)
40 defer cancel()
41
42 for _, key := range keys {
43 if err := ctx.Err(); err != nil {
44 out[key] = legacyKeyringOutcome{Status: legacyKeyringTimeout}
45 continue
46 }
47 o := legacyKeyringProbeLookup(ctx, key)
48 switch o.Status {
49 case legacyKeyringFound:
50 if strings.TrimSpace(o.Value) == "" {
51 out[key] = legacyKeyringOutcome{Status: legacyKeyringAbsent}
52 continue
53 }
54 stored, err := storeCredentialIfAbsentAndNotCleared(key, o.Value)
55 o.Value = "" // scrub before returning
56 if err != nil {
57 out[key] = legacyKeyringOutcome{Status: legacyKeyringError}
58 continue
59 }
60 if !stored {
61 // Current store already has a value or tombstone; do not apply
62 // the legacy keyring secret. Report found so migration does not
63 // re-probe endlessly without writing an absent marker.
64 out[key] = legacyKeyringOutcome{Status: legacyKeyringFound}
65 continue
66 }
67 out[key] = legacyKeyringOutcome{Status: legacyKeyringFound}
68 case legacyKeyringAbsent, legacyKeyringError, legacyKeyringTimeout:
69 out[key] = legacyKeyringOutcome{Status: o.Status}
70 default:
71 out[key] = legacyKeyringOutcome{Status: legacyKeyringTimeout}
72 }
73 }
74 return out
75 }
76
76 lines GO