tellatribe

Enter the access code to read the project documents.

tellatribe Docs Status: All modules built and live · Oct 19: Creator Campaigns Part B shipped (briefs, applications, deals, verification → bounties, brand balance + Stripe funding, disputes, reports) on top of the tax-identity gate and annual statements · awaiting owner inputs: tellatribe Stripe account (payments + Connect + funding webhook), HealthyApp webhook secret, Ayrshare key

Build tracks · build-plan/03-reconciliation-and-surfaces.md

03 — Reconciliation and Surface Inventory

Build plan section 3 of n · tellatribe · 2026-10-03 Inputs: PRODUCT.md (confirmed truth), PRD.md v0.1 (authoritative requirements), PRD-Activation-Platform.md v1.1 (commercial vision, pending reconciliation — this document is that reconciliation). Precedence: PRODUCT.md and PRD.md win every conflict with PRD-Activation-Platform.md. Direction: internal first, commercial-shaped. The structure must survive the pivot to a sellable multi-tenant SaaS; the feature set does not have to.

Three confirmed truths used as hard filters below:

Truth Source Effect on reconciliation
Two levels, permanently PRD §2.1, §5.2, §11.3; PRODUCT.md Anything implying depth, ranks, volume qualification or breakaways is Out
No fee to an affiliate, ever PRD §2.1, §11.1 Any affiliate-facing billing is Out; merchant-facing billing is a hook that stays empty
Admin success is absence PRD §1, §10, §14; PRODUCT.md principle 5 Any feature whose value requires a recurring admin login (approval of drafts, recommendation review, browsing dashboards) is Out or demoted to a report

Part A — Reconciliation

A.1 Requirement-by-requirement table

Verdict key:

  • As-is — in v1 as written (possibly under a different name).
  • Reshaped — in v1 in a smaller or different form; the "how" is stated.
  • Deferred/arch — not in v1, but a v1 architectural decision must leave room; the decision is stated.
  • Deferred — not in v1, purely additive later, nothing to decide now.
  • Out — conflicts with confirmed product truth; the reason is stated.

Priorities (P0/P1) are the Activation PRD's and are listed only so the team can see where the two documents disagree on what is core (notably: Mode 2 publishing is P1 there and v1-core here; Stripe payouts are P1 there and v1-core here).

§7.1 Workspace, onboarding, program setup

ID Activation requirement (short) Pri Verdict Disposition
ONB-01 Workspace creation for merchant / agency / network admins; tenant-isolated P0 Deferred/arch Create a workspaces table with exactly one row. Every tenant-owned table carries workspace_id NOT NULL; RLS reads it. No workspace creation UI, no agency/network types, no data region. See checklist A.2 #1.
ONB-02 Guided first-program builder from business-type templates P0 Deferred/arch Programs are rows (PRD §5.1), never constants. Defaults live in one program_defaults seed object — that object is the template in embryo. No wizard, no template picker; the admin Program form is the v1 builder.
ONB-03 Recommended defaults for tracking, attribution, fraud, disclosure, maturity, each explained P0 Reshaped Program form ships PRD defaults (30-day hold, $50 minimum, 90-day window, last-click + customer lock) with a one-line "why this default" beside each field. "Persist the selected policy version" is already satisfied by PRD §5.1 (plan level in force at conversion pays) and §11.4 (versioned terms).
ONB-04 Integration health check and sandbox test conversion before activation P0 Reshaped An integration panel on the Program screen: API key, redirect-route snippet, Stripe webhook endpoint, last click received, last webhook received, and a test-mode conversion button. Directly serves PRD §14 "new product integrates in under a day." This is the one admin element in Part B not literally in PRD §10; it is pulled forward deliberately.
ONB-05 Migration import of partners, links, historical conversions, assets, payout balances P1 Deferred for partners/links/assets (additive CSV). Out for payout balances An imported balance would be a commission row with no conversion_id, which PRD §5.3/§11.2 forbids by schema constraint. If a legacy balance is ever needed it enters at the payout layer as an adjustment on a payout, never in commissions.

§7.2 Partner recruitment, identity, network access

ID Activation requirement (short) Pri Verdict Disposition
PRT-01 Branded application/invitation flows with configurable fields, eligibility questions, approval steps, invite expiry; magic-link accept P0 Reshaped One signup flow: recruiting link carries the sponsor code; affiliate claims a referral code; accepts a specific terms version. Magic link via Supabase Auth. Build the pending_approval enrollment state and its queue item regardless of the gated/open decision (D.1), so gating is a program toggle, not a build. Configurable form fields, eligibility questions: deferred, no arch impact (a JSONB column later).
PRT-02 Portable partner profile across programs; each merchant sees only authorized fields P0 As-is within one workspace (PRD §5.2: one affiliate globally, per-program enrollment rows). Deferred/arch across workspaces Decide now: auth.users is platform-level; affiliates is workspace-scoped (one row per person per workspace); affiliate_programs is the enrollment inside the workspace. Cross-merchant portability later = one auth user, several affiliate rows. Do not make affiliates a global table without workspace_id. See A.2 #1.
PRT-03 Partner segmentation and tags (status, channel, location, performance, risk, custom tags) P0 Reshaped (minimal) / Deferred v1 targeting exists only where PRD §9.3 needs it: assets restricted by program or by performance threshold. Tags, channel, location: deferred, additive table.
PRT-04 Opt-in vetted marketplace and direct recruitment P1 Deferred PRD §4 names marketplace out of v1. Additive flag later; no v1 decision required.
PRT-05 Partner education in the campaign workflow; acknowledgements gate packs when configured P1 Reshaped v1 = the plain-English "what you may and may not claim" page (PRD §9.3) acknowledged once at signup with the terms. Per-asset gating: deferred, no arch impact.

§7.3 Enablement Hub (collateral → activation)

