I found my postback secret leaked but could not rotate without downtime — thMenu dual-secret overlap (PR #609 CCC-B)
Lloyd Birmingham Jewellery Quarter 35-yo 6-yr freelance growth-marketing consultancy custom commission-tracking SaaS UK + Ireland thMenu affiliate handle lloyd-grow built Linear-integrated postback receiver early 2025 HMAC-SHA256 signed POSTs Cloudflare Worker verify signature n8n flow writes Linear row each new commission 14 months clean. Monday offboarding contractor Anand 3-month engagement parallel client Anand VPN access Lloyd dev environment .env file thMenu postback signing secret. Lloyd froze. Anand 24 hours cached access secret likely sahte POST forge Linear receiver fake commission rows ROI distortion downstream confusion. Lloyd thMenu affiliate dashboard Rotate Signing Secret button. Old rotate UX You must delete current secret then new one generated created problem moment Lloyd delete dispatcher stop signing old start new but Linear receiver still old until receiver updated 5-10 minute gap window every postback HMAC-verify-fail dropped silent gaps Lloyd commission audit trail. Lloyd email support old secret leak delete-then-create gap window can't update receiver without dropping postbacks better flow. Engineering rotation problem known webhook_subscriptions PR #563 batch SS-B dual-secret rotation pattern shipped. webhook_subscriptions.signing_secret_prev TEXT NULL + secret_rotated_at + partial index + dispatcher dual-sign 7-day overlap + algorithm-negotiation header Stripe / GitHub / Slack canonical. But affiliate postback secret affiliate_profiles.postback_secret not covered sibling-surface coverage gap. Two paths (1) immediate workaround manually generate new secret + dispatcher dual-sign both old + new 7-day window null old after ship pattern permanent; (2) permanent fix mirror SS-B pattern webhook_subscriptions over affiliate_profiles schema migration + dispatcher dual-sign + prune cron + algorithm-negotiation header. PR #609 batch CCC-B shipped Supabase migration 20260523000006_affiliate_postback_secret_rotation.sql ALTER TABLE affiliate_profiles ADD postback_secret_prev TEXT NULL + postback_secret_rotated_at TIMESTAMPTZ NULL + idx_aff_postback_prev_secret_rotated WHERE postback_secret_prev IS NOT NULL. Dispatcher cloudflare/src/lib/affiliate-postback-dispatch.ts 7-day overlap every postback signed both primary + previous secret primary X-thMenu-Signature raw hex backward-compatible previous sibling header X-thMenu-Signature-Previous overlap window X-thMenu-Sig-Algorithm: sha256 future SHA-512/Ed25519 negotiation receivers match either signature. Rotate endpoint new POST /api/affiliate/postback/rotate-secret CSRF token + affiliate guard + OCC race-guard atomic UPDATE postback_secret_prev = postback_secret postback_secret = ? postback_secret_rotated_at = now WHERE affiliate_id = ? AND postback_secret = ? concurrent loser 409 rotation_race. New secret returned once cleartext UI affiliate shown hash stored. Prune cron daily 04:00 UTC postback_secret_rotated_at < now - 7 days NULL Supabase REST PATCH naturally idempotent. Lloyd hit Rotate new secret cleartext UI banner Rotation window 7 days old secret remains update receiver. Lloyd copied .env restart Cloudflare Worker next 5-10 minutes postbacks both old + new receiver new verify also old overlap valid no drops 7 days later prune cron null old Lloyd exclusively new dispatcher only new transition seamless 0 commissions dropped. Lloyd blog Stripe-style dual-secret rotation less than day 0 commissions lost operational hygiene 3.8k. Berk Erzurum Ataturk Universitesi @berk-perf 7-yr Performance Marketing Turkish SaaS + restoran zinciri Notion + n8n + Cloudflare Worker contractor .env screen parallel ticket rotation seamless 1-month Pro credit + Hall of Fame. Pattern HMAC-signed integration surface delete-then-create rotation anti-pattern canonical schema secret + prev_secret + rotated_at + dispatcher dual-sign 7-day overlap + receivers both + prune cron prev NULL window + algorithm-negotiation header. Sibling-surface coverage webhook_subscriptions PR #563 SS-B + affiliate_profiles.postback_secret PR #609 CCC-B + Stripe Stripe-managed + Wise single-secret brief downtime + OAuth refresh PR #526 HH + future Coinbase. Implementation checklist schema secret+prev+rotated_at + partial index + dispatcher dual-sign overlap primary+sibling header + algorithm-negotiation header + rotate endpoint atomic OCC race-guard + secret ONCE cleartext + UI banner 7 days + daily prune cron + audit-log rotation event + sibling-surface sweep. PR #609 reference.
thMenu Team
thmenu.com
Found this helpful? Share it.
Related articles
Why Digital Menus Increase Restaurant Revenue by Up to 30%
Studies show restaurants using digital QR menus see measurable increases in aver…
When a Customer Downgrades, What Happens to Old Features? — The Silent Feature-Drift Problem in SaaS
Most SaaS apps run a single line of code when a customer downgrades — but old fe…
JWT alg-confusion attack — why Supabase's HS256 → RS256/JWKS migration breaks legacy verifiers
Verifiers that never decode the JWT header are wide open to `alg=none` and alg-c…