Bilko Backoffice — Ops Infra (Logging Views + support@ Forwarding + Preflight)
Bilko Backoffice — Ops Infra (MC #103325)
Branch: feat/103325-backoffice-infra | PR: #317 | Proveo verdict: PASS (2026-06-10) | Sibling: Backoffice Backend MVP (page 3100)
1. Cloud Logging Saved Views
GCP project: tribal-sign-487920-k0
Bucket: _Default (global)
Verified via: gcloud logging views list --bucket=_Default --location=global --project=tribal-sign-487920-k0
| View ID | Scope filter | Intended use / Log Explorer query to add |
|---|---|---|
bilko-error-by-org |
resource.type="cloud_run_revision" AND resource.labels.service_name=~"bilko-api-(demo|stage)" |
Add query severity>=ERROR. Group results by orgId (parse via JSON_EXTRACT(textPayload, "$.orgId") — orgId lives in textPayload JSON, not jsonPayload). |
bilko-request-trace |
resource.type="cloud_run_revision" AND resource.labels.service_name=~"bilko-(api|web)-(demo|stage)" |
Add query logName=~"stdout" OR logName=~"requests". Correlate requests end-to-end by requestId field in textPayload. |
bilko-5xx-demo |
resource.type="cloud_run_revision" AND resource.labels.service_name=~"bilko-(api|web)-demo" |
Add query httpRequest.status>=500. Scoped to demo environment only. |
GCP constraint — view filter expressiveness
GCP gcloud logging views create --log-filter only accepts log source, resource type, appHub fields, user labels, and log ID conditions. Severity comparisons (severity>=ERROR) and field comparisons (httpRequest.status>=500) are not valid in view filters — they must be added as Log Explorer query refinements on top of the saved view scope. This is a documented GCP platform limitation. Each view description in GCP documents this explicitly.
Log schema note: Bilko API logs structured data as JSON inside textPayload (not jsonPayload). The textPayload schema is: {"requestId":"...","method":"...","path":"...","status":N,"durationMs":N,"userId":"...","orgId":"...","ip":"..."}. ERROR logs are stack traces in textPayload; orgId is present on request-completion log lines, not on exception lines.
2. [email protected] Email Forwarding
MX provider — IMPORTANT
bilko.cloud MX = Migadu (aspmx1.migadu.com + aspmx2.migadu.com, confirmed via dig MX bilko.cloud). The CF Email Routing section in DEPLOY-MAP.md is STALE and must be corrected — Cloudflare does not handle bilko.cloud email.
Implemented forwarding
Mail flow: [email protected] (Migadu mailbox, may_receive=true, may_send=false) → Migadu forwarding → [email protected]
Key Migadu design constraint: Alias destinations only accept same-domain addresses — external addresses are silently rewritten to <localpart>@<same-domain>. The correct mechanism for external cross-domain delivery is a forwarding on a mailbox object (not an alias).
Implementation steps taken:
- Confirmed
GET /v1/domains/bilko.cloud/mailboxes/support/forwardings— support@ was alias-only (no mailbox). - Created
[email protected]mailbox:may_receive=true,may_send=false, IMAP/POP3 disabled (receive-only). - Added forwarding via
POST /v1/domains/bilko.cloud/mailboxes/support/forwardings {"address":"[email protected]"}— response:is_active: true,confirmed_at: 2026-06-10T08:17:01Z, no confirmation email required. - Deleted the old support@ alias (superseded by mailbox).
- Removed investigation-only forwarding from
[email protected]— sales@ is left untouched (forwardings: []).
Verified state (Proveo independent GET):
GET /v1/domains/bilko.cloud/mailboxes/support/forwardings
{"forwardings":[{"address":"[email protected]","confirmed_at":"2026-06-10T08:17:01Z","blocked_at":null,"is_active":true}]}
GET /v1/domains/bilko.cloud/mailboxes/sales/forwardings
{"forwardings":[]}
Migadu admin path (for future changes)
To modify forwarding: admin.migadu.com → bilko.cloud → Mailboxes → support → Forwardings. Do not use the Aliases section for external cross-domain targets.
3. Preflight Rollback Script
File: scripts/ops/bilko-support-fix-preflight.sh (committed at 67ed0ce5, PR #317, mode 100755)
What it does
- STEP 1 — Cloud SQL backup (write, skipped in dry-run): Takes an on-demand Cloud SQL backup of the Bilko DB before any deploy action. Provides a restore point.
- STEP 2 — Capture current Cloud Run revision (read-only always): Records the live revision name and image SHA for both
bilko-api-demoandbilko-web-demo. - STEP 3 — Print rollback commands (print only, never executes): Outputs the exact
gcloud run services update-trafficcommands needed to roll back to the captured revisions. These areecho-wrapped — they are never executed by the script.
How to run
# Dry-run (safe, no writes — use to confirm rollback targets before deploy)
bash scripts/ops/bilko-support-fix-preflight.sh --dry-run
# Live run (takes SQL backup, captures revisions, prints rollback cmds)
bash scripts/ops/bilko-support-fix-preflight.sh
Deploy-fragility rule enforced
All example re-deploy commands in the printed output use --update-secrets. The script documents and enforces: NEVER use --set-env-vars for Bilko Cloud Run deploys — it overwrites the Secret Manager binding and exposes secrets as plaintext environment variables.
4. Known Follow-up
| Item | Status | Owner |
|---|---|---|
| DEPLOY-MAP.md CF Email Routing section for bilko.cloud is stale (lists Cloudflare; MX is Migadu) | Open | John / next infra PR |
| PR #317 bundles MC #103323 application code (Sentry, SupportTickets, DB migrations V71+V72) — confirm separate QA validation for that scope | Open (Proveo advisory) | John |
| Merge PR #318 (smoke-test fix) before PR #317, or close #318 as superseded if #317 merges first | Open | John |
Created by Skillforge for MC #103325. Evidence: /tmp/evidence-103325/verification.md + /tmp/alai/p2p-pairing-evidence/proveo-multi-317-318-verdict.md. All facts machine-verified.
No comments to display
No comments to display