ID Activation requirement (short) Pri Verdict Disposition
ENB-01 Campaign-centred asset library with type, owner, locale, channels, offer, dates, rights, approval, version P0 Reshaped + Deferred/arch v1 assets are per-product, categorised, versioned, targetable (PRD §9.3). No campaign object. Arch: assets.product_id plus nullable program_id; the vault's grouping is data-driven, not a hardcoded product tab list, so a later "campaign" grouping is one more column. Do not name the link's free-text label campaign_id.
ENB-02 Ingest files, URLs, product feeds, copy blocks, templates; validate; malware-scan P0 Reshaped Upload image/video/document, copy blocks, scripts; type/size validation. Product feeds: Out of v1 (no ecommerce product). Malware scan: deferred, storage-hook, no arch impact.
ENB-03 Channel-ready creative variants with source/version linkage P0 Reshaped + Deferred/arch PRD Mode 1 requires correct aspect ratios per platform; Mode 2 requires per-network rendition. Arch: asset_versions → asset_renditions(platform, placement, file) from day one rather than one file per asset.
ENB-04 Activation Packs per channel as an immutable snapshot of what was presented P0 Reshaped The v1 "pack" is a token-rendered asset + caption + disclosure + the affiliate's link, taken by one of three modes. Record every take as an asset_uses row: asset_version_id, link_id, affiliate_id, mode (copy/download/publish/record), platform, created_at. This is the pack's ancestor, the source of PRD's usage count, and the data behind the affiliate's own used/posted marks on the vault.
ENB-05 Partner-specific tracking outputs inside packs (link, deep link, coupon, sub-ID, QR) P0 As-is for link/deep link/QR/short link via tokens (PRD §9.3). Out for coupon PRD §4 excludes coupon attribution in v1. Sub-ID = the link's campaign label.
ENB-06 Enforce visibility, rights, expiry, approval; mark affected packs "update required" P0 Reshaped + Deferred/arch v1: versioning plus program/threshold restriction. Arch: asset_versions.status (draft/active/retired) and nullable expires_at from day one; because asset_uses references the version, "which affiliates took the stale one" is a query later, not a migration.
ENB-07 Compliant claims/disclosure modules; pack cannot be ready until acknowledgement recorded P0 As-is for disclosure on every asset + claims page (PRD §9.3, §11.5–6). Out for per-pack acknowledgement A gate before every copy contradicts principle 4 (collateral is finished work; each rung removes a reason to stall). One acknowledgement at signup.
ENB-08 Co-branding / limited personalisation via approved merge fields P1 As-is PRD tokens {{ref_link}} {{short_link}} {{affiliate_name}} {{product_name}}. Logo merge field: deferred, one more token.
ENB-09 Content approval workflow (submit draft/proof/URL; reviewer approves) P1 Out Requires a human in the loop on every post — the daily login the product exists to eliminate. The Mode 2 "exactly what we will post" preview is the affiliate's own check, not an admin gate.
ENB-10 Attribute pack/asset use through to clicks, conversions, commission, reversal rate P0 Reshaped + Deferred/arch PRD §10 Reports: collateral usage vs revenue. Arch: clicks must carry link_id, not only ref_code, and asset_uses must carry link_id; otherwise asset-level revenue is unrecoverable later. When an affiliate takes an asset, the embedded link is the affiliate's default link for that product with the asset slug recorded on the asset_uses row and passed as the campaign label, so the chain asset → link → click → conversion → commission exists without the affiliate building anything.
ENB-11 Partner content calendar; expiry/deadline/new-kit notifications in partner's timezone P1 Reshaped v1 = "new since your last visit" badge + new-collateral email (PRD §9.3, §9.6) + the affiliate's own Mode 2 publish queue (scheduled posts). A campaign calendar: deferred.
ENB-12 Graceful retirement: replacement / revoke / grace period; detect affected packs P0 Reshaped v1: new version supersedes, old version retired. Detection of affected published items: deferred, enabled by ENB-06 arch.

§7.4 Tracking and attribution

ID Activation requirement (short) Pri Verdict Disposition
TRK-01 First-party conversion tracking via SDK/pixel and server-side, idempotent, consent-aware P0 As-is (server-side) / Deferred (pixel) PRD §6: /r/[code] on the product domain, S2S conversion API, Stripe webhook path, idempotency key required. Pixel: deferred, no arch impact; PRD §2.2 makes server-side primary on purpose.
TRK-02 Links, direct links, deep links, coupons, QR, sub-IDs; enable/disable per program P0 Reshaped Links, deep links, QR, short link, campaign label in v1. Coupons: Out of v1 (PRD §4). Per-program method toggles: deferred, no arch impact.
TRK-03 Plain-language attribution presets plus advanced rule builder with multi-touch simulator P0 Reshaped (one preset) / Out (rule builder, multi-touch) PRD §6.5 fixes last-click-wins within a per-program window plus customer lock on first conversion. A rule builder is the enterprise administration burden the Activation PRD's own §14 warns against, and multi-touch is incoherent with customer-locked recurring commissions. The window is already per-program; nothing more to shape.
TRK-04 Attribution explanation for every conversion (candidates, rule version, winner, calculation) P0 Reshaped Pulled forward. Admin: conversion detail shows click → code → affiliate, customer_attribution lock, program/plan level in force, flags tripped. Affiliate: commission detail shows amount basis, level, state, and the payable-on date. There is only ever one candidate, so no "excluded candidates" list.
TRK-05 Reconcile cancellations, refunds, subscriptions, upgrades, chargebacks, offline/imported conversions P1 As-is (refund/chargeback/recurring via webhooks; voided/reversed states). Deferred (imported) PRD §6.4, §7.3. Upgrades are just invoice.paid amounts. Offline conversions already have a path (S2S API) — nothing to add.
TRK-06 Webhooks and REST APIs with scoped credentials, versioning, idempotency, rate limits, docs P1 Reshaped (inbound) / Out (outbound) Inbound /v1 API with per-product scoped keys and idempotency is v1 (PRD §6.3, §12). Outbound webhooks to products conflict with "products call it; it never calls them" (PRODUCT.md). If a future merchant demands them it is an additive webhook_subscriptions table. Rate limits: deferred, edge-level.

§7.5 Commissioning, payments, finance

ID Activation requirement (short) Pri Verdict Disposition
PAY-01 Commission templates: percent, flat, recurring share, new-customer rate, one-time bonus P0 As-is (percent/flat/recurring via plan_level.kind/basis/recurring_months). Deferred (bonus) "New-customer rate" is the first_payment basis. A volume bonus (PRD §4 allows one) must still attach to a conversion_id — the conversion that crossed the threshold — or it violates the structural guard. Not in v1; see D.7.
PAY-02 Rules by product, category, customer status, channel, partner group, geography, coupon, date; conflict detection; test calc P1 As-is (by product, by date) / Out (the rest) Program-per-product and program-in-force-at-conversion cover product and date. Category/channel/geo/group/coupon rules are the administration burden PRD §1 rejects. The pure commission engine (PRD §12) can take richer rules later without a rewrite — that is the only accommodation, and it is already required.
PAY-03 Immutable ledger: earn, pending, approved, held, reversed, paid, adjustment; linked to events and policy versions; exportable P0 As-is PRD §7. Name mapping: Activation "held" = PRD pending inside hold_days (plus flagged for manual holds); "adjustment" = a negative row pointing at its parent. One gap: PRD lists no manual transition into flagged for an already-pending commission. See D.5.
PAY-04 Configurable maturity/approval/payout schedules; partner sees exact status, next eligible date, reason P0 As-is PRD §5.3 hold_days, §8 monthly run, §9.1 balances by state with next payout date. Make the per-row "payable on" date and the reason ("30-day refund window") visible on the commission row — PRODUCT.md calls the hold period affiliate-visible.
PAY-05 Payment-provider integration plus controlled exports P1 As-is Stripe Connect Express primary, PayPal secondary, CSV escape hatch (PRD §8). Failed payouts return rows to approved.
PAY-06 Tax/payment onboarding via processor; completeness state; gates payout P1 As-is Stripe hosted onboarding owns KYC/1099 (PRD §2.5, §8). Payout run skips and notifies the un-onboarded.

