XtraDTF Alpha — internal runbook

Option B: Prove downstream Surface 1 end-to-end

Manual walkthrough — create a Surface 5 tenant, add a downstream public-film shop, run a referred embed order, and verify merchant-of-record payment, network fulfillment, and affiliate commission accrual.

Last updated: 2026-06-09 · Environment: alpha.xtradtf.com

Security note: This doc lists default alpha passwords and API keys for convenience. You said passwords have not been rotated yet. Rotate before any public partner onboarding.

What you are proving

Business ruleHow you verify it
Surface 5 tenant can own downstream Surface 1 Platform shows child under tenant; child has downstream_surface = public_film
Parent is merchant of record (MoR) Checkout on child embed uses parent mock payment account (DB: parent shop payment settings)
XtraDTF network root fulfills the job Order fulfillment_shop_id = xtradtf; job appears in Ops queue for xtradtf
Affiliate commission accrues on parent ledger Parent shop admin → Affiliates → ledger row after paid order
Referral code from URL flows to checkout Embed shows “Referral code … applied”; commission matches order total × affiliate %

Quick links & credentials

AppURLLoginPassword
Platform admin /platform/ platform@xtradtf.com ChangeMeOnFirstLogin!
Network root shop admin (xtradtf) /admin/ admin@xtradtf.com ChangeMeOnFirstLogin!
Production ops (xtradtf queue) /ops/ prod@xtradtf.com ChangeMeOnFirstLogin! (same seed)
Extranet (Surface 3 — not part of this walkthrough) /extranet/ Use extranet partner admin you create separately

Network root embed (reference)

Direct XtraDTF retail calculator (not used in Option B, but handy):

https://alpha.xtradtf.com/embed/?shop=xtradtf&key=b6d4e0747cb9463e18ad1dd202e1e19d36cff36f7d2b75e9

Active subscription plans (Platform → Plans)

PlanSlugPriceUse in this walkthrough
Surface 5 — Full Tenantfull-tenant$249/moParent tenant
Surface 3 — Extranet Filmextranet-film$249/moNot used here
Surface 4 — API/PODapi-podDeferred / inactive

Suggested test identities

Pick your own slugs if these are taken; keep them memorable.

RoleSuggested slugSuggested admin emailAdmin password
Surface 5 parent tenantacme-tenantadmin@acme-tenant.testAcmeTenant123!
Downstream Surface 1 childacme-retailadmin@acme-retail.test (optional)AcmeRetail123!
Affiliate codeacme-ref at 10% commission

