feat(FN-009): implement config and secrets management with runtime injection
- Add RuntimeInjectionService for scope-based config/secret resolution - Mount configs as JSON files at /app/config/ with 0400 permissions - Inject secrets as environment variables with uppercase keys - Implement scope hierarchy: instance > project > user > global - Create ConfigListPage and SecretListPage frontend components - Mask secret values in API responses (never expose decrypted) - Validate secrets exist before spawning containers - Add comprehensive tests for runtime injection service - Update documentation with config/secrets workflow
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Project, ProjectCreate, ProjectUpdate, ToolDefinition, ToolInstance, User } from '../types/api.ts'
|
||||
import type { Config, ConfigCreate, Project, ProjectCreate, ProjectUpdate, Secret, SecretCreate, ToolDefinition, ToolInstance, User } from '../types/api.ts'
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
|
||||
|
||||
@@ -141,4 +141,58 @@ export const api = {
|
||||
const response = await fetchWithAuth('/tools')
|
||||
return response.json()
|
||||
},
|
||||
|
||||
getConfigs: async (projectId: string): Promise<Config[]> => {
|
||||
const response = await fetchWithAuth(`/configs?scope_type=project&scope_id=${projectId}`)
|
||||
return response.json()
|
||||
},
|
||||
|
||||
createConfig: async (data: ConfigCreate): Promise<Config> => {
|
||||
const response = await fetchWithAuth('/configs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
return response.json()
|
||||
},
|
||||
|
||||
updateConfig: async (id: string, data: { value: unknown }): Promise<Config> => {
|
||||
const response = await fetchWithAuth(`/configs/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
return response.json()
|
||||
},
|
||||
|
||||
deleteConfig: async (id: string): Promise<void> => {
|
||||
await fetchWithAuth(`/configs/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
},
|
||||
|
||||
getSecrets: async (projectId: string): Promise<Secret[]> => {
|
||||
const response = await fetchWithAuth(`/secrets?scope_type=project&scope_id=${projectId}`)
|
||||
return response.json()
|
||||
},
|
||||
|
||||
createSecret: async (data: SecretCreate): Promise<Secret> => {
|
||||
const response = await fetchWithAuth('/secrets', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
return response.json()
|
||||
},
|
||||
|
||||
updateSecret: async (id: string, data: { value: string }): Promise<Secret> => {
|
||||
const response = await fetchWithAuth(`/secrets/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
return response.json()
|
||||
},
|
||||
|
||||
deleteSecret: async (id: string): Promise<void> => {
|
||||
await fetchWithAuth(`/secrets/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user