§7.6 Fraud, policy, trust

ID Activation requirement (short) Pri Verdict Disposition
RSK-01 Default risk policies: self-referral, duplicate attribution, coupon leakage, velocity, suspicious signups, restricted traffic; adjustable with false-positive note P0 As-is for the PRD §7.4 six (self-referral, duplicate customer, 2+ chargebacks/30d, refund rate, click-to-convert speed, IP volume). Out coupon leakage. Deferred restricted traffic sources Thresholds are program/workspace config with a one-line consequence note, consistent with ONB-03.
RSK-02 Explainable case queue: evidence, score, related events, recommended action, prior decisions, approve/hold/reject with reason P0 As-is (reshaped detail) This is the PRD §10 exceptions queue. v1 rules are boolean, so there is no score; show which rules tripped and the evidence. "Prior decisions" = this affiliate's audit-log entries.
RSK-03 Terms acknowledgement; violation register with evidence, corrective action, appeal P0 As-is (terms, PRD §11.4) / Deferred (violation register) Suspend-with-reason, audited (PRD §10) covers v1. A structured register and appeal flow is additive.
RSK-04 Append-only audit log for sensitive actions P0 As-is PRD §12 audit_log. Must cover: reparent, suspend, manual commission state change, program rate change, API key create/revoke, payout release, admin view-as.

§7.7 Reporting and operating cockpit

ID Activation requirement (short) Pri Verdict Disposition
RPT-01 Role-specific "Today" dashboards: operator action queue, partner work/earnings, finance payables P0 Reshaped Admin home is the exceptions queue (PRD §10) — that is Today. Affiliate home is a what-happened / what's-next board, not stat cards (fits the chosen "Board" direction). A finance role does not exist in v1.
RPT-02 Program/partner/campaign/channel/asset dashboards with consistent definitions and drill to ledger P0 Reshaped PRD §10 Reports: revenue by affiliate/product/level, cohort retention, collateral usage vs revenue, liability outstanding. Every figure drills to its ledger rows. No channel/campaign cuts in v1.
RPT-03 Custom reports, saved views, CSV/API exports with definitions P1 Deferred v1 exports: affiliate statements, payout-run CSV, ledger CSV. Saved views additive.
RPT-04 Activation funnel: invited → approved → onboarded → opened → pack created → published → clicked → converted → paid P0 Deferred/arch Emit the events now, build the report later. PRD §14's own success criteria ("median affiliate visits the vault within 48h and posts something") cannot be measured without signed_up, code_claimed, link_created, link_copied, asset_used(mode), first_click, first_conversion, payout_onboarded, first_paid. One events table, append-only, from day one.
RPT-05 Recommended next actions with evidence; dismissible; never auto-alter money P1 Deferred Recommendations are things an admin logs in to read. Automated affiliate nudges (email on new collateral, PRD §9.6) do the useful part without the admin.

§7.8 Integrations (no IDs in source; labelled by class)

