5f060e3d1e
hosts.api_key, customer_configs.api_key / retrieval_password and host_pbs_secrets.value now hold the R-821/R-133 seal (enc:v1:, OFFSITE_SECRET_KEY). The two API keys get an api_key_hash lookup twin (SHA-256, backfilled keyless in migrate()), so box authentication never needs the sealing key; a row with no hash is matched on its plaintext only while it is plaintext. SealLegacyBoxSecrets seals legacy rows at start-up (idempotent, non-fatal). A sealed value that does not open sets SecretsUnreadable: serve/compare paths answer 500, saves refuse the record, the PBS token is not burned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
24 lines
757 B
Go
24 lines
757 B
Go
package configgen
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
|
)
|
|
|
|
// R-879: a config whose sealed secrets did not open must not become a controller.yaml with an empty
|
|
// hub key — Generate refuses it.
|
|
func TestR879_GenerateRefusesUnreadableSecrets(t *testing.T) {
|
|
cfg := &store.CustomerConfig{CustomerID: "c1", ConfigJSON: "{}", SecretsUnreadable: true}
|
|
out, err := Generate("hub: {}\n", cfg, nil)
|
|
if err == nil || strings.Contains(out, "api_key") {
|
|
t.Fatalf("Generate = %q, %v — want a refusal", out, err)
|
|
}
|
|
cfg.SecretsUnreadable = false
|
|
cfg.APIKey = "k1"
|
|
if out, err := Generate("hub: {}\n", cfg, nil); err != nil || !strings.Contains(out, "k1") {
|
|
t.Fatalf("readable config = %q, %v", out, err)
|
|
}
|
|
}
|