Walkthrough steps

  1. Create the Surface 5 parent tenant

    Open Platform adminPartners & tenantsAdd partner.

    • Partner type: Surface 5 — Full tenant
    • Slug: acme-tenant (or your choice)
    • Display name: Acme Full Tenant
    • Legal business name: Acme Tenant LLC
    • EIN: any valid format, e.g. 12-3456789
    • Status: stays Trial on create (required)
    • Surface plan: Surface 5 — Full Tenant ($249)
    • Shop admin email: admin@acme-tenant.test
    • Shop admin password: AcmeTenant123!

    Click Create partner. New partners always start trial + EIN pending.

  2. Verify EIN and activate the tenant

    In Platform → Edit partner for acme-tenant:

    1. Click Verify EIN (sets manual verified).
    2. Set Shop status to Active.
    3. Click Save changes.

    You can verify EIN and activate in one save — partner profile updates run before status checks.

  3. Create downstream Surface 1 (public film)

    Still editing acme-tenant in Platform — scroll to Downstream accountsAdd downstream.

    • Surface: Surface 1 — Public film (parent branding)
    • Slug: acme-retail
    • Display name: Acme Retail Storefront
    • Brand display name (optional): Acme Heat Press Supplies — tests parent-facing brand label in API
    • Contact email: optional
    • Admin email/password: optional for this test

    Click Create downstream. Child starts in trial (embed may still work for xtradtf network fulfillment).

    Copy the child embed key: re-open the child in Platform (or parent downstream list) and note embed_api_key from shop detail. You need it for the calculator URL.

  4. Create an affiliate on the parent tenant

    Sign out of Platform. Open Shop admin and log in as the parent tenant:

    admin@acme-tenant.test / AcmeTenant123!

    Go to AffiliatesAdd affiliate:

    • Code: acme-ref
    • Name: Acme Referral Partner
    • Commission: defaults to 10% (set via API if you need a different rate)

    Ledger should be empty before the test order.

  5. Place a referred order on the downstream embed

    Build the child embed URL (replace CHILD_EMBED_KEY with the key from step 3):

    https://alpha.xtradtf.com/embed/?shop=acme-retail&key=CHILD_EMBED_KEY&affiliate_code=acme-ref

    Aliases also work: ?ref=acme-ref or ?affiliate=acme-ref.

    In the calculator:

    1. Confirm banner: Referral code acme-ref applied to this order.
    2. Upload a PNG design.
    3. Set dimensions / quantity; wait for quote.
    4. Checkout → fill shipping + email.
    5. Pay with mock card: 4242 4242 4242 4242 (any future expiry/CVC).

    Write down the order number (format XT-YYYYMMDD-XXXX).

  6. Verify affiliate commission (parent admin)

    Back in parent shop admin (admin@acme-tenant.test) → Affiliates:

    • Commission ledger should show a new accrued row for your order number.
    • Commission amount ≈ order total × 10% (rounded to cents).
    • Affiliate Accrued balance increases; Balance owed updates.

    Example: $22.97 order → $2.30 commission at 10%.

  7. Verify network fulfillment (xtradtf ops)

    Log into Ops as prod@xtradtf.com.

    The paid downstream order should queue on xtradtf printers (network root fulfillment), not on the child tenant’s empty printer list.

    Optional: xtradtf admin → Orders — you may see fulfillment-side activity depending on filters.

  8. Verify downstream order ownership

    Orders are stored with origin_shop_id = child (acme-retail). If you created a child admin user, log into child shop admin → Orders to see the order.

    Parent tenant admin does not list child-origin orders in the Orders tab today — that’s expected. Parent sees affiliate money; child sees the customer order.

SQL verification (optional, on server)

If you have SSH, these queries confirm MoR + fulfillment + affiliate in one glance:

sudo -u postgres psql -d xtradtf_alpha -c "
SELECT o.order_number,
       origin.slug AS origin_shop,
       fulfill.slug AS fulfillment_shop,
       o.total_amount,
       o.payment_status,
       o.original_quote->>'affiliate_code' AS affiliate_code
FROM orders o
JOIN shops origin ON origin.id = o.origin_shop_id
JOIN shops fulfill ON fulfill.id = o.fulfillment_shop_id
ORDER BY o.id DESC LIMIT 3;"

sudo -u postgres psql -d xtradtf_alpha -c "
SELECT c.order_number, a.code, c.commission_percent,
       c.order_total, c.commission_amount, c.status
FROM affiliate_commission_entries c
JOIN shop_affiliates a ON a.id = c.affiliate_id
ORDER BY c.id DESC LIMIT 3;"

Expect: origin_shop = acme-retail, fulfillment_shop = xtradtf, affiliate row on parent shop.

Automated smoke script (sanity check)

After your manual walkthrough, you can run the scripted smoke test (uses xtradtf embed + creates disposable partners):

php /var/www/alpha.xtradtf.com/scripts/smoke_network_stack.php

That script does not replace Option B — it hits a shorter path on the network root shop.

Success checklist

When something fails

SymptomLikely cause
Embed “Missing embed key”Wrong key= in URL; copy from Platform shop detail
Cannot activate tenantEIN not verified first
No “Add downstream” sectionParent is not full_tenant type
Referral banner missingInvalid code format; must be 2–32 chars a-z, 0-9, hyphen
No ledger entry after payAffiliate created on wrong shop (must be parent), or code mismatch
Ops queue emptyProduction job still pending; check cron or run php scripts/process_production_jobs.php --once

What comes after Option B

See also: Platform vision