English
Goals
- Connect admin-web onboarding to prego-control-plane jobs, then Provision Tenant (Pulumi, Ansible, Zuplo sync,
provision-complete). - Optionally record staging-only onboarding funnel events in D1 via
POST /internal/funnel-events/ingestusing the admin BFF routePOST /api/debug/funnel-logwhenNEXT_PUBLIC_PREGO_ONBOARDING_DEBUG=1.
Preconditions (all phases)
| Area | Notes |
|---|---|
| Zuplo | Browser can call CP POST /v1/* — ALLOWED_ORIGINS includes the admin host. See prego-zuplo runbook. |
| admin-web | NEXT_PUBLIC_PREGO_CONTROL_PLANE_URL, NEXT_PUBLIC_PREGO_AUTH_URL; Worker secret PREGO_CONTROL_PLANE_INTERNAL_API_KEY matches CP INTERNAL_API_KEY. |
| CP D1 | Migrations applied. |
| Pipeline trigger | Either PROVISION_QUEUE with a consumer deployment, or GITHUB_TOKEN plus GITHUB_WORKFLOW_DISPATCH_URL pointing at provision-tenant.yml. |
Phase 0 — Browser to CP job
- Set production
NEXT_PUBLIC_PREGO_CONTROL_PLANE_URLand verify Zuplo routes for/v1/tenantsand/v1/jobs/:id. - Verify: After company submit, HTTP 202 with
job_id; job status progresses from Pending.
Phase 1 — GitHub workflow_dispatch
- CP secrets:
GITHUB_TOKEN(workflow scope),GITHUB_WORKFLOW_DISPATCH_URL=https://api.github.com/repos/ORG/REPO/actions/workflows/provision-tenant.yml/dispatches(replace ORG/REPO; repo is usually the Prego monorepo that hosts the workflow). - Queue path uses the same URL and token for idempotent dispatch.
Phase 2 — Placement vs workflow inputs
- Workflow fails fast if
target_server_idis empty andcreate_new_serveris false. Align placement and queue payload with workflow inputs.
Phase 3 — Hetzner and Pulumi
- GitHub secrets:
HCLOUD_TOKEN_SG,PULUMI_ACCESS_TOKEN. Confirm prego-pulumi stack outputs (server_ip,db_server_ip) and SSH key name in Hetzner.
Phase 4 — Ansible
- Secrets:
PREGO_SSH_PRIVATE_KEY,PREGO_DB_ROOT_PASSWORD. Workflow checks out prego-ansible and runsplaybook.yml.
Phase 5 — Zuplo sync and CP callback
- Secrets:
ZUPLO_ACCOUNT_NAME,ZUPLO_BUCKET_NAME,ZUPLO_API_KEY. Callback postsCompletedorFailedto/internal/provision-complete.
Phase 6 — DNS (optional)
tenant-dnsmay useCLOUDFLARE_API_TOKENandCLOUDFLARE_ZONE_ID; step is best-effort (continue-on-error).
Failure observation
- CP:
GET /v1/jobs/:id,GET /internal/trace/:trace_id(Bearer), operator UIs under/cp/*where available. - GitHub:
callback-failedreportsfailure_stage.
Export funnel events to a file
From the monorepo root:
export CONTROL_PLANE_URL="https://your-gateway.example"export CONTROL_PLANE_API_KEY="your INTERNAL_API_KEY"./scripts/export-funnel-events.sh trace_your_id 200 > funnel.jsonUses GET /internal/funnel-events?trace_id=... on the control plane (via Zuplo).
Staging onboarding funnel debug (implementation)
- Enable: build or Worker variable
NEXT_PUBLIC_PREGO_ONBOARDING_DEBUG=1(staging only; leave unset in production). - Behavior: Client batches events to same-origin
POST /api/debug/funnel-log, which forwards to CPPOST /internal/funnel-events/ingestwith sourceprego_admin_web_onboarding_debug. When the flag is off, the route returns 404. - Privacy: Do not log OTP codes, passwords, or JWTs. Email uses SHA-256 fingerprint only for correlation.
- Code:
apps/admin-web/lib/onboarding-funnel-debug.ts,app/api/debug/funnel-log/route.ts,components/onboarding/OnboardingFunnelDebugProvider.tsx.
한국어
목표
- admin 온보딩에서 컨트롤 플레인 잡 생성 후 GitHub Provision Tenant 워크플로로 인프라·Zuplo·완료 콜백까지 연결한다.
- 스테이징에서만
NEXT_PUBLIC_PREGO_ONBOARDING_DEBUG=1로 온보딩 단계 이벤트를 D1funnel_events에 남길 수 있다 (BFFPOST /api/debug/funnel-log).
사전 조건
위 표와 동일하며, Zuplo CORS·admin Worker 시크릿·CP D1 마이그레이션·GitHub 디스패치 또는 큐가 준비되어야 한다.
단계별 요약
- Phase 0: 브라우저에서 CP로 잡 생성 확인.
- Phase 1:
GITHUB_TOKEN및GITHUB_WORKFLOW_DISPATCH_URL설정 후 워크플로 자동 실행 확인. - Phase 2: 배치 결과와 워크플로 입력(
create_new_server,target_server_id) 일치. - Phase 3: Hetzner·Pulumi 시크릿 및 스택.
- Phase 4: Ansible SSH·DB 비밀번호.
- Phase 5: Zuplo sync 시크릿 및
provision-complete. - Phase 6: (선택) Cloudflare DNS.
퍼널 이벤트 파일 내보내기
scripts/export-funnel-events.sh 로 trace_id 별 JSON을 파일로 저장할 수 있다. 운영자는 CP INTERNAL_API_KEY를 사용한다.
스테이징 디버그 로그
- 프로덕션에서는 플래그를 끈다. OTP·비밀번호·토큰 원문은 기록하지 않는다.