A dual-run migration between payment processors. Seven reviewers.
The migration design has material security, integrity, and cutover-control gaps that block safe live vault transfer and writer cut-over. The board agrees on the risks but disagrees on whether a short or longer dual-run best manages them; the duration requires an owned, evidence-based decision.
The vault-to-vault API lacks documented schema/version controls, validation, audit logs, and 1:1 token mapping or checksum reconciliation. Generic PCI Level 1 evidence does not validate this high-impact migration path.
Raised by API and Integration Architect
No migration-API-scoped penetration evidence, right-to-audit exercise, or mandatory Security go/no-go is defined before moving 54,300 live cards.
Raised by Security and Reliability Reviewer
Reverse transfer support and drills are not evidenced. Partial state failures, pending Ridgeline cancellation, retries, and post-transfer charge failures can cause orphaned, unbillable, or dual-billed subscriptions.
Raised by Principal Software Architect
A 10-week versus 3-week dual-run dispute remains open with no decision owner, threat model, acceptance record, credential segregation/rotation plan, or measurable exit criteria.
Raised by AI Governance and Evaluation Reviewer
The 48-hour dedup design lacks late-event reconciliation and idempotency details. Phase 4 still lacks Security, Finance, and Support approvals; acceptance metrics and revenue-reporting controls are incomplete.
Raised by Product Delivery Lead
Majority view: Dual-run duration must be explicitly risk-assessed and governed before approval.
Majority view: Security exposure is material, but an unvalidated compressed rollout may create unacceptable operational risk.
This review assesses the API integration design for live payment-vault migration and writer cut-over. At 42/100, it is not safe to approve: material gaps in transfer integrity, migration security assurance, rollback readiness, and cutover governance could compromise 54,300 live cards and payment continuity.
A score of 42/100 means the document has serious deficiencies that prevent confident execution of the proposed migration. If these controls fail, the organisation risks orphaned or unbillable subscriptions, duplicate billing, failed charges, revenue-reporting errors, and uncontrolled exposure across PCI-relevant integrations.
There is disagreement over dual-run duration: Ops/Support favours a longer gradual rollout to preserve cohort rollback flexibility, while Security favours roughly three weeks to reduce duplicated PCI-relevant integrations and credential exposure. The duration cannot be approved on preference alone because either choice creates material but different revenue, reliability, and security exposure.
Document owner: Staff Engineer, Payments Platform
Status: Approved for Phase 0–2 (dual-run infrastructure); Phase 4 (writer cutover) pending Security, Finance, and Support sign-off
Last updated: 2026-07-30
Audience: Payments Platform, Finance, Security, Support Operations, Engineering Leadership
Related tickets: PAY-2210 (reserve hold dispute with Ridgeline), PAY-2244 (Corvant underwriting approval), FIN-880 (deferred revenue continuity), SEC-514 (PCI scope re-assessment)
Tenfold is Hollowbrook, Inc.'s subscription workforce-scheduling product for hourly-shift businesses — retail, quick-service restaurants, and healthcare staffing agencies. We currently have 54,300 active paying accounts, $61.2M in ARR, and card-on-file billing only (no bank debit). 71% of accounts are on monthly plans; the remaining 29% prepay annually, which currently sits on our balance sheet as $8.9M of deferred revenue. All billing today runs through Ridgeline Payments, who we signed with at seed stage in 2021 because they were the only processor willing to underwrite an unproven SaaS company with no processing history.
Two things are forcing this migration rather than letting it sit on the backlog:
Corvant has approved us for a dedicated underwriting profile (not a shared pool), offers network tokenization, a lower blended rate (2.7% + $0.30 versus Ridgeline's 3.1% + $0.35), and — critically for this plan — a documented vault-to-vault credential migration API that moves stored payment methods directly between processors without the PAN ever transiting Hollowbrook's servers.
This document covers the dual-running strategy, how we move 54,300 live subscriptions and their stored credentials, the PCI DSS scope changes, webhook and reconciliation handling, the cutover sequence, the rollback plan, and how Finance keeps continuous revenue reporting across the boundary. This is a one-way door in the specific sense that once a customer's card has been migrated and their subscription's renewal authority has moved to Corvant, un-migrating them means re-vaulting through the same bulk transfer process in reverse — not a config flip. We are treating the per-cohort cutover as reversible up to that point and effectively irreversible after.
Ridgeline hosts our card vault (we never store raw PANs — we hold
Ridgeline's tokenized payment method references, format
rl-pm-<20 hex>) and owns subscription lifecycle:
billing cycle dates, retry/dunning schedule on failed payments, and
invoice generation. Our application calls Ridgeline's API to
create and modify subscriptions; Ridgeline calls our webhook
endpoint on billing events (invoice.paid,
invoice.payment_failed,
subscription.canceled, card.updated). Our
billing service consumes those webhooks to update account
entitlement (feature access, seat counts) and forwards normalized
events to the Finance data warehouse for revenue recognition.
Ridgeline's dunning logic retries a failed card charge on a fixed schedule: day 1, day 4, day 8, then cancel. This schedule is not configurable per account and is not adaptive to decline reason (a hard decline like "stolen card" gets the same three retries as a soft decline like "insufficient funds," which wastes retry attempts and, per some published research on retry timing, mildly increases the odds of a dispute on hard-decline cases where the retries look like unauthorized charge attempts to the cardholder).
Corvant's subscription and vault model is broadly similar in
shape — tokenized payment method references (format
cv-pm-<uuid>), webhook-driven lifecycle events,
hosted-fields card capture — which is what makes a fairly direct
migration feasible rather than a rebuild. The meaningful
differences: Corvant's dunning is decline-reason-aware (soft
declines get up to 4 retries over 12 days; hard declines get 1 retry
then immediate cancellation, reducing dispute-triggering retries),
and Corvant supports network tokenization so card references
self-heal on reissue without customer action.
We are not changing our subscription tiers, pricing, or billing cadence as part of this migration — this is a processor swap, not a pricing project. Scope is deliberately narrowed to keep the blast radius to "how money moves," not "what customers pay."
We will run both processors live simultaneously for the duration of
the migration, rather than a single hard cutover for all 54,300
accounts at once. Every subscription record in our billing service
gets a new field, renewal_authority, set to either
ridgeline or corvant. The routing layer
consults this field on every billing-relevant action — a renewal
charge, a plan change, a cancellation — and directs the call to the
corresponding processor's API. Only one processor is ever
authoritative for a given subscription's renewal at a time;
there is no dual-charging by design, enforced by the fact that
Ridgeline subscriptions are explicitly canceled (not just left
dormant) at the moment a cohort's authority moves to Corvant.
```yaml
routing:
default_authority: ridgeline
cohort_overrides:
authority: corvant
accounts: ["acct_8841", "acct_8842", "acct_8850"] # 12 internal test accounts
authority: corvant
criteria:
plan_type: monthly
dispute_history: none
tenure_days_min: 180
target_start: 2026-08-11
webhook_dedup_window_seconds: 172800 # 48h idempotency window, both providers
freeze_on_migration: true # blocks writes during a subscription's flip window
```
This is where the first real disagreement in this plan sits, and we want to name it rather than bury it. The dual-run window — the period where both processors are live and some fraction of subscriptions is on each — is currently scoped to run 10 weeks (Section 8). A gradual, cohort-by-cohort rollout is the right call operationally: it lets us catch integration bugs against a small blast radius, gives Support time to build muscle memory on two sets of processor error codes, and gives us a real rollback path per cohort instead of an all-or-nothing bet. That is the case Ops and Support leadership have made, and we agree with it.
Security's position, raised in SEC-514 review, is that every week the dual-run window stays open is a week we are maintaining full PCI DSS scope against *two* processor integrations, two webhook signature-verification paths, two sets of API credentials with card-data-adjacent permissions, and two vaults of live customer cards instead of one. A 10-week gradual rollout is, from that angle, 10 weeks of doubled attack surface in exchange for rollback convenience. Security's counter-proposal is a compressed 3-week window with larger cohorts. We have not resolved this. The plan as written goes with Ops' 10-week gradual schedule because the rollback value feels concrete and the incremental security exposure feels diffuse, but we recognize that is exactly the kind of reasoning that looks bad in hindsight if the diffuse risk is the one that materializes, and we think this genuinely deserves an independent read rather than a Payments Platform judgment call.
We are not asking customers to re-enter card details. Re-prompting 54,300 accounts for a fresh card would predictably cost us real revenue — every additional friction point in a re-auth flow measurably increases lapse rates in every dunning study we've seen internally and externally — and would defeat a large part of the point of switching to a processor with better retention tooling in the first place.
Instead we're using Corvant's vault-to-vault migration
API. The mechanics: Ridgeline and Corvant both support a
processor-initiated bulk transfer where Ridgeline encrypts and
transmits the underlying card data directly to Corvant's vault
over a dedicated, mutually authenticated channel, keyed by a
merchant-authorization token we generate per batch.
Hollowbrook's servers send and receive only the token
references (rl-pm-... in, cv-pm-... out) —
never the PAN, never even transiently. This preserves our SAQ A
eligibility (Section 6) because the card data path never enters our
environment; it moves processor-to-processor under an agreement both
providers are independently attesting to.
```
Migration batch record (internal schema, illustrative)
subscription_migrations
id uuid primary key
account_id text not null
rl_subscription_id text not null -- Ridgeline subscription reference
rl_pm_ref text not null -- Ridgeline tokenized payment method
cv_subscription_id text -- null until created
cv_pm_ref text -- null until vault transfer completes
cohort text not null
status text not null -- queued | vault_transferred | subscription_created
-- | reconciled | flipped | rolled_back
next_renewal_at timestamptz not null -- carried over unchanged from Ridgeline
requested_at timestamptz not null
completed_at timestamptz
failure_reason text
```
Two properties of this schema matter. First,
next_renewal_at is copied verbatim from the Ridgeline
subscription and never recalculated — we do not want a migrated
customer's bill date to shift by even a day, since an
unexpected charge-date change is one of the most common triggers for
"I don't recognize this charge" disputes. Second,
status is a strict forward progression with
rolled_back as the only exit that isn't
reconciled/flipped; there is deliberately
no partial state where a subscription is simultaneously chargeable
from both sides.
The open disagreement here is about verification, not mechanism. Both Ridgeline and Corvant are PCI DSS Level 1 certified merchants and service providers, and our current plan treats that attestation as sufficient grounds to proceed with the bulk vault transfer without additional technical controls beyond the mutually authenticated channel both vendors provide by default. A more conservative position — one a security reviewer is likely to hold — is that "both parties are Level 1 certified" describes their general compliance posture, not this specific one-time bulk transfer mechanism, which is a less commonly audited code path than day-to-day transaction processing at either company. Under that view, we should be requiring Corvant to produce transfer-specific evidence (a recent penetration test report scoped to the migration API, or a right-to-audit clause invoked before go-live) rather than accepting their compliance program's general reputation as proof this specific pipe is sound. We have not requested that evidence as of this writing; Legal has the vendor agreement and has not flagged it as a gap, but Legal was not asked the question in those terms.
Hollowbrook's SAQ A scope depends on card data never touching our systems in any form — we use hosted fields (an iframe served by the processor) for card capture today, and will continue to for both providers during and after the migration. That does not change. What does change, temporarily, is the number of PCI-relevant integration surfaces we operate: