diff --git a/VERSION b/VERSION
index 81566e4..4daf42f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.27.0
\ No newline at end of file
+0.27.1
\ No newline at end of file
diff --git a/cmd/nomos/main.go b/cmd/nomos/main.go
index 9af73d4..aab9b93 100644
--- a/cmd/nomos/main.go
+++ b/cmd/nomos/main.go
@@ -63,11 +63,11 @@ func main() {
var secretsResolved int
if sec != nil {
resCtx, resCancel := context.WithTimeout(context.Background(), 10*time.Second)
- if v := secrets.ResolveSecret(resCtx, sec, "mcp/bearer-token", ""); v != "" {
+ if v := secrets.ResolveSecret(resCtx, sec, "mcp_bearer-token", ""); v != "" {
mcpToken = v
secretsResolved++
}
- openrouterAPIKey = secrets.ResolveSecret(resCtx, sec, "openrouter/api-key", os.Getenv("OPENROUTER_API_KEY"))
+ openrouterAPIKey = secrets.ResolveSecret(resCtx, sec, "openrouter_api-key", os.Getenv("OPENROUTER_API_KEY"))
if openrouterAPIKey != "" && openrouterAPIKey != os.Getenv("OPENROUTER_API_KEY") {
secretsResolved++
}
diff --git a/cmd/oikos/main.go b/cmd/oikos/main.go
index 87bd118..c3551bf 100644
--- a/cmd/oikos/main.go
+++ b/cmd/oikos/main.go
@@ -53,18 +53,18 @@ func main() {
)
if sec != nil {
overlays := secrets.ConfigOverlays(map[string]func(string){
- "matrix/token": func(v string) { cfg.MatrixToken = v },
- "approval/hmac-secret": func(v string) { cfg.ApprovalHMACSecret = v },
- "mcp/bearer-token": func(v string) { cfg.MCPBearerToken = v },
- "api/token": func(v string) { cfg.APIToken = v },
- "oidc/client-secret": func(v string) { cfg.OIDCClientSecret = v },
+ "matrix_token": func(v string) { cfg.MatrixToken = v },
+ "approval_hmac-secret": func(v string) { cfg.ApprovalHMACSecret = v },
+ "mcp_bearer-token": func(v string) { cfg.MCPBearerToken = v },
+ "api_token": func(v string) { cfg.APIToken = v },
+ "oidc_client-secret": func(v string) { cfg.OIDCClientSecret = v },
})
n := secrets.OverlayConfig(ctx, sec, overlays)
slog.Info("secrets resolved from Infisical", "count", n)
secrets.VerifyExpectedSecrets(ctx, sec, []string{
- "matrix/token", "approval/hmac-secret", "mcp/bearer-token",
- "api/token", "oidc/client-secret", "openrouter/api-key", "webhook/hmac-secret",
+ "matrix_token", "approval_hmac-secret", "mcp_bearer-token",
+ "api_token", "oidc_client-secret", "openrouter_api-key", "webhook_hmac-secret",
})
}
@@ -381,13 +381,13 @@ func runSecret(ctx context.Context, cfg config.Config) {
// expectedSecrets is the set of keys that should exist in Infisical
// for a fully-migrated deployment.
var expectedSecrets = []string{
- "matrix/token",
- "approval/hmac-secret",
- "mcp/bearer-token",
- "api/token",
- "oidc/client-secret",
- "openrouter/api-key",
- "webhook/hmac-secret",
+ "matrix_token",
+ "approval_hmac-secret",
+ "mcp_bearer-token",
+ "api_token",
+ "oidc_client-secret",
+ "openrouter_api-key",
+ "webhook_hmac-secret",
}
// runSecretVerify checks that all expected secrets are present in Infisical.
@@ -425,11 +425,11 @@ func runSecretAudit(ctx context.Context, cfg config.Config) {
backend := newInfisicalBackendOrFail(cfg)
envValues := map[string]string{
- "matrix/token": cfg.MatrixToken,
- "approval/hmac-secret": cfg.ApprovalHMACSecret,
- "mcp/bearer-token": cfg.MCPBearerToken,
- "api/token": cfg.APIToken,
- "oidc/client-secret": cfg.OIDCClientSecret,
+ "matrix_token": cfg.MatrixToken,
+ "approval_hmac-secret": cfg.ApprovalHMACSecret,
+ "mcp_bearer-token": cfg.MCPBearerToken,
+ "api_token": cfg.APIToken,
+ "oidc_client-secret": cfg.OIDCClientSecret,
}
fmt.Println("key infisical env status")
diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go
index 57c0486..c241f33 100644
--- a/cmd/webhook/main.go
+++ b/cmd/webhook/main.go
@@ -32,7 +32,7 @@ func main() {
secret := resolveWebhookHMAC(ctx)
if secret == "" {
- fmt.Fprintln(os.Stderr, "WEBHOOK_HMAC_SECRET must be set (env var or Infisical webhook/hmac-secret)")
+ fmt.Fprintln(os.Stderr, "WEBHOOK_HMAC_SECRET must be set (env var or Infisical webhook_hmac-secret)")
os.Exit(1)
}
@@ -111,5 +111,5 @@ func resolveWebhookHMAC(ctx context.Context) string {
os.Getenv("OIKOS_SECRETS_DIR"),
)
envFallback := os.Getenv("WEBHOOK_HMAC_SECRET")
- return secrets.ResolveSecret(ctx, sec, "webhook/hmac-secret", envFallback)
+ return secrets.ResolveSecret(ctx, sec, "webhook_hmac-secret", envFallback)
}
diff --git a/scripts/deploy.sh b/scripts/deploy.sh
index d83e7e5..a02ccea 100755
--- a/scripts/deploy.sh
+++ b/scripts/deploy.sh
@@ -51,10 +51,14 @@ echo "[6/6] health check"
for i in $(seq 1 $RETRIES); do
if curl -sf "$HEALTH_URL" > /dev/null 2>&1; then
echo "healthy after ${i}s"
- exit 0
+ break
fi
sleep "$SLEEP"
done
-echo "ERROR: health check failed after $((RETRIES * SLEEP))s"
-exit 1
+# 7. Seed secrets into Infisical (idempotent)
+echo "[7/7] seed secrets"
+docker compose exec -T api oikos secret list > /dev/null 2>&1 && \
+ docker compose cp scripts/seed-secrets.sh api:/opt/oikos/scripts/seed-secrets.sh 2>/dev/null && \
+ docker compose exec -T api /opt/oikos/scripts/seed-secrets.sh || \
+ echo "WARNING: secret seeding skipped (infisical not reachable)"
diff --git a/scripts/deploy/network.hubris.oikos-deploy-webhook.plist b/scripts/deploy/network.hubris.oikos-deploy-webhook.plist
index 2717c38..554e7d8 100644
--- a/scripts/deploy/network.hubris.oikos-deploy-webhook.plist
+++ b/scripts/deploy/network.hubris.oikos-deploy-webhook.plist
@@ -10,8 +10,16 @@
EnvironmentVariables
- WEBHOOK_HMAC_SECRET
- 6502524162d6dbc3f6d137000395d401f1837d74ef9bb0a876f8e6bbd65d1ff2
+ OIKOS_INFISICAL_SITE_URL
+ http://localhost:8080
+ OIKOS_INFISICAL_CLIENT_ID
+ 82e6e362-bbee-4f22-b44e-215c85bdb14a
+ OIKOS_INFISICAL_CLIENT_SECRET
+ aa7c928b366591741e4fa99016c5644fc6119b4174ba0dab3570db1229e0bdf1
+ OIKOS_INFISICAL_PROJECT_ID
+ a436936f-6610-4698-9075-76013af7c68e
+ OIKOS_INFISICAL_ENV
+ dev
WEBHOOK_REPO_DIR
/Users/dtoro/Projects/oikos
WEBHOOK_LISTEN
diff --git a/scripts/seed-secrets.sh b/scripts/seed-secrets.sh
new file mode 100755
index 0000000..675521e
--- /dev/null
+++ b/scripts/seed-secrets.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# One-shot: populate Infisical with oikos secrets from env vars.
+# Designed to run inside the oikos-api container where Infisical is reachable.
+# Safe to re-run (set is idempotent).
+#
+# Usage: docker exec oikos-api-1 /opt/oikos/scripts/seed-secrets.sh
+#
+# Secrets are read from the container environment (set via docker-compose).
+# If a secret is already in Infisical, it is updated in place.
+
+set -e
+
+echo "=== seed-secrets: $(date) ==="
+
+KEYS="
+matrix_token:${OIKOS_MATRIX_TOKEN:-}
+approval_hmac-secret:${OIKOS_APPROVAL_HMAC_SECRET:-}
+mcp_bearer-token:${OIKOS_MCP_BEARER_TOKEN:-}
+api_token:${OIKOS_API_TOKEN:-}
+oidc_client-secret:${OIKOS_OIDC_CLIENT_SECRET:-}
+openrouter_api-key:${OPENROUTER_API_KEY:-}
+webhook_hmac-secret:${WEBHOOK_HMAC_SECRET:-}
+"
+
+set_count=0
+skip_count=0
+
+echo "$KEYS" | while IFS=: read -r key value; do
+ [ -z "$key" ] && continue
+ if [ -z "$value" ]; then
+ echo "SKIP: $key (env var empty/missing)"
+ skip_count=$((skip_count + 1))
+ continue
+ fi
+ if oikos secret set "$key" "$value" 2>/dev/null; then
+ echo "SET: $key"
+ set_count=$((set_count + 1))
+ else
+ echo "FAIL: $key"
+ fi
+done
+
+echo ""
+echo "seed-secrets complete: $set_count set, $skip_count skipped"