feat(secrets): seal-secret.sh (credential-free) + fuzefront-secrets scaffold - #92
Conversation
…ledSecret scaffold seal-secret.sh <KEY>: hidden-prompt → fetch current public cert from FuzeInfra (stable URL; handles key rotation) → kubeseal --cert --merge-into the manifest IN PLACE (preserves other keys). Per-repo scope hard-coded (fuzefront/ fuzefront-secrets), --scope/--cert/--in/--manifest overrides. No kubeconfig: only the public cert is needed to seal; FuzeInfra holds the decrypt key. Manifest is the SHARED app secret (Authentik/Permit/DB/OAuth/messaging/LLM + billing) — documented full key inventory + loud warning never to sync it empty (would clobber live keys). Populate every key via the script before Argo-wiring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tool encoding issues)
CI Fix —
|
…ead of shared blob Billing's 3 sensitive keys (STRIPE_SECRET_KEY/STRIPE_WEBHOOK_SECRET/ BILLING_INTERNAL_TOKEN) now live in their OWN SealedSecret 'billing-secrets'; billing-service Deployment references it (DB_PASSWORD/PERMIT_API_KEY stay shared in fuzefront-secrets). A compromised billing pod can't read Authentik/SMTP/OAuth/LLM secrets, and sealing/rotating billing keys can't clobber other services. Dropped the shared-secret scaffold (operator-owned). seal-secret.sh defaults to scope fuzefront/billing-secrets and is marked an interim copy (canonical tool + cert URL + methodology owned by FuzeInfra, delegated separately).
CI Autofix — branch pushed for reviewI diagnosed the root cause and pushed a fix on branch Root causeGitHub Actions is now forcing Node.js 24 on runners that request Node 20 (Node 20 is deprecated). Node 24 supports synchronous
FixRebuilt all 12
No application logic was changed — only the module format of the pre-committed dist files. To merge: open a PR from |
CI Fix InvestigationRoot cause: The ```js When the backend (CJS) loads Fix: Rebuilt The fix is on branch |
…illing_svc role, DB, secrets) - values: complete billingService (dbUser=billing_svc, secretName=billing-secrets, meterFlushIntervalSec, permitPdpUrl, dbBootstrap) — template referenced these but they were undefined (billing never actually deployed). - billing-db-bootstrap Job (pre-install, idempotent): creates least-privilege billing_svc role + 'billing' schema + grants via psql as the superuser. billing- service self-migrates its schema on boot as billing_svc. - ingress carve-out: ONLY /api/v1/billing/webhooks/stripe is public (Exact match, Stripe-signature verified); rest of /api/v1/billing stays internal. - billing-secrets gains BILLING_DB_PASSWORD (billing_svc's password); STRIPE/BILLING env always render (dropped the Helm-values guards — SealedSecret provides them). - values-prod: billingService.enabled=true (fixed a duplicate-key bug that clobbered it — billingService was declared twice; merged node-2 affinity into one block). - Verified: helm lint clean + helm template renders all billing artifacts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI Fix —
|
…rt resolution Mirror the proven @fuzefront/chat-client fix (#90): billing-ui keeps @fuzefront/billing-client external, so the host vite/rollup bundle must statically resolve its named exports. Plain tsc emitted CJS __exportStar(require()) -> 'X is not exported' at host build. tsup emits static ESM re-exports + .d.ts + .cjs. Adds module/exports map + tsup devDep; tsconfig ignoreDeprecations '6.0' (TS 6.0.3 baseUrl escalation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…internal-by-default) Decision: path-based routing under the single app host, not per-service subdomains (one cert, no DNS churn, same-origin/no-CORS, shared cookies). Services internal-only by default; ingress carves out only public paths (billing's Stripe webhook); browser-facing APIs go through host-backend proxy with the service's internal token. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI Fix: Playwright sign-in flow — postgres health check never passesRoot cause: The --health-cmd "pg_isready -U fuzeinfra"When no database is specified, Fix: Add - --health-cmd "pg_isready -U fuzeinfra"
+ --health-cmd "pg_isready -U fuzeinfra -d fuzefront_platform"I prepared the one-line fix on branch |
CI Fix InvestigationThe Playwright sign-in flow job fails because the backend never starts: Root CauseThe billing feature commit ( The fix is to use FixBranch |
CI Fix — branch
|
CI fix pushed — branch ready for PRFailing jobs: Email Integration (MailHog), Notify Team Root cause`services/email-service` was never added to the root `package.json` workspaces array, even though the service's Dockerfile already used the workspace-root approach (`npm ci --workspace=services/email-service`). Because it was not registered, the root `package-lock.json` had no entry for it. The CI step: ```yaml
failed because `npm ci` requires a lock file and `@fuzefront/shared` is a private monorepo package not published to npm — so there was no way to resolve it in a standalone install. The Notify Team job cascaded because `email-integration` returned `failure`. Fix (2 files, no workflow changes)
npm 7+ automatically detects the workspace root when `npm ci` is run from a workspace-member subdirectory, so the existing CI step works without modification. Verification`cd services/email-service && npm ci --dry-run` passes after the workspace registration (confirmed locally on this runner). Please open a PR from `claude-auto-fix-ci-feat/billing-secret-tooling-27994777298` → `feat/billing-secret-tooling` to merge the fix. |
CI fix ready — branch
|
CI fix pushed — branch `claude-auto-fix-ci-feat/billing-secret-tooling-27996506999`Root causeThe Email Integration (MailHog) job calls `npm ci` inside `services/email-service`, but two things were wrong:
The Notify Team failure is purely downstream — it echoes failure and exits 1 whenever any upstream job fails. Fix (commit `1f15386`)
Verified with `npm ci --dry-run`: exits 0, resolves 427 packages. Please merge `claude-auto-fix-ci-feat/billing-secret-tooling-27996506999` → `feat/billing-secret-tooling` to unblock this PR's CI. |
CI Fix Analysis — branch
|
CI fix — branch ready for reviewThe Email Integration (MailHog) job was failing because The Dockerfile for the service already used Fix applied on branch
|
#669) The postprod-smoke@fuzefront.com account was provisioned on an earlier CI run. Since then POST_PROD_PASSWORD and the Authentik-stored password have drifted, causing every run of test 7 to hit a 401 on POST /api/v1/security/session and hard-fail (runs #76–#92). Root cause: the email-available check returns `available: false` (account exists), so the spec falls into the sign-in branch and fails with 401 instead of self-provisioning. Fix: when sign-in returns 401 and AUTHENTIK_ADMIN_TOKEN is available, the spec now: 1. Calls GET https://auth.fuzefront.com/api/v3/core/users/?email=<EMAIL> to find the Authentik user's numeric pk (mirrors accountApi.ts findUserPk). 2. Calls POST .../set_password/ to reset the password to POST_PROD_PASSWORD (mirrors accountApi.ts setUserPassword). 3. Retries POST /api/v1/security/session — now passes. 4. Annotates the test result so the self-heal is visible in the report. Without AUTHENTIK_ADMIN_TOKEN the spec fails with a clear diagnostic rather than looping silently on 401. Workflow changes: thread AUTHENTIK_ADMIN_TOKEN through prod-post-deploy.yml → post-prod-e2e.yml → the "Run post-prod smoke" step env. Claude-Session: https://claude.ai/code/session_01VDvprmS9SwG7vcVZum7RDM Co-authored-by: Claude <noreply@anthropic.com>
Adds
deploy/scripts/seal-secret.sh <KEY>— hidden prompt → fetch current sealed-secrets public cert from FuzeInfra (stable URL, rotation-safe) →kubeseal --cert --merge-intothe manifest in place (preserves other keys). No kubeconfig/cluster access needed (only the public cert seals; FuzeInfra holds the decrypt key). Per-repo scope hard-coded (fuzefront/fuzefront-secrets),--scope/--cert/--in/--manifestoverrides.Also scaffolds
deploy/contabo/sealed/fuzefront-secrets.yaml— the SHARED app secret (Authentik/Permit/DB/OAuth/messaging/LLM + billing) with the full key inventory documented and a loud warning never to sync it empty/partial (would clobber the live secret).Depends on: FuzeInfra exposing the sealed-secrets public cert at a stable URL (separate @claude delegation). Until then, use
--cert <local pub.pem>.🤖 Generated with Claude Code