feat(app): node-override secrets UX + supabase scaffold refresh
- Secrets page: 'Node overrides' section (per-node values that shadow a shared
secret on that node) — list/reveal/edit/delete + add; shared secrets show an
'override: <node>' badge. Authority-only writes.
- API: GET /secrets/overrides, GET/PUT/DELETE /secrets/overrides/{node}/{name};
OpenBaoBackend.list_node_overrides enumerates castle/nodes/*
- supabase scaffold: drop stale 'cat ~/.castle/secrets/...' + 'castle deploy',
point at the dashboard Secrets page / castle apply
- tests: file-backend override endpoints (empty/400/404)
Verified live: primer's postgres override discoverable + full CRUD round-trip.
This commit is contained in:
@@ -583,3 +583,29 @@ export function useDeleteSecret() {
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["secrets"] }),
|
||||
})
|
||||
}
|
||||
|
||||
export function useSecretOverrides() {
|
||||
return useQuery({
|
||||
queryKey: ["secret-overrides"],
|
||||
queryFn: () =>
|
||||
apiClient.get<{ overrides: Record<string, string[]> }>("/secrets/overrides"),
|
||||
})
|
||||
}
|
||||
|
||||
export function useSetOverride() {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ node, name, value }: { node: string; name: string; value: string }) =>
|
||||
apiClient.put(`/secrets/overrides/${node}/${name}`, { value }),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["secret-overrides"] }),
|
||||
})
|
||||
}
|
||||
|
||||
export function useDeleteOverride() {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: ({ node, name }: { node: string; name: string }) =>
|
||||
apiClient.delete(`/secrets/overrides/${node}/${name}`),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["secret-overrides"] }),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user