- Date: 2026-08-06
- Status: Proposed (design spec — architecture-first; no code, gated on maintainer-provisioned infra)
- Phase / Feature: turning the "give the developer a git link" action into an invisible, Arno-hosted, paid share
- Builds on: ADR 0081 (per-project repo, §6 + its 2026-08-06 amendment — Variant A, invisible provisioning, lazy-create-at-share), ADR 0049 / 0052 (Sorgente + prod model)
- Ratified: the maintainer chose Variant A (repos under Arno's org, one-time maintainer setup, zero per-user activity) and directed that payment route through Arno (reseller markup), gated at the share action. Billing model recommended as subscription; final price is a business decision left to the maintainer.
Context
ADR 0081 makes each project's divergence materialize as a git repo, provisioned lazily at first share under Arno's own GitHub org (Variant A). This ADR records the hosting-at-scale and monetization decisions that ride on that share action: who pays whom, how cards are handled, and what the customer buys. ADR 0081 owns the git model; this ADR owns the money and the account topology.
Driving scenario (maintainer's words): a designer finishes a design, wants to hand a developer a link — at that moment: pay; OK, pays by card; link issued.
Decision
§1 — Reseller model: Arno is the merchant, GitHub is a cost input
Arno holds a single GitHub Enterprise account for its org and pays GitHub. The user pays Arno, not GitHub, and never holds a GitHub account or bill. Standard reseller/markup arrangement: GitHub cost is an input, Arno sets the customer price. Because Variant A read-links consume no GitHub seat (ADR 0081 amendment, Cost), the marginal GitHub cost of an issued read-link is ≈ $0 → the share price is almost entirely margin. The only real cost input is an opt-in write-collaborator seat, priced as a higher tier or passed through.
§2 — The share action is the paywall + lazy-create gate
The owner clicks "give the developer a link." Flow:
- Paywall interstitial (price from the billing model, §4).
- Card handled by a PCI-compliant processor (§3) — Arno's UI and servers never receive card data.
- On
payment.succeededwebhook → backend lazily creates the Arno-org private repo (ADR 0081 §6), commits the current resolved export, and issues the read-token clone-link.
Payment and repo creation coincide — no repo is created unpaid. This is why lazy-create (ADR 0081 amendment C) and monetization share one gate: the same event that earns revenue is the one that incurs the (near-zero) GitHub cost.
§3 — Card handling: processor-only, never Arno (safety-critical)
Card data flows only through a PCI-compliant processor — Stripe Checkout or a Merchant-of-Record (Paddle / Lemon Squeezy). Arno stores no PAN, renders no raw card field; it receives only processor tokens + webhooks.
Recommendation: a Merchant-of-Record (Paddle / Lemon Squeezy). At 100k global users the MoR also assumes VAT / sales-tax liability and remittance, which raw Stripe leaves to Arno. Trade-off: an MoR takes a higher cut than Stripe's base rate in exchange for offloading global tax compliance.
§4 — Billing model: subscription (recommended) vs one-time unlock
The share buys access to a living repo — under the hood Arno keeps syncing the designer's edits into it (ADR 0081 invisible model). Two models:
- Subscription (recommended). The link/repo stays live and auto-synced while the subscription is active. Matches the ongoing service actually rendered (continuous sync ≠ one-time dump); recurring revenue; a lapsed subscription revokes the token and pauses sync (§5).
- One-time unlock. Simpler UX ("pay once, link issued"), but a single payment against a perpetually-synced repo does not cover ongoing cost — economically unbalanced.
Ratified direction: subscription, with the final price a business decision the maintainer sets (not fixed here). Write-collaborator seats (§1/§5) are a higher tier or add-on.
§5 — Access tiers map to cost
| Tier | Mechanism | GitHub seat | Customer price |
|---|---|---|---|
| Consumer (read) | tokenized clone-link | none — $0 | base share price (≈ pure margin) |
| Contributor (write) | collaborator by GitHub handle or deploy key | collaborator = 1 paid seat; deploy key = $0 | higher tier / passthrough |
Token links are revocable / rotatable from Arno: revoke = invalidate the token + pause sync. This is the enforcement point behind a lapsed subscription (§4).
Anti-patterns
- Do not let Arno's servers or UI touch raw card data — processor-only (§3). This is also a hard platform rule: the agent never enters card/financial credentials nor creates payment accounts; the maintainer wires the processor with their own keys via secrets.
- Do not create a GitHub repo before payment — creation is the post-payment step (§2), keeping unpaid repos (and GitHub cost) at zero.
- Do not give every project a repo at create — that reintroduces 100k unpaid repos (ADR 0081 amendment C).
- Do not hand a write-collaborator seat by default — it is the one paid GitHub input; default to read-token-links (§5).
- Do not price a perpetually-synced repo as a one-time fee (§4).
- Do not expose the user to GitHub at all in Variant A — no GitHub account, login, or bill reaches the Arno user; GitHub is Arno's internal cost input (§1).
Infra gates (maintainer-provisioned — credentials, not code)
- GitHub org + Enterprise agreement sized for automated bulk repo creation (pre-clear the pattern with GitHub — automated mass repo creation under one org is atypical and can trip abuse limits).
- GitHub App (scopes: repo-create, contents-write, collaborator-add) — secrets provisioned on
arno-api-test(today absent → blocks all git writes, per ADR 0081). - Payment processor account — Stripe or (recommended) a Merchant-of-Record (Paddle / Lemon Squeezy); API keys via secrets; a webhook endpoint for
payment.succeeded/ subscription lifecycle.
All three are credential/account steps only the maintainer can perform. The agent does not create payment accounts or enter card/financial credentials.
Roadmap
- P1 — DONE (2026-08-07). GitHub App + Arno-org provisioning path, proven end-to-end on the test stand.
apps/api/src/projects-app/:provision.ts(mint token viaPROJECTS_APP_*+ idempotentensureOrgRepo) andexport.ts(provisionAndExportProject— read pins →serializeDesignExport→ commitdesign/*straight to the repo default branch, no PR). Maintainer-gated routesPOST /api/v1/projects-app/smoke+POST /api/v1/projects/:projectId/org-export. Verified live: private repo created underarno-projects, threedesign/*files committed, and a re-export of an unchanged pin layer is a git no-op (deterministic manifest —serializeomitExportedAt). Infra provisioned by the maintainer: orgarno-projects, AppArno Project Repos(id 4513994),PROJECTS_APP_*secrets onarno-api-test. - P2 — payment processor integration (Checkout / MoR) +
payment.succeeded→ the sameprovisionAndExportProjectseam behind the paywall + issue-token-link. Blocked on the payment stack (Block 3 of the infra runbook). - P3 — subscription lifecycle (active → synced; lapsed → revoke token + pause sync); write-collaborator tier. Auto-sync-on-edit needs a per-project "provisioned" marker so a pin change re-exports ONLY after the repo exists (lazy-create preserved) — a small schema delta, deferred with the other §8 deltas.
- P4 — token rotation / revocation UI; deploy-key path for seat-free write.
References
- ADR 0081 — per-project repo (§6) + 2026-08-06 amendment (Variant A, invisible provisioning, lazy-create-at-share). This ADR is the billing/hosting half of that amendment.
- ADR 0049 / 0052 — Sorgente + prod model (why prod has no live Sorgente DB; the release channel projects read through).
- Platform rule — the agent never enters card / financial credentials or creates payment accounts; the maintainer wires the processor.