@enactprotocol/secrets 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/package.json +30 -0
- package/src/dagger/index.ts +19 -0
- package/src/dagger/secret-object.ts +126 -0
- package/src/dagger/uri-parser.ts +202 -0
- package/src/env/index.ts +54 -0
- package/src/env/manager.ts +251 -0
- package/src/env/parser.ts +240 -0
- package/src/env/reader.ts +105 -0
- package/src/env/writer.ts +118 -0
- package/src/index.ts +120 -0
- package/src/keyring.ts +136 -0
- package/src/resolver.ts +184 -0
- package/src/types.ts +194 -0
- package/tests/dagger/secret-object.test.ts +217 -0
- package/tests/dagger/uri-parser.test.ts +194 -0
- package/tests/env/manager.test.ts +220 -0
- package/tests/env/parser.test.ts +352 -0
- package/tests/env/reader-writer.test.ts +257 -0
- package/tests/fixtures/complex.env +26 -0
- package/tests/fixtures/empty.env +0 -0
- package/tests/fixtures/simple.env +4 -0
- package/tests/keyring.test.ts +250 -0
- package/tests/mocks/keyring.ts +164 -0
- package/tests/resolver.test.ts +287 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @enactprotocol/secrets
|
|
3
|
+
*
|
|
4
|
+
* OS keyring integration and environment variable management for Enact.
|
|
5
|
+
* Provides secure secret storage using platform-native keychains.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const version = "0.1.0";
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Types
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
SecretResolution,
|
|
16
|
+
SecretNotFound,
|
|
17
|
+
SecretResolutionResult,
|
|
18
|
+
SecretMetadata,
|
|
19
|
+
SecretTrace,
|
|
20
|
+
SecretTraceEntry,
|
|
21
|
+
EnvScope,
|
|
22
|
+
EnvFileLocation,
|
|
23
|
+
EnvironmentVariable,
|
|
24
|
+
EnvResolution,
|
|
25
|
+
ParsedEnvFile,
|
|
26
|
+
EnvFileLine,
|
|
27
|
+
DaggerSecretScheme,
|
|
28
|
+
DaggerSecretUri,
|
|
29
|
+
GetSecretOptions,
|
|
30
|
+
SecretObject,
|
|
31
|
+
} from "./types";
|
|
32
|
+
|
|
33
|
+
export { KEYRING_SERVICE } from "./types";
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Keyring Functions
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
buildAccount,
|
|
41
|
+
parseAccount,
|
|
42
|
+
setSecret,
|
|
43
|
+
getSecret,
|
|
44
|
+
deleteSecret,
|
|
45
|
+
listSecrets,
|
|
46
|
+
listAllSecrets,
|
|
47
|
+
secretExists,
|
|
48
|
+
isKeyringAvailable,
|
|
49
|
+
} from "./keyring";
|
|
50
|
+
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Secret Resolution
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
getNamespaceChain,
|
|
57
|
+
resolveSecret,
|
|
58
|
+
traceSecretResolution,
|
|
59
|
+
resolveSecrets,
|
|
60
|
+
checkRequiredSecrets,
|
|
61
|
+
} from "./resolver";
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Environment Variables
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
// Parser
|
|
69
|
+
parseEnvFile,
|
|
70
|
+
parseEnvContent,
|
|
71
|
+
serializeEnvFile,
|
|
72
|
+
createEnvContent,
|
|
73
|
+
updateEnvVar,
|
|
74
|
+
removeEnvVar,
|
|
75
|
+
// Reader
|
|
76
|
+
getGlobalEnvPath,
|
|
77
|
+
getLocalEnvPath,
|
|
78
|
+
readEnvFile,
|
|
79
|
+
readEnvVars,
|
|
80
|
+
loadGlobalEnv,
|
|
81
|
+
loadLocalEnv,
|
|
82
|
+
loadGlobalEnvFile,
|
|
83
|
+
loadLocalEnvFile,
|
|
84
|
+
globalEnvExists,
|
|
85
|
+
localEnvExists,
|
|
86
|
+
// Writer
|
|
87
|
+
writeEnvFile,
|
|
88
|
+
writeEnvVars,
|
|
89
|
+
setEnvVar,
|
|
90
|
+
deleteEnvVar,
|
|
91
|
+
setGlobalEnvVar,
|
|
92
|
+
setLocalEnvVar,
|
|
93
|
+
deleteGlobalEnvVar,
|
|
94
|
+
deleteLocalEnvVar,
|
|
95
|
+
// Manager (high-level API)
|
|
96
|
+
setEnv,
|
|
97
|
+
getEnv,
|
|
98
|
+
getEnvValue,
|
|
99
|
+
deleteEnv,
|
|
100
|
+
listEnv,
|
|
101
|
+
resolveAllEnv,
|
|
102
|
+
resolveToolEnv,
|
|
103
|
+
hasLocalEnv,
|
|
104
|
+
hasGlobalEnv,
|
|
105
|
+
} from "./env";
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Dagger Secret Integration
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
parseSecretUri,
|
|
113
|
+
resolveSecretUri,
|
|
114
|
+
isSecretUri,
|
|
115
|
+
getSupportedSchemes,
|
|
116
|
+
getSecretObject,
|
|
117
|
+
getSecretObjects,
|
|
118
|
+
parseSecretOverride,
|
|
119
|
+
parseSecretOverrides,
|
|
120
|
+
} from "./dagger";
|
package/src/keyring.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS Keyring integration for secure secret storage
|
|
3
|
+
*
|
|
4
|
+
* Uses the system keychain:
|
|
5
|
+
* - macOS: Keychain
|
|
6
|
+
* - Windows: Credential Manager
|
|
7
|
+
* - Linux: Secret Service (libsecret)
|
|
8
|
+
*
|
|
9
|
+
* All secrets are stored with:
|
|
10
|
+
* - Service: "enact-cli"
|
|
11
|
+
* - Account: "{namespace}:{SECRET_NAME}"
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { keyring } from "@zowe/secrets-for-zowe-sdk";
|
|
15
|
+
import { KEYRING_SERVICE, type SecretMetadata } from "./types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Build the account string for keyring storage
|
|
19
|
+
* Format: "namespace:SECRET_NAME"
|
|
20
|
+
*/
|
|
21
|
+
export function buildAccount(namespace: string, secretName: string): string {
|
|
22
|
+
return `${namespace}:${secretName}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parse an account string back to namespace and secret name
|
|
27
|
+
*/
|
|
28
|
+
export function parseAccount(account: string): {
|
|
29
|
+
namespace: string;
|
|
30
|
+
secretName: string;
|
|
31
|
+
} {
|
|
32
|
+
const colonIndex = account.lastIndexOf(":");
|
|
33
|
+
if (colonIndex === -1) {
|
|
34
|
+
throw new Error(`Invalid account format: ${account}`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
namespace: account.slice(0, colonIndex),
|
|
38
|
+
secretName: account.slice(colonIndex + 1),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Store a secret in the OS keyring
|
|
44
|
+
*
|
|
45
|
+
* @param namespace - The namespace for the secret (e.g., "alice/api")
|
|
46
|
+
* @param name - The secret name (e.g., "API_TOKEN")
|
|
47
|
+
* @param value - The secret value to store
|
|
48
|
+
*/
|
|
49
|
+
export async function setSecret(namespace: string, name: string, value: string): Promise<void> {
|
|
50
|
+
const account = buildAccount(namespace, name);
|
|
51
|
+
await keyring.setPassword(KEYRING_SERVICE, account, value);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Retrieve a secret from the OS keyring
|
|
56
|
+
*
|
|
57
|
+
* @param namespace - The namespace for the secret
|
|
58
|
+
* @param name - The secret name
|
|
59
|
+
* @returns The secret value, or null if not found
|
|
60
|
+
*/
|
|
61
|
+
export async function getSecret(namespace: string, name: string): Promise<string | null> {
|
|
62
|
+
const account = buildAccount(namespace, name);
|
|
63
|
+
const value = await keyring.getPassword(KEYRING_SERVICE, account);
|
|
64
|
+
return value ?? null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Delete a secret from the OS keyring
|
|
69
|
+
*
|
|
70
|
+
* @param namespace - The namespace for the secret
|
|
71
|
+
* @param name - The secret name
|
|
72
|
+
* @returns true if deleted, false if not found
|
|
73
|
+
*/
|
|
74
|
+
export async function deleteSecret(namespace: string, name: string): Promise<boolean> {
|
|
75
|
+
const account = buildAccount(namespace, name);
|
|
76
|
+
return await keyring.deletePassword(KEYRING_SERVICE, account);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* List all secrets for a namespace
|
|
81
|
+
*
|
|
82
|
+
* @param namespace - The namespace to list secrets for
|
|
83
|
+
* @returns Array of secret names in the namespace
|
|
84
|
+
*/
|
|
85
|
+
export async function listSecrets(namespace: string): Promise<string[]> {
|
|
86
|
+
const credentials = await keyring.findCredentials(KEYRING_SERVICE);
|
|
87
|
+
const prefix = `${namespace}:`;
|
|
88
|
+
|
|
89
|
+
return credentials
|
|
90
|
+
.filter((cred) => cred.account.startsWith(prefix))
|
|
91
|
+
.map((cred) => cred.account.slice(prefix.length));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* List all secrets across all namespaces
|
|
96
|
+
*
|
|
97
|
+
* @returns Array of secret metadata
|
|
98
|
+
*/
|
|
99
|
+
export async function listAllSecrets(): Promise<SecretMetadata[]> {
|
|
100
|
+
const credentials = await keyring.findCredentials(KEYRING_SERVICE);
|
|
101
|
+
|
|
102
|
+
return credentials.map((cred) => {
|
|
103
|
+
const { namespace, secretName } = parseAccount(cred.account);
|
|
104
|
+
return {
|
|
105
|
+
key: secretName,
|
|
106
|
+
namespace,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check if a secret exists in the keyring
|
|
113
|
+
*
|
|
114
|
+
* @param namespace - The namespace for the secret
|
|
115
|
+
* @param name - The secret name
|
|
116
|
+
* @returns true if the secret exists
|
|
117
|
+
*/
|
|
118
|
+
export async function secretExists(namespace: string, name: string): Promise<boolean> {
|
|
119
|
+
const value = await getSecret(namespace, name);
|
|
120
|
+
return value !== null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Check if the keyring is available on this system
|
|
125
|
+
*
|
|
126
|
+
* @returns true if keyring operations are available
|
|
127
|
+
*/
|
|
128
|
+
export async function isKeyringAvailable(): Promise<boolean> {
|
|
129
|
+
try {
|
|
130
|
+
// Try to list credentials - this will fail if keyring is not available
|
|
131
|
+
await keyring.findCredentials(KEYRING_SERVICE);
|
|
132
|
+
return true;
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/resolver.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret resolution with namespace inheritance
|
|
3
|
+
*
|
|
4
|
+
* When a tool requests a secret, we walk up the namespace path:
|
|
5
|
+
* Tool: alice/api/slack/notifier
|
|
6
|
+
* Needs: API_TOKEN
|
|
7
|
+
*
|
|
8
|
+
* Lookup:
|
|
9
|
+
* 1. alice/api/slack:API_TOKEN
|
|
10
|
+
* 2. alice/api:API_TOKEN ✓ found
|
|
11
|
+
* 3. alice:API_TOKEN
|
|
12
|
+
*
|
|
13
|
+
* First match wins.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { getSecret } from "./keyring";
|
|
17
|
+
import type {
|
|
18
|
+
SecretResolution,
|
|
19
|
+
SecretResolutionResult,
|
|
20
|
+
SecretTrace,
|
|
21
|
+
SecretTraceEntry,
|
|
22
|
+
} from "./types";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get the namespace chain for a tool path
|
|
26
|
+
* Walks up the path segments from most specific to least specific
|
|
27
|
+
*
|
|
28
|
+
* @param toolPath - The full tool path (e.g., "alice/api/slack")
|
|
29
|
+
* @returns Array of namespaces to check in order
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* getNamespaceChain("alice/api/slack")
|
|
33
|
+
* // Returns: ["alice/api/slack", "alice/api", "alice"]
|
|
34
|
+
*/
|
|
35
|
+
export function getNamespaceChain(toolPath: string): string[] {
|
|
36
|
+
const segments = toolPath.split("/").filter(Boolean);
|
|
37
|
+
const chain: string[] = [];
|
|
38
|
+
|
|
39
|
+
for (let i = segments.length; i > 0; i--) {
|
|
40
|
+
chain.push(segments.slice(0, i).join("/"));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return chain;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Resolve a secret using namespace inheritance
|
|
48
|
+
*
|
|
49
|
+
* @param toolPath - The tool path to resolve secrets for
|
|
50
|
+
* @param secretName - The secret name to find
|
|
51
|
+
* @returns Resolution result with namespace info, or not-found result
|
|
52
|
+
*/
|
|
53
|
+
export async function resolveSecret(
|
|
54
|
+
toolPath: string,
|
|
55
|
+
secretName: string
|
|
56
|
+
): Promise<SecretResolutionResult> {
|
|
57
|
+
const namespaces = getNamespaceChain(toolPath);
|
|
58
|
+
const searchedNamespaces: string[] = [];
|
|
59
|
+
|
|
60
|
+
for (const namespace of namespaces) {
|
|
61
|
+
searchedNamespaces.push(namespace);
|
|
62
|
+
const value = await getSecret(namespace, secretName);
|
|
63
|
+
|
|
64
|
+
if (value !== null) {
|
|
65
|
+
return {
|
|
66
|
+
namespace,
|
|
67
|
+
value,
|
|
68
|
+
key: secretName,
|
|
69
|
+
found: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
key: secretName,
|
|
76
|
+
found: false,
|
|
77
|
+
searchedNamespaces,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Trace secret resolution for debugging
|
|
83
|
+
* Shows which namespaces were checked and where the secret was found
|
|
84
|
+
*
|
|
85
|
+
* @param toolPath - The tool path to resolve secrets for
|
|
86
|
+
* @param secretName - The secret name to find
|
|
87
|
+
* @returns Full trace with all namespaces checked
|
|
88
|
+
*/
|
|
89
|
+
export async function traceSecretResolution(
|
|
90
|
+
toolPath: string,
|
|
91
|
+
secretName: string
|
|
92
|
+
): Promise<SecretTrace> {
|
|
93
|
+
const namespaces = getNamespaceChain(toolPath);
|
|
94
|
+
const entries: SecretTraceEntry[] = [];
|
|
95
|
+
let result: SecretResolutionResult | null = null;
|
|
96
|
+
|
|
97
|
+
for (const namespace of namespaces) {
|
|
98
|
+
const account = `${namespace}:${secretName}`;
|
|
99
|
+
const value = await getSecret(namespace, secretName);
|
|
100
|
+
const found = value !== null;
|
|
101
|
+
|
|
102
|
+
entries.push({ namespace, account, found });
|
|
103
|
+
|
|
104
|
+
if (found && !result) {
|
|
105
|
+
result = {
|
|
106
|
+
namespace,
|
|
107
|
+
value,
|
|
108
|
+
key: secretName,
|
|
109
|
+
found: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If not found anywhere
|
|
115
|
+
if (!result) {
|
|
116
|
+
result = {
|
|
117
|
+
key: secretName,
|
|
118
|
+
found: false,
|
|
119
|
+
searchedNamespaces: namespaces,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
key: secretName,
|
|
125
|
+
toolPath,
|
|
126
|
+
entries,
|
|
127
|
+
result,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Resolve multiple secrets for a tool
|
|
133
|
+
*
|
|
134
|
+
* @param toolPath - The tool path to resolve secrets for
|
|
135
|
+
* @param secretNames - Array of secret names to resolve
|
|
136
|
+
* @returns Map of secret name to resolution result
|
|
137
|
+
*/
|
|
138
|
+
export async function resolveSecrets(
|
|
139
|
+
toolPath: string,
|
|
140
|
+
secretNames: string[]
|
|
141
|
+
): Promise<Map<string, SecretResolutionResult>> {
|
|
142
|
+
const results = new Map<string, SecretResolutionResult>();
|
|
143
|
+
|
|
144
|
+
for (const name of secretNames) {
|
|
145
|
+
const result = await resolveSecret(toolPath, name);
|
|
146
|
+
results.set(name, result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return results;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check if all required secrets are available for a tool
|
|
154
|
+
*
|
|
155
|
+
* @param toolPath - The tool path to check
|
|
156
|
+
* @param requiredSecrets - Array of required secret names
|
|
157
|
+
* @returns Object with available and missing secrets
|
|
158
|
+
*/
|
|
159
|
+
export async function checkRequiredSecrets(
|
|
160
|
+
toolPath: string,
|
|
161
|
+
requiredSecrets: string[]
|
|
162
|
+
): Promise<{
|
|
163
|
+
allFound: boolean;
|
|
164
|
+
found: SecretResolution[];
|
|
165
|
+
missing: string[];
|
|
166
|
+
}> {
|
|
167
|
+
const found: SecretResolution[] = [];
|
|
168
|
+
const missing: string[] = [];
|
|
169
|
+
|
|
170
|
+
for (const name of requiredSecrets) {
|
|
171
|
+
const result = await resolveSecret(toolPath, name);
|
|
172
|
+
if (result.found) {
|
|
173
|
+
found.push(result);
|
|
174
|
+
} else {
|
|
175
|
+
missing.push(name);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
allFound: missing.length === 0,
|
|
181
|
+
found,
|
|
182
|
+
missing,
|
|
183
|
+
};
|
|
184
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for secrets and environment management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Constants
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
/** Keyring service name for all Enact secrets */
|
|
10
|
+
export const KEYRING_SERVICE = "enact-cli";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Secret Types
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Result of secret resolution with namespace information
|
|
18
|
+
*/
|
|
19
|
+
export interface SecretResolution {
|
|
20
|
+
/** The namespace where the secret was found */
|
|
21
|
+
namespace: string;
|
|
22
|
+
/** The secret value */
|
|
23
|
+
value: string;
|
|
24
|
+
/** The secret key */
|
|
25
|
+
key: string;
|
|
26
|
+
/** Whether the secret was found */
|
|
27
|
+
found: true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Result when secret is not found
|
|
32
|
+
*/
|
|
33
|
+
export interface SecretNotFound {
|
|
34
|
+
/** The secret key that was looked for */
|
|
35
|
+
key: string;
|
|
36
|
+
/** Whether the secret was found */
|
|
37
|
+
found: false;
|
|
38
|
+
/** Namespaces that were searched */
|
|
39
|
+
searchedNamespaces: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Result of secret resolution (found or not found)
|
|
44
|
+
*/
|
|
45
|
+
export type SecretResolutionResult = SecretResolution | SecretNotFound;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Metadata about a stored secret
|
|
49
|
+
*/
|
|
50
|
+
export interface SecretMetadata {
|
|
51
|
+
/** Secret key name */
|
|
52
|
+
key: string;
|
|
53
|
+
/** Namespace where it's stored */
|
|
54
|
+
namespace: string;
|
|
55
|
+
/** When it was created/last modified (if available) */
|
|
56
|
+
modified?: Date;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Trace entry for debugging secret resolution
|
|
61
|
+
*/
|
|
62
|
+
export interface SecretTraceEntry {
|
|
63
|
+
/** Namespace that was checked */
|
|
64
|
+
namespace: string;
|
|
65
|
+
/** Account string used for lookup */
|
|
66
|
+
account: string;
|
|
67
|
+
/** Whether secret was found at this namespace */
|
|
68
|
+
found: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Full trace of secret resolution
|
|
73
|
+
*/
|
|
74
|
+
export interface SecretTrace {
|
|
75
|
+
/** Secret key being resolved */
|
|
76
|
+
key: string;
|
|
77
|
+
/** Tool path used for resolution */
|
|
78
|
+
toolPath: string;
|
|
79
|
+
/** Each namespace checked in order */
|
|
80
|
+
entries: SecretTraceEntry[];
|
|
81
|
+
/** Final result */
|
|
82
|
+
result: SecretResolutionResult;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// Environment Variable Types
|
|
87
|
+
// ============================================================================
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Scope where environment variables can be stored
|
|
91
|
+
*/
|
|
92
|
+
export type EnvScope = "global" | "local" | "default";
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Location where environment variables can be stored (files only)
|
|
96
|
+
*/
|
|
97
|
+
export type EnvFileLocation = "global" | "local";
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* An environment variable with its value and source
|
|
101
|
+
*/
|
|
102
|
+
export interface EnvironmentVariable {
|
|
103
|
+
/** Variable key */
|
|
104
|
+
key: string;
|
|
105
|
+
/** Variable value */
|
|
106
|
+
value: string;
|
|
107
|
+
/** Where it was resolved from */
|
|
108
|
+
source: EnvScope;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Result of environment variable resolution
|
|
113
|
+
*/
|
|
114
|
+
export interface EnvResolution {
|
|
115
|
+
/** Variable key */
|
|
116
|
+
key: string;
|
|
117
|
+
/** Resolved value */
|
|
118
|
+
value: string;
|
|
119
|
+
/** Source of the value */
|
|
120
|
+
source: EnvScope;
|
|
121
|
+
/** File path if from a file */
|
|
122
|
+
filePath?: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Parsed .env file content
|
|
127
|
+
*/
|
|
128
|
+
export interface ParsedEnvFile {
|
|
129
|
+
/** Key-value pairs */
|
|
130
|
+
vars: Record<string, string>;
|
|
131
|
+
/** Preserved lines (for writing back with comments) */
|
|
132
|
+
lines: EnvFileLine[];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* A line in an .env file (for preserving format)
|
|
137
|
+
*/
|
|
138
|
+
export interface EnvFileLine {
|
|
139
|
+
/** Type of line */
|
|
140
|
+
type: "comment" | "empty" | "variable";
|
|
141
|
+
/** Original line content */
|
|
142
|
+
raw: string;
|
|
143
|
+
/** Variable key (if type is 'variable') */
|
|
144
|
+
key?: string;
|
|
145
|
+
/** Variable value (if type is 'variable') */
|
|
146
|
+
value?: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Dagger Secret URI Types
|
|
151
|
+
// ============================================================================
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Supported Dagger secret URI schemes
|
|
155
|
+
*/
|
|
156
|
+
export type DaggerSecretScheme = "env" | "file" | "cmd" | "op" | "vault";
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Parsed Dagger secret URI
|
|
160
|
+
*/
|
|
161
|
+
export interface DaggerSecretUri {
|
|
162
|
+
/** The URI scheme */
|
|
163
|
+
scheme: DaggerSecretScheme;
|
|
164
|
+
/** The URI value (without scheme://) */
|
|
165
|
+
value: string;
|
|
166
|
+
/** Original full URI */
|
|
167
|
+
original: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Options for getting a secret object
|
|
172
|
+
*/
|
|
173
|
+
export interface GetSecretOptions {
|
|
174
|
+
/** Override URI to use instead of keyring */
|
|
175
|
+
overrideUri?: string;
|
|
176
|
+
/** Whether to trace resolution */
|
|
177
|
+
trace?: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Result from getSecretObject
|
|
182
|
+
*/
|
|
183
|
+
export interface SecretObject {
|
|
184
|
+
/** The secret name */
|
|
185
|
+
name: string;
|
|
186
|
+
/** The secret value */
|
|
187
|
+
value: string;
|
|
188
|
+
/** Source of the secret */
|
|
189
|
+
source: "keyring" | "override";
|
|
190
|
+
/** Namespace if from keyring */
|
|
191
|
+
namespace?: string;
|
|
192
|
+
/** Override URI if used */
|
|
193
|
+
overrideUri?: string;
|
|
194
|
+
}
|