Class Activation P0 / P1 Verdict Disposition
INT-Ecommerce Shopify + generic (P0); Woo/BigCommerce/Adobe/feeds (P1) Deferred No ecommerce product in the portfolio. The generic S2S conversion API is the adapter; a Shopify app is additive.
INT-Billing Stripe + generic subscription events (P0); Paddle/Chargebee/Recurly (P1) As-is (Stripe) PRD §6.4. Scope the webhook to platform revenue only for HealthyApp — never Connect tenant charges.
INT-Marketing CSV + link-compatible email (P0); Klaviyo/Mailchimp/HubSpot/Salesforce/social publishing (P1) Reshaped Social publishing is v1-core here (Mode 2), not P1. Email/CRM connectors: deferred.
INT-Payments CSV export (P0); processor orchestration (P1) As-is, inverted Stripe Connect is v1; CSV is the escape hatch.
INT-Identity Magic link + MFA for staff (P0); SSO/SAML/SCIM, custom domains, retention controls (P1) As-is (magic link; admin MFA) / Deferred/arch (custom domains) Admin MFA is cheap and sits on the money boundary — ship it. Custom portal domains: resolve the workspace from the session, never from the URL, so a subdomain-per-workspace later is a routing change only (A.2 #6).

Activation PRD §8–§10 (IA, permissions, data model) — handled in A.2

Summary of the name mapping so the team reads both documents without translating twice:

Activation PRD object v1 table(s) Note
Workspace workspaces One row in v1
Program programs, plan_levels As PRD §5.1
Partner identity auth.users + affiliates User is platform-level; affiliate is workspace-scoped
Enrollment affiliate_programs Carries approval state and accepted terms version
Campaign — No v1 object. Free-text label on links
Asset assets, asset_versions, asset_renditions PRD lists only assets; versions and renditions are additions this document requires
Activation Pack asset_uses Replaces PRD's asset_views; records mode, version, link
Tracking output referral_codes, links PRD lists referral_codes but per-link performance (§9.2) needs a links row
Touchpoint / conversion clicks, conversions, customer_attribution As PRD §6
Commission ledger entry commissions As PRD §7
Payout batch payout_runs, payouts, payout_items PRD lists payouts/payout_items; the run itself needs a row
Risk case queue view over commissions.state = flagged, payouts.state = failed, negative balances, affiliate_programs.state = pending_approval No separate table in v1; the queue is a query
Audit event audit_log As PRD §12
(not in Activation PRD) social_accounts, publish_jobs, recordings Required by PRD §9.3 Modes 2 and 3; absent from PRD §12's table list, which predates the Oct 3 §9.3 update

A.2 The "commercial-shaped" checklist

Decisions that must be made in Phase 1 (Ledger) and Phase 2 (Tracking) so the SaaS pivot is a feature project, not a rewrite.

# Decision Do in v1 Do NOT build yet Cost of getting it wrong
1 Tenancy boundary workspaces table, one seeded row. workspace_id NOT NULL FK on products, programs, affiliates, affiliate_programs, links, clicks, conversions, customer_attribution, commissions, payouts, payout_runs, assets (+versions/renditions/uses), social_accounts, publish_jobs, recordings, events, audit_log, api_keys. One current_workspace_id() SQL helper that every RLS policy uses. Composite uniques include workspace_id — except referral_codes.code, which is globally unique because go.tellatribe.com/CODE is one shared short domain. Partition clicks/conversions by month with workspace_id as a leading index column. Workspace switcher, workspace creation, agency/network workspace types, data region, plan tiers. clicks and conversions are the hottest, partitioned, never-updated tables (PRD §12). Adding a column and rewriting every RLS policy on them after launch is the single most expensive retrofit in the system, and the RLS boundary is "the highest-consequence security boundary" (PRD §12).
2 Roles and permissions Two roles: owner and affiliate. Model as workspace_members(user_id, workspace_id, role) even with one row. Authorise through one can(actor, action, resource) helper, never if (role === 'admin') scattered in components. Admin "view as affiliate" is a server-side read-only context flag, written to audit_log. Admin MFA on. Program manager, creative manager, finance approver, compliance reviewer, agency manager, partner team member; dual approval; step-up auth; partner organisations with members. Authorization sprinkled as role checks across every screen means every screen is touched at pivot. Building six roles now for one human means six untested permission matrices guarding real money.
3 Program templates vs hardcoded program Programs and plan levels are rows (PRD §5.1 already). MAX_DEPTH = 2 is a named constant in the engine with the legal reason in a comment, plus CHECK (level IN (1,2)) on plan_levels. All defaults (hold 30, min $50, window 90, attribution last-click) live in one program_defaults object that seeds the Program form. The engine stays a pure function (conversion, program, tree) → commission[]. Template picker, business-type templates, setup wizard, rule builder, per-channel/geo rules. HealthyApp's 25%/5% hardcoded anywhere outside a plan_levels row means the second product is a code change and the first paying merchant is an engine rewrite.
4 API-key scoping api_keys(workspace_id, product_id, scopes[], key_hash, prefix, mode: test/live, created_by, revoked_at). Scopes: clicks:write, conversions:write. Shown once on creation; two keys may be live at once for rotation. Every inbound request resolves workspace_id from the key, never from the payload. Test-mode keys write to the same tables with mode='test' and are excluded from the ledger's payable set. Key-management UI beyond create/reveal-once/revoke on the Program screen; rate limiting; OAuth client credentials; per-key IP allowlists. A single AFFILIATE_API_SECRET env var means re-keying every integration at pivot and no way to attribute an inbound event to a tenant. Test mode retrofitted later means the first merchant's integration test pollutes a live ledger.
5 Asset ownership by workspace assets.workspace_id; storage paths /{workspace_id}/{asset_id}/{version}/{rendition}; signed URLs only. Token substitution is a pure function (asset_version, affiliate, link) → rendered with no knowledge of any product. Product marks are data (products.name, logo_url, mark_color), rendered by one component; no HealthyApp-specific component anywhere in the vault. Scripts are an asset type with read_seconds_at_default_speed. Brand-kit import, rights metadata, locale variants, DAM features, malware scanning, product feeds. The vault is the second differentiator (PRODUCT.md). A flat bucket plus product-aware components means re-uploading and re-rendering every asset for the first external merchant — and a cross-tenant signed-URL leak on collateral is a sales-killing incident.
6 Branding / white-label hooks All colour, type and spacing as CSS custom properties on :root, once. workspaces.branding JSONB exists and holds tellatribe's own defaults (name, logo path, support email, sender name); transactional emails and the portal header read from it. Workspace resolved from session membership, never from the URL path. Portal stays at tellatribe. Theme editor, per-workspace palettes, custom portal domains, custom email sending domains, white-label toggle. The tellatribe palette is locked once chosen; this item is about tokenisation, not colour. Hex values and the string "tellatribe" hardcoded in components and email templates means a grep-and-pray pass over every file when the first merchant wants their logo in the header. A workspace slug baked into every route means rewriting routing and every internal link.
7 Billing hooks that stay empty workspaces.plan = 'internal' column; no Stripe customer for the workspace; no billing code path anywhere. Keep the payout Stripe account reference on the workspace (workspaces.payout_account_ref) so the payout engine asks the workspace which account pays, rather than reading one env var. Plans, metering, invoices, trials, usage limits, merchant checkout. Low cost if the column exists; high cost if the payout rail is read from a global env var — the SaaS payout model (does tellatribe pay out as platform, or does each merchant connect their own Stripe?) is a genuine fork, and a workspace-level account reference is what keeps both branches open.
8 Event instrumentation and promotional-action counting Append-only events(workspace_id, actor, affiliate_id?, name, props JSONB, occurred_at) from day one; the names in RPT-04 above. Separately, every promotional action is already a row — asset_uses(mode), publish_jobs, recordings — so "actions per affiliate per period" is a query. PRODUCT.md requires this count from day one for the future activity bonus (D.7). Funnel report, dashboards over it, warehouse export, the bonus itself. Without it, PRD §14's success criteria are unmeasurable, the commercial pitch ("time to first promotion") has no evidence, and the activity bonus cannot be switched on without a backfill that does not exist. Cannot be back-filled.
9 Config, not constants Hold days, minimum payout, cookie window, 1099 threshold, chargeback-flag threshold, refund-rate threshold: rows on programs or workspaces, never env or code constants. PRD §2.5 and §5.3 already say this. Settings search, advanced-mode toggle. Every one of these is a per-merchant number in the SaaS.

A.3 What the Activation PRD got right that PRD.md lacks

Pulled forward because each makes the internal product better, not bigger.

  1. "Why this default?" lines (ONB-03). One sentence beside each program setting — "30 days matches the refund window; pay earlier and you chase money back." Costs nothing; stops the one admin from guessing in a year.
  2. The "Today" framing for the affiliate (RPT-01, §8.2 My Work). PRD §9.1 describes a stats dashboard. The affiliate's home should instead be the next payout and a feed of what happened, with one next action. Stats move to Earnings. This matches the chosen Board direction and principle 3 (depth on demand).
  3. A per-conversion explanation (TRK-04) and per-row "payable on + reason" (PAY-04). PRD guarantees traceability in the schema; these make it visible. The affiliate-facing version is the cheapest dispute prevention available.
  4. The Activation Pack as a snapshot (ENB-04, §10). Reshaped to asset_uses, it makes "collateral usage vs revenue" actually computable, powers the affiliate's own used/posted marks on the vault, and later enables "update required" on stale takes.
  5. Asset expiry and retirement (ENB-06, ENB-12). Launch collateral goes stale. expires_at and a retired status on versions cost two columns now.
  6. Guardrail metrics (§5). Replace vanity with: confirmed-invalid conversion rate, tracking error rate (webhook events failed/dead-lettered), time-to-resolution for queue items, ledger-vs-Stripe reconciliation variance. These are the admin's monthly glance.
  7. Activation funnel events (RPT-04, §12). Instrument now; see A.2 #8.
  8. Integration health check (ONB-04). Last click / last webhook received and a test conversion are what make "integrates in under a day" verifiable rather than hoped.
  9. Empty-state rule (§8.3). Every empty state says what to do next, why it matters, and how long it takes. Adopt as a design rule for every screen in Part B.

Not pulled forward, with reason: content approval (admin login), recommendations (admin login), rule builder and multi-touch (administration burden; incoherent with customer lock), marketplace (PRD §4), coupons (PRD §4), six staff roles (one human).

A.4 Recommendation on the documents

Keep PRD-Activation-Platform.md as a frozen appendix retitled "v2 vision — commercial platform," with its status line changed to point at this reconciliation as the authoritative mapping; do not fold it into PRD.md and do not retire it. Folding would triple the length of the authoritative document and reintroduce every Out item as a standing temptation in the file engineers actually read; retiring would discard the only articulation of the sellable product and the only place the commercial personas, guardrail metrics and funnel taxonomy are written down. PRD.md should gain a short §16 "Commercial shape" that lists the nine checklist decisions in A.2 by reference, and PRD.md §12's key-table list should be updated with the additions named in the mapping table above (workspaces, links, asset_versions, asset_renditions, asset_uses, payout_runs, social_accounts, publish_jobs, recordings, events, api_keys).


Part B — Surface inventory

Derived from PRD §9 (portal), §9.3 (three collateral modes), §10 (admin), §11 (terms versioning), §8 (payouts), plus the four pull-forwards marked PF in A.3 (integration panel, commission detail, per-row payable-on, affiliate home as a board). Nothing else is added.

Conventions:

  • Affiliate portal is mobile-first; design and review at 390 wide. Admin is desktop-first. Public is mobile-first.
  • Common states not repeated per row: loading (skeleton of the same layout; a commission row never changes size or position across states — only the state mark changes) and error (inline, retryable, never a blank page). Rows list only domain states.
  • Routes are the portal's; /r/[code] lives on each product's domain and go.tellatribe.com/[code] is a bare redirect. Neither is a screen.

B.1 Public (unauthenticated)

# Screen Route Purpose Primary action Data shown Domain states Form
P1 Join /join · /join/[sponsor_code] Become an affiliate; sponsor set from the recruiting link Continue (sends magic link) Sponsor name if code present ("Invited by Ashley"); email; display name; referral-code claim with live availability check and a suggestion from the name; the current terms version and the claims guidelines, accepted together Code taken; sponsor code invalid/suspended (join proceeds without sponsor, says so); already an affiliate (→ sign in); signup closed (if gated and closed — D.1) Mobile
P2 Check your email /join/sent · /sign-in/sent Confirm the magic link went out Open mail app / Resend Masked email Resend cooldown; link expired (from P4) Mobile
P3 Sign in /sign-in Returning affiliate or admin Send magic link Email Unknown email (same message as success — no enumeration) Mobile
P4 Auth confirm /auth/confirm Token exchange; no UI beyond a spinner — — Expired/used token → P3 with message —
P5 Pending approval /join/pending Shown only if the program is gated (D.1) — What happens next and expected time Approved (redirect on next visit); declined Mobile
P6 Terms /terms/[version] The exact versioned text an affiliate accepted (PRD §11.4) — Terms text, version, effective date Superseded version (banner linking to current) Mobile

B.2 Affiliate portal (mobile-first)

# Screen Route Purpose Primary action Data shown Domain states Form
A1 Board (home) PF / The three things PRODUCT.md "Portal Priorities" names, in order: what you can promote · where you stand · jump into collateral. Acceptance test: "it should feel simple to take some action" — a first-timer takes one promotional action without reading PROMOTE on a product row (→ A10 filtered to that product; the asset already carries the link) · secondary: GET A LINK (→ A8) Products strip (priority 1): one row per enrolled product — mark, name, your L1/L2 rate in plain words ("25% of first 12 months"), count of collateral, PROMOTE. Standing hero (priority 2): next payout amount, date, days away, state word; pending / approved split one tap away; guidelines link (→ A17) sits with it. Feed: commission earned (product mark, L1/L2, amount, state, time), commission approved, payout sent, downline joined, new collateral, click milestones (first click, then every 100 — not every click). Payout-onboarding banner when a pending commission exists and onboarding is incomplete (D.4) First run: hero reads "$0.00 — first payout after your first sale"; products strip is the dominant element; three-step list: Promote something · Get your own link · Set up payouts (later). Link live, nothing yet: "Your link is live · 0 clicks". Negative balance: hero shows the net and why. Suspended: read-only board with the reason and contact. Terms updated: blocking interstitial A20 Mobile
A2 Earnings /earnings PRD §9.1 metrics with density on demand Change period Clicks, unique visitors, conversions, conversion rate, EPC, earnings for period, across all products and per product; pending / approved / paid balances separately; next payout date and projected amount; downline counts by level; 30-day sparkline. Segments: Ledger · Payouts · Team · Payout method No data yet (explains what each number will mean); period with zero activity; negative balance Mobile
A3 Commission detail PF /earnings/commissions/[id] (sheet) Why this amount, why this state — Amount; level (direct / override on name); product; conversion date; plan rule in force (e.g. "25% of $99 first payment"); state; payable on date and reason ("30-day refund window"); if reversed/voided, the reason and the parent row; payout it was paid in Pending · Approved · Paid · Voided · Reversed · Flagged ("under review — you don't need to do anything") Mobile
A4 Payouts /earnings/payouts · /earnings/payouts/[id] PRD §9.5 payout history with per-payout commission detail Download statement List: date, amount, method, status. Detail: every commission row inside it, netted reversals, provider reference No payouts yet; failed (what happened, what to fix); skipped under minimum (balance rolled forward); skipped — onboarding incomplete (→ A6) Mobile
A5 Team (downline) /earnings/team PRD §9.4 single list of recruits Share recruiting link Name, join date, product(s), activity level. Never earnings or contact details. L2 count in header Empty: "No one yet — bring in someone good, earn on what they sell" + recruiting link Mobile
A6 Payout method /earnings/payout-method PRD §9.5 onboarding and tax status Set up with Stripe (hosted) / Use PayPal instead Method; onboarding state; tax-form state (from Stripe); minimum payout and next run date Not started; in progress (Stripe requirements outstanding — list them); complete; restricted by provider; PayPal (email only); country unsupported by Stripe (→ PayPal) Mobile
A7 Links /links Every link with its own numbers (PRD §9.2) New link Per link: product mark, label, destination, clicks, conversions, earnings; copy on the row. A default link per enrolled product is minted at join (label "Default") so collateral can carry a link before the affiliate has built one; labelled links are the pro's per-channel breakdown. Pinned section: recruiting link (visually distinct, "sets sponsorship, earns nothing by itself") Never truly empty (the default link exists); "only your default link so far" explains labels in one line; one product only (list collapses the product column) Mobile
A8 Link builder /links/new Product → destination → label → link, short link, QR Create Product picker (skipped when enrolled in one); destination page (default: product home; curated list + custom path); campaign label (optional) Not enrolled in the chosen product; short domain not configured (short-link row hidden — D.8) Mobile
A9 Link detail /links/[id] (sheet) Copy, QR, per-link performance Copy / Download QR / Share Full link, short link, QR, clicks, conversions, earnings, created date Zero traffic yet Mobile
A10 Studio (vault) /studio PRD §9.3 collateral, three modes Open an asset Per product, by category (email swipes, social captions, images, video, one-pagers, webinar decks, FAQ/objections, scripts). Each card: thumbnail, title, running time (script read time, video length), "new since your last visit" badge, recommended-use note, the affiliate's own marks (used / posted), mode affordances (Copy · Post · Record). Filters: product, category, mode Empty (no collateral for your products yet — honest, dated); only-populated categories shown; restricted asset (threshold not met — says what unlocks it); new version available on something already used Mobile
A11 Asset detail /studio/[asset] The rendered, personalised asset Copy / Download (Mode 1) · Post (→A12) · Record (→A15, scripts only) Rendered preview with {{ref_link}} etc. substituted; caption with disclosure already inside; renditions per platform (aspect ratio chips); version; which link it carries (per-asset link, A.1 ENB-10) Copied (confirmation that survives a glance); downloaded; posted before (date, where); restricted; superseded version Mobile
A12 Post composer (Mode 2) /studio/[asset]/post Publish from inside the portal Post now / Schedule Connected accounts to pick; per-network "exactly what we will post" preview (rendition, caption, link placement, disclosure); time picker No connected accounts (→A13 inline); account token expired; network rejected (reason); queued; posted (link to the post) Mobile
A13 Connected accounts /studio/accounts OAuth connection manager Connect Per network: account name, status, connected date None connected; expired (reconnect); revoked by network Mobile
A14 Publish queue /studio/queue Scheduled, posted, failed — with retry Retry / Cancel Items: asset, network, scheduled time, status, failure reason Empty; failed with retry; posting in progress Mobile
A15 Prompter (Mode 3) /studio/[asset]/record Phone as teleprompter over live camera Record Script over the lens (not beside), substituted CTA already in it, disclosure inside the script; speed thumb adjustable during recording; countdown; visible recording state readable at a glance; front/rear toggle; portrait default; caption safe-area marked; elapsed vs estimated read time Camera/mic permission denied (how to fix, fall back to Download script); Standby → Countdown → Recording → Recorded; interrupted (call/background) keeps the partial take Mobile, full-screen, bottom bar hidden
A16 Review take /studio/[asset]/record/review Keep, retake, or ship it Post (→A12) / Save to phone / Retake Playback; take length; retake is one tap and never threatens the previous take until the new one lands Multiple takes (pick one); saving; saved; uploaded for posting Mobile
A17 Guidelines /studio/guidelines PRD §9.3 what you may and may not claim; disclosure — Plain-English claims rules per product (HealthyApp health claims called out), the exact disclosure text, income-claim prohibition Updated since acceptance (badge) Mobile
A18 Settings /settings Profile, preferences Save Name, email, referral code (immutable once used — shown, not editable), sponsor name, terms version accepted (→P6), delete-account request (PRD §11.7 — anonymises, ledger survives) Deletion requested (pending admin) Mobile
A19 Notifications /settings/notifications PRD §9.6 each switch individual Toggle First click · first conversion · daily conversion digest · commission approved · payout sent · new collateral · downline signup All off (warns that payout problems will still be sent — operational mail is not optional) Mobile
A20 Terms update interstitial on any route PRD §11.4: accept the new version to continue Accept What changed, version, link to full text Declined (read-only board, no new links) Mobile

B.3 Admin (desktop-first)

# Screen Route Purpose Primary action Data shown Domain states Form
D0 Admin sign-in /sign-in (+ MFA step) Owner login Send magic link → enter MFA code — MFA not enrolled (enrol on first login) Desktop
D1 Queue (home) / PRD §10 exceptions queue — the only screen that must be good at being empty Per item, 2–3 buttons Items: flagged commissions/conversions (which rules, evidence), failed payouts (provider reason), negative balances (amount, since, producing or not), pending approvals (if gated), deletion requests. Count by type; age of oldest Empty — the normal state ("All services running normally"; last run, next run, pending total); items; item actioned (slides out, undo for 10s where reversible) Desktop
D2 Exception detail PF drawer on D1 (and from D4) TRK-04 explanation Approve / Void / Suspend affiliate · Retry payout / Mark paid manually · Write off / Keep · Approve / Decline applicant Click (time, IP hash, referer, campaign) → code → link → affiliate; customer_ref and attribution lock; amount; program and plan levels in force; L1 and L2 rows generated; rules tripped with evidence; this affiliate's prior queue decisions (audit) Each action requires a reason for anything manual; result written to audit Desktop
D3 Programs /programs · /programs/[id] PRD §10 create product, rates, hold, minimum, window, terms Save (forward-only) Product (name, domain, logo, mark colour); L1 and L2: kind, value, basis, recurring months; hold days; minimum payout; cookie window; attribution (fixed: last click + customer lock, shown not editable); terms (versioned, new version = new acceptance); gated toggle (D.1). Each default with its one-line "why". Integration panel (PF ONB-04): API keys (create, reveal once, revoke; test/live), redirect-route snippet, Stripe webhook URL + signing secret, last click received, last webhook received, test conversion button New (unsaved, nothing integrated); live; rate changed (banner: applies to conversions from now); no events received yet; test conversion result pass/fail with remediation Desktop
D4 Affiliates /affiliates · /affiliates/[id] PRD §10 search, view, adjust, suspend, reparent, view-as Search; on detail: Suspend · Reparent · Flag a commission · Write off · View as List: name, code, status, products, sponsor, downline count, balances by state, open flags. Detail: profile, enrollments and accepted terms version, sponsor and downline, links with stats, ledger (every row, drill to D2), payouts, payout-onboarding state, audit trail Pending approval; active; suspended (reason); negative balance; onboarding incomplete; deletion requested. "Adjust" means: flag/void a commission with reason or write off a negative balance — never edit a row (PRD §7.1) Desktop
D5 Payout runs /payouts · /payouts/[run] PRD §10 one screen: review the batch, release Release Upcoming: run date, affiliates included, batch total, netted reversals, skipped under minimum (count, rolled total), skipped onboarding-incomplete (count, notified), method split. History: runs with totals and failure counts. Run detail: per-affiliate payout → rows Nothing payable; ready; releasing (progress); completed with failures (→ D1); released by whom, when (audit) Desktop
D6 Collateral /collateral · /collateral/new · /collateral/[id] PRD §10 upload, categorise, version, target — the most-used admin screen Publish version Product; category; title; files and renditions per platform; copy with token insertion and live preview as a sample affiliate; required disclosure block; recommended-use note; restriction (program / performance threshold); expires_at; versions; usage: takes by mode, posts, revenue attributed. Scripts: text, estimated read time at default scroll speed, spoken CTA token Draft; active; retired; expired; superseded; missing disclosure (cannot publish); rendition missing for an enabled network (warns) Desktop
D7 Reports /reports PRD §10 revenue by affiliate / product / level; referred-customer cohort retention; collateral usage vs revenue; commission liability outstanding. PF guardrails: invalid-conversion rate, webhook failure/dead-letter count, queue time-to-resolution, ledger-vs-Stripe variance Change period / Export CSV As listed; every figure drills to ledger rows No data; period with none Desktop
D8 Audit log /audit PRD §12 audit_log as a screen Filter Actor, action, object, reason, before/after, time, IP Empty Desktop
D9 Workspace settings /settings The one row Save Workspace name; support/sender email; payout account reference (read-only); 1099 threshold; fraud thresholds (chargebacks/30d, refund rate, click-to-convert seconds, IP volume) each with a consequence line; admin members (owner only in v1); MFA status — Desktop

B.4 Non-screen surfaces the design must still cover

  • Redirects: /r/[code] on each product domain (302, sets ac_click); go.tellatribe.com/[code]. Failure must still land on the destination (PRD §12 non-negotiable; Activation §11 reliability).
  • Transactional email (PRD §9.6 + operational): first click; first conversion; daily conversion digest; commission approved; payout sent; new collateral; downline signup; operational, not switchable: magic link, payout onboarding needed, payout skipped/failed, terms updated, account suspended, admin queue alert and monthly run reminder.
  • Hosted third-party steps: Stripe Connect Express onboarding (return and refresh URLs → A6); social OAuth consent screens (return → A13).
  • QR code and statement PDF as downloadable artefacts.

B.5 The affiliate's first five minutes

Assumes open signup (D.1 recommended default), one product live (HealthyApp), and arrival via a recruiting link.

Min Screen What they do What they see that proves it worked
0:00 P1 /join/ASHLEY Sees "Invited by Ashley". Enters email, name. Code field pre-suggests from the name; they accept or edit; availability confirmed inline. Accepts terms vN and the claims guidelines in one checkbox with both linked. Continue. Code shown as theirs before leaving the screen
0:40 P2 → mail → P4 Taps the magic link Lands signed in; no password ever existed
1:00 A1 Board, first run Sees the three things in order: HealthyApp row with "25% of first 12 months · 14 pieces of collateral · PROMOTE"; hero "$0.00 — first payout after your first sale" with the guidelines link beside it; three steps. Taps PROMOTE Nothing to read first; the one action is the biggest control on the screen
1:10 A10 Studio Filtered to HealthyApp; sees only the categories that exist; a social caption marked NEW. Taps it A11 renders with their link already in the caption and the disclosure already present — the default per-asset link was minted when they joined, so no link-builder step stands between them and the asset
1:40 A11 Taps Copy caption, then Download image Both confirmations; the card now carries their own "used" mark. asset_uses and events rows written; promotional-action count for the period = 2
2:10 A1 Board Returns. Step 1 ticked; feed row Your link is live · 0 clicks; step 2 "Get your own link" offered for the pro who wants a labelled one They leave with a caption on the clipboard and an image on the phone
2:30 A8 Link builder (optional) One product, so the picker is pre-selected; destination defaults to the product home; label optional. Create → A9 → Copy "Copied"; the link appears in A7 with its own numbers
~5:00 (optional) A11 → A15 If the asset was a script: Record → prompter → review → Save to phone or Post A video, from script to file, without leaving the portal (PRD §14)

Where payout onboarding is asked for — recommendation: after first earnings, not at signup. Trigger it when the first commission reaches pending: an email, a Board banner, and step 3 on the first-run list turns active with a date ("set up payouts by approval date"). The 30-day hold guarantees at least a month of runway before anything is payable, and the payout run already skips-and-notifies the un-onboarded (PRD §8 step 4), so nothing is lost. Stripe Express asks for date of birth, SSN/ITIN and a bank account; asking that of a coach who has not yet seen a single click is the largest avoidable drop-off in affiliate signup and buys nothing for 30+ days. Hard requirement remains: no payout leaves without completed onboarding. Escalate the banner's prominence as the approval date nears; after approval with onboarding still incomplete, the Board hero itself reads "Approved · waiting on your payout details."

B.6 The admin's week

Normal week (queue empty) — zero logins.

When Screen Why Login?
Daily — (email) Queue digest: "Queue empty · 14 conversions · $1,240 pending · next run Nov 1" No
Ad hoc, when there is new material D6 Collateral Upload, set disclosure, renditions, publish; affiliates get the new-collateral email Yes — the one voluntary login
1st of the month D5 Payout runs Review batch total, skipped counts; Release. Stay for the completion state. Yes — the one required login
After the run D7 Reports Monthly glance: revenue by product/level, liability, the four guardrails Same session

Exception week.

Trigger (email) Screen path Decision
"2 flagged conversions" D1 → D2 drawer Read rules tripped and evidence → Approve (→ pending) or Void with reason. If the affiliate has a pattern (prior decisions in the drawer) → D4 detail → Suspend with reason
"Payout failed — 1 affiliate" D1 → D2 → D5 run detail Retry after affiliate fixes bank detail (rows are back in approved automatically), or Mark paid manually with reference if paid out-of-band
"Negative balance, not producing — 90 days" D1 → D4 Write off (audited) or Keep rolling
Applicant pending (only if gated) D1 → D2 Approve / Decline
Affiliate dispute by email D4 detail → ledger → D2 Answer from the ledger in under five minutes (PRD §14); if a reparent is warranted → Reparent with reason (forward-only)
Deletion request D1 → D4 Anonymise (ledger rows survive as financial records, PRD §11.7)

Everything above returns to D1, and D1 returns to empty.

B.7 Navigation model

Affiliate bottom bar — BOARD · LINKS · STUDIO · EARNINGS, evaluated against B.2.

Tab Holds Verdict
BOARD A1, A20 (interstitial) Holds
LINKS A7, A8, A9, recruiting link (pinned section of A7) Holds
STUDIO A10, A11, A12, A13, A14, A15, A16, A17 Holds. Record (A15/A16) takes the full screen and hides the bar; it is still Studio's. Connected accounts and the publish queue belong here because they only exist for Mode 2
EARNINGS A2, A3, A4, A5 (Team), A6 (Payout method) Holds, with two placements that must be explicit: Team (downline) lives under Earnings, because its economic meaning is the L2 override and PRD §9.1 puts downline counts on the earnings dashboard; Payout method lives under Earnings, because it is a money setting and the "set up payouts" nudge points there
(homeless) A18 Settings, A19 Notifications Not a destination. Place behind the avatar/code in the header (the enamel header already shows the affiliate's code at right).

Verdict: the four destinations hold every screen. Two risks to design against: Earnings becomes the dense tab (five segments) — acceptable, it is where the pro's density lives (principle 3), but the segmented control must be visible without scrolling; and "Studio" must read as the whole vault, not only the recorder — the Record affordance is a button on a script, not the meaning of the tab. Deep links from email land directly on A3, A4, A11 and A6 so a notification never drops someone on a tab root.

Admin primary nav — Queue · Collateral · Payouts · Affiliates · Programs · Reports, with Audit and Settings in an overflow. Ordered by frequency of real use (PRD §10: collateral gets the most actual use; payouts monthly; the rest exceptional). Compared with the Activation PRD §8.1 (Today, Programs, Partners, Campaigns & Collateral, Conversions, Payouts, Insights, Settings): Campaigns is dropped (no object), Conversions is dropped as a top-level destination because a browsable conversions list invites the daily look the product is designed to remove — conversions are reached through an affiliate, a queue item, or a report.

B.8 Open decisions

Stated as questions with recommended defaults. D.1–D.3 are PRD §15 items; the rest surfaced from this inventory. Rates (PRD §15.1) and domain registration (§15.5) are not screen decisions and are listed only where they touch a screen.

# Question Recommended default Screen impact
D.1 Gated or open signup? Open, auto-approved, as a per-program toggle defaulting off. The downside (junk signups, self-referral) is already handled by PRD §7.4 flags and the hold; gating adds a queue item type and a waiting screen that an internal program with HealthyApp customers as the growth lever does not need. Build the pending_approval state anyway so flipping is a setting. P5 exists but is off; D1 has an "applicants" type that is normally hidden; D3 has the toggle
D.2 Can customers become affiliates? Yes. It is the largest growth lever (PRD §15.3). The entry point is HealthyApp's surface, not ours: an "Earn" link inside HealthyApp deep-links to /join?product=healthyapp&customer_ref=… so the affiliate row carries customer_ref and self-referral matching is exact rather than email-fuzzy. P1 accepts customer_ref; A1 first-run copy acknowledges "you already use it"; no new screen
D.3 Cross-product downline? Yes (PRD §5.2 already assumes a global sponsor). A sponsor earns L2 on everything their recruit sells, under each product's own L2 rate. A5 shows product(s) per recruit; A2 Team segment shows L2 by product; nothing to toggle
D.4 Payout onboarding before or after first earnings? After — triggered by the first pending commission, hard-required before the first payout (B.5). A1 banner and step 3 behaviour; A6 reachable but never a gate on A8/A10
D.5 Can the admin manually flag (hold) a pending or approved commission? Yes. PRD §7.2 has no manual transition into flagged; add pending → flagged and approved → flagged as admin actions with a required reason, audited. Without it the only tool for a suspected-but-unflagged row is Suspend, which is too blunt. D4 ledger gets a "Flag" action; A3 shows "under review"
D.6 Which networks does Mode 2 publish to at launch? Instagram (business/creator accounts via Graph API), Facebook Pages, LinkedIn. TikTok and X via Mode 1 download at launch; their APIs' approval timelines and posting constraints should not gate the vault. A13 list; A12 preview variants; D6 rendition set
D.7 Bonuses in v1? No — but shape for the one PRODUCT.md names. The future bonus rewards promotional actions per period (posting, recording, sharing) — never recruiting, never volume. Count from day one: asset_uses(mode) plus publish_jobs and recordings give actions per affiliate per period with no backfill. When switched on, it is paid through a separate bonus_awards ledger that joins payout_items, not as a commissions row, so PRD §11.2 (commission requires a conversion) stays a schema constraint. A sales-volume bonus, if ever wanted, attaches to the conversion that crossed the threshold. None in v1; later a "this period: N actions" line on A1/A2 and a bonus row type in A3/A4
D.8 Short-link domain go.tellatribe.com? Register and use it. If not available at launch, A8/A9 hide the short-link row rather than show a placeholder. A8, A9, A11 token {{short_link}} falls back to {{ref_link}}
D.9 Is the vault allowed to launch empty? No. Seed at least one asset in each of: social caption (with image renditions), email swipe, one script, and the guidelines page for HealthyApp before Phase 6 ships; show only populated categories. PRD §15.6 asks what exists today — that inventory is a prerequisite for the Studio design review. A10 empty state should be a build-time failure, not a design
D.10 Does the platform store Mode 3 recordings? Yes, briefly: keep the upload for 7 days to serve the publish queue, then delete unless it was posted (then keep the posted reference, not the file). Say so on A16. A16 copy; A14 item lifetime
D.11 What does the affiliate see about clicks on the Board? Milestones only (first click, every 100th) plus the running total on A2/A7. Every click as a feed row is noise that buries money rows. A1 feed rules
D.12 Admin MFA mandatory? Yes, enrol on first login. One human, real money, magic-link-only is one phished inbox away from a payout run. D0
D.13 Terms re-acceptance blocks what? New links and new takes, not viewing. A20 appears on entry; declining leaves a read-only board. Existing links keep working — a dead link is worse than an unaccepted clause (PRD §6.1 reasoning). A20, A7, A10 disabled affordances

Rendered from build-plan/03-reconciliation-and-surfaces.md. Edit the source, not this page.