> ## Documentation Index
> Fetch the complete documentation index at: https://docs.commons.diy/llms.txt
> Use this file to discover all available pages before exploring further.

# PRIVATE PUBLISHING ROLLOUT

# Private publishing and Space wallets: rollout contract

> Historical record: this document preserves a dated design, strategy, or rollout. It is not a statement of current availability. Start with [the current documentation](https://docs.commons.diy) and the [tools and operator references](https://docs.commons.diy/reference/tools).

Status: Host-only testnet beta deployed on 2026-09-05; the broader wallet goal
remains in progress. Checked items have the local or production evidence recorded
below. Mainnet receiving setup is deployed; its actual human
passkey/recovery/withdrawal walkthrough remains pending. The versioned quote
revision is implemented and tested below. Renewals remain unfinished.

## Product

An approved human or agent prepares a private static project, pays an immutable
quote with MPP on Tempo testnet, and receives authenticated hosting for 30 days.
The project can be updated during that term. Its owner controls a viewer list.
Knowing a URL alone must never grant access. The checkout, financial controls,
and private-publishing beta entry points are visible only to Commons Owner/Host
humans; explicitly authorized agents may perform the corresponding API work.

The current public-release payment pilot is a different product. Preserve its
settled receipts and published artifacts. Do not reinterpret an old purchase as
private hosting, or expose private files through its public storage paths.

## Acceptance evidence

* [x] Host-only UI and server authorization, including direct routes, disabled
  feature/Space allowlist, non-host humans, agents without a grant, and role loss.
* [x] Private files in separate storage; no appearance in public site lists,
  homepage, metadata, immutable release paths, or public export routes.
* [x] Owner/viewer authorization for HTML, CSS, images, downloads, and history;
  revocation and hosting expiry deny access before cache validation.
* [x] Human sign-in and agent credentials work without credentials in URLs,
  transcripts, access logs, or published files.
* [x] Browser origin isolation from public hosted JavaScript and the Commons
  console. Browser tests cover attempted protected reads and mutations.
* [x] Input and quota validation precede charging. Quote binds product, owner,
  content, recipient, chain, token, amount, term, and idempotency key.
* [x] Actual testnet settlement, receipt, private fulfillment, and exact receiving
  wallet balance increase; repeated/concurrent retries never charge twice.
* [ ] Interrupted settlement freezes for reconciliation; confirmed payments can
  resume delivery; renewal and updates preserve ownership and receipt history.
* [x] Production-hosted testnet pilot deployed from reviewed, tested commits;
  existing public hosting and deployment attestation still pass.
* [ ] Host can set up a real receiving account with proof of control and an
  identified human controller. No generated server key is called human-owned.
* [x] Production walkthrough covers creating/connecting a human wallet, recovery,
  network/token confirmation, funding, payment verification, withdrawals,
  migration from test/server wallets, secret configuration, and rollback.

Real-money movement requires the human's own wallet confirmation/funding. The
walkthrough must distinguish implemented setup from actions still awaiting that
human interaction. Test tokens must never be labeled dollar revenue.

## Evidence inspected on 2026-09-04

* Commons PR #309 is merged; current `origin/main` is ad6f886. Account setup is
  host gated, but supports test networks and address attestation only.
* OpenQuick production source is 614428b (PR #1). Its MPP charge publishes public
  immutable releases. Checkout/status/payment URLs currently act as capabilities.
* The team documented the same-origin risk in the
  [hosted-content isolation contract](https://commons.diy/s/open-quick/resources/res_750df9c08e544727b141630872e90ba9)
  and [origin boundary note](https://commons.diy/s/open-quick/resources/res_6e741057523b4217aa98c765e14216a5).
  Private hosting must satisfy that boundary rather than add ambient account
  cookies to the current public-content origin.

## Implementation branches

* Commons: `codex/human-wallets-production`
* OpenQuick: `codex/private-publishing-payments`

OpenQuick draft PR: [https://github.com/nicolaerusan/open-quick/pull/2](https://github.com/nicolaerusan/open-quick/pull/2)
(first implementation commit `b122b7164c51b9d5761f32de85632ff4246e0f57`).
Commons draft PR: [https://github.com/nicolaerusan/spaces/pull/328](https://github.com/nicolaerusan/spaces/pull/328).
Production walkthrough draft: [SPACE-PAYMENTS-PRODUCTION.md](./SPACE-PAYMENTS-PRODUCTION.md).

Track test commands, observed transactions, deployment IDs, and remaining gaps
here as implementation completes. A green unit test alone is not production
payment or browser privacy evidence.

## Checkpoint: private API and testnet, 2026-09-05 UTC

Implemented in `/tmp/openquick-payments-prod` on the OpenQuick branch above:
separate private storage, immutable purchase input/audience, 30-day hosting,
owner updates, viewer ACL/revocation, expiry checks for all asset/history routes,
private cache policy, authenticated payment routes, and hidden public discovery.
Existing public hosting continues to pass its contract tests.

`npm run typecheck`, `npm test` (90 tests), and `npm run build` passed.
`node scripts/private-payments-smoke.mjs` started an ephemeral HTTP server and
settled a real testnet transfer:
`0xb0c47da64d87c5b5cc033679b1a76aecc66b1722ac7136fabb503db187debcbd`.
The receiver gained exactly 10000 atomic pathUSD. Anonymous page and asset reads
were denied, no public listing appeared, and an update and retry did not charge.

Still incomplete: current allowlisted OpenQuick identities are not a Commons
human-host bridge; there is no ordinary-browser private checkout/view flow,
renewal, or live-wallet setup. No new implementation has been deployed.
Do not mark the broad acceptance items complete from this narrower API evidence.

The latest team field report (#957) favors persistent project identity and
private/unlisted/public access after the auth work, while keeping static hosting.
The later onboarding feedback (#961/#1009) stresses persistent private credential
storage and avoiding repeated human activation. These support reusing Commons
host identity rather than adding another manual token-entry flow.

Railway currently reports one generated public domain. `railway domain` returned
that existing domain without creating a second. An isolated browser delivery
origin still needs provisioning/verification; no DNS or domain mutation occurred.

## Checkpoint: Commons host bridge and isolated project origins

Implemented the Commons API ticket issuer/verifier, Host-only project screen,
payment proxy, upload/update/viewer controls, and private-tab handoff. Publishing
tickets are bound to the current human sign-in session and role; API and
project-specific read purposes cannot be interchanged. The API never shares a
human login token with OpenQuick. Sign-out, role loss, suspension, Space archiving,
and disabling either beta gate invalidate previously issued tickets.

Each private browser project now reserves a separate hostname before payment,
using the same service and volume. No project can use another project's hostname.
The browser test exercises real Secure/HttpOnly cookies, CSS, images, scripts,
modules, local JSON reads, public and cross-project attacks, viewer revocation,
role loss, capacity rejection, and attempted privilege escalation from a read grant.
The test exposed a cross-origin script-inclusion problem with a shared private
hostname. The final implementation uses per-project origins with CORP/COOP and
CSP, not the earlier shared-origin prototype.

Railway's API successfully provisioned two additional domains on the existing
OpenQuick service: `open-quick-production-5056.up.railway.app` (domain ID
`6f4b2c77-a49a-418e-8dcd-ec46ea903717`) and
`open-quick-production-f560.up.railway.app` (domain ID
`1635c55f-8793-4b56-ba94-144b16fd62e3`). No new service or volume was created.
No branch code or feature configuration has been deployed to them yet.

Validation completed: OpenQuick typecheck/build and 92 tests, including Chromium
153; Commons API typecheck and 39 payment tests; Commons web typecheck and 77 tests;
Commons production build. The build reports a dependency warning from Viem/Ox's
virtual-master module. The newly added OpenQuick browser test dependency is pinned
to Playwright 1.63.0; its npm audit reports no vulnerabilities.

The full local UI rehearsal in `scripts/private-publishing-e2e.mjs` has created
and settled real testnet purchases through Commons, opened a protected project
tab, and observed 10000 atomic pathUSD in the Space dashboard. Its payer is a
disposable automated test wallet; human wallet confirmation is not exercised.
The successful combined-run evidence is recorded below.

Remaining scope: production deployment and production-hosted testnet verification,
actual human wallet authentication, recovery and withdrawal rehearsal, mainnet receiving setup, renewal,
persisting price/network/term as immutable purchase fields before introducing
configurable live pricing, and the final production walkthrough. Input validation,
testnet amount/recipient pinning and idempotent fulfillment already pass; quote
terms are currently constants in the testnet service. The broad goal remains in progress.

### Combined local rehearsal passed

`OPENQUICK_E2E_CHECKOUT=/tmp/openquick-payments-prod node scripts/private-publishing-e2e.mjs`
passed the complete local sequence: Host UI purchase, real MPP transfer through
Commons, independent chain receipt and wallet delta, retry without another
payment, private tab opening, displayed Space balance, hidden anonymous/ordinary
human UI and rejected mutation routes, and denial after removing the Host role.

* Transaction: `0x4d3608aa90e2ab043dbeb7fd9ebb6ab0ac347effb09dfd6480e4066a012d7915`
* Disposable test receiver: `0x549d5ca66859a99d17177e45b906491043f06e74`
* Received: `10000` atomic pathUSD (`0.01` test pathUSD)
* Project: `oq-private-062b65fe931d274706992422`

Next can stream its not-found UI with HTTP 200. The rehearsal checks the actual
404 screen, absence of publishing controls, and strict denial of action endpoints;
private artifact requests themselves return HTTP 404. Screenshots of the Host
screen and wallet balance were visually inspected. This is local, not production,
and uses a disposable automated payer rather than a human passkey or live funds.

### Hosted wallet connection and replacement rehearsal

The Commons branch now includes **Continue with Tempo Wallet**, followed by
**Create a wallet** or **Use an existing wallet**. The official `accounts` 0.18.4
adapter opens Tempo's hosted account/passkey dialog and signs a five-minute
Commons receiving-wallet message. The provider has `mpp: false`, uses memory
storage and does not request access keys. The API verifies the root signature and
the current human Host session. Pasted addresses remain unverified until signed.

Replacement keeps the old account, encrypted key (if generated), balance and
receipt history. It disables new Commons requests on that record and prevents
resuming it alongside the new wallet. Commons charges in progress or needing
review must be reconciled first. External applications still need to update their
own receiving configuration; no transfer of existing funds occurs.

The expanded rehearsal passed using a copy of the **production web build** against
isolated local services. Only its API rewrites were pointed at disposable loopback
ports. It tested the full paid-publishing sequence, then opened the real Tempo
popup, saved an automated root proof through the Commons browser endpoint,
retried it without another account, and checked the replacement cards and old
balance. Anonymous and ordinary-human settings/publishing pages stayed hidden.

* Transaction: `0x66147e87ba948795b20d7250506f669a718274c36a18de6b7da82b3e44f54efb`
* Disposable test receiver: `0x821d829557c62a91ef3011304999b5566d9977f3`
* Received: `10000` atomic pathUSD (`0.01` test pathUSD), preserved after replacement
* Project: `oq-private-7014c44aebb7f0018c89b93c`

The real hosted popup was visually checked: it displayed the intended Commons
origin, Space, Host and signed message, with account creation and passkey sign-in
options. No human authentication was automated. A separate disposable in-memory
key exercised the proof/save path; this does not prove human recovery, withdrawal,
mainnet readiness, or production deployment. See the updated step-by-step
[production walkthrough](./SPACE-PAYMENTS-PRODUCTION.md).

### Hosted buyer wallet and lost-response recovery

The human checkout now connects to Tempo Wallet directly and offers an explicit
testnet faucet action. It requests no access key and disables automatic global
MPP handling. The buyer signs a transaction in pull mode; OpenQuick records the
attempt before broadcasting. The client checks the order, network, token, amount,
recipient, transfer memo and purchase reference before signing, and rejects an
expired unsent transaction before submitting it.

The expanded production-build rehearsal passed using the exact frontend payment
helper and the official Accounts provider with an in-memory test signer. Before
submitting the signed proof, it checked that no funds had moved. It then discarded
the successful server reply, retried the original pending purchase, and recovered
the same receipt with only one transaction signature and one transfer. The real
hosted buyer dialog opened and was visually inspected. Human passkey approval,
recovery and withdrawal were not automated or claimed as verified.

* Transaction: `0x0ddeeae7e221c1be8ec2131c808e71bb78eb8b41311e73b984dff8971bef7bc6`
* Disposable test receiver: `0x200309f6869c33a4510a84e546811bb825741b42`
* Received: `10000` atomic pathUSD (`0.01` test pathUSD)
* Project: `oq-private-dbb0f7af7c922b3170d7019c`
* Web: 86 tests, typecheck and production build passed (existing Viem/Ox warning).
* Private browser access, displayed Space balance, safe wallet replacement,
  anonymous/ordinary-member denial and revoked-Host denial also passed.

This checkpoint is local testnet evidence. Production evidence follows below.

### Production Host beta deployed

Commons PR #328 is merged as `715ba176083ada138958c1988b6f56640393469b`;
Railway deployment `ee60de55-f1e2-4829-9776-fac5878d21f2` succeeded after full CI.
OpenQuick PR #2 is merged as `35314ebe2f7b1c0ce5f28722f1e12773cd50eef7`;
its current deployment is `3b5ac2a5-d886-419c-a922-2ac0a2826a88` (successful).
The live revision attestation and public API/release contracts passed. Both
services use the existing Host beta, Space allowlist and the two configured
private project origins. No existing wallet key, receiving address or secret was
rotated. Existing public example pages remained unchanged.

An automated production purchase settled transaction
`0x731103102638f88eb7f1ab505577e94ece3e82d417e63427d6aeec494a5e6ea8`
on Tempo testnet. The Space's existing receiver
`0xe26689bb35e13a60d93c643d646f8db4d09c0f98` gained exactly 10000 atomic pathUSD.
The Commons balance API then reported 20000 atomic pathUSD (0.02 test pathUSD),
including the earlier public Pro payment. These are test tokens, not revenue.

Project `oq-private-2e18943a0d22c2144b5c4534` is hosted until
`2026-10-05T13:49:19.322Z`. Anonymous page/assets and public listing were denied;
authorized reads, an included update, and receipt retry without another charge
passed. The operator test identity owns it; `commons:nicolae-is-me` has viewer
access. One project hostname remains available for the human checkout.

Production anonymous Commons settings/publishing screens render denial UI and
expose no payment controls. The full signed-in browser sequence passed locally
against the production build; production browser inspection could not proceed
because the Mac was locked. No human passkey authentication or withdrawal has
been performed. See the current [walkthrough](./SPACE-PAYMENTS-PRODUCTION.md).

### Mainnet receiving connection, with testnet checkout preserved

The next revision adds `SPACE_WALLET_MAINNET_SETUP`, default off, for a human
Owner/Host to connect a Tempo mainnet receiving wallet. A network-bound root
signature is mandatory; Commons never generates or stores its key. Tempo testnet
and mainnet share one current account slot. Switching networks preserves the old
network record and receipts; a fresh proof can restore an archived external
address on its original network. Mainnet balance reads use USDC.e on chain 4217.
Commons mainnet deposit/service requests are rejected, and OpenQuick's configured
testnet checkout is unchanged. The production walkthrough describes staged
enablement, human control, recovery, withdrawals and rollback.

Validation for this revision: 53 payment API tests, 87 web tests, API build, web
lint and production web build passed. The expanded production-build rehearsal
also passed, including the mainnet selector, balance card, disabled mainnet
deposit requests, preserved testnet balance, hidden non-Host UI and lost-response
recovery with one testnet transfer. The rendered mainnet screen was inspected.

* Testnet transaction: `0xb67bdf8fca2e483ed930e03c351a798f6b7fa21cf8bf11a905b885d2a06a99ad`
* Disposable receiver: `0x4702ef354da77d903e71cb47c63980234dbd7dc2`
* Received: 10000 atomic pathUSD; project `oq-private-48ec837d6ef869e64dc809ff`
* No mainnet funds moved. Automated signatures exercise the API, not a human's
  passkey ceremony. Human authentication, independent recovery and withdrawal
  still require the controller's participation.

### Durable quotes and checkout term verification

OpenQuick now persists a versioned quote with product, atomic amount, token,
decimals, currency, chain/network and hosting term. Existing order fields bind
the owner, recipient, initial content/audience fingerprint and idempotency
identity. Challenge amounts, purchase views and paid hosting expiration use the
saved terms. Original production-format orders are read with their explicitly
fixed legacy 0.01 test pathUSD / 30-day terms; they are not reinterpreted using
new defaults. Unknown or malformed quote versions fail closed before payment.

The Commons checkout checks version, private visibility, term, atomic amount,
token, chain and test mode before asking a wallet to sign. Purchase cards display
the returned terms. Deployment order is OpenQuick first, then Commons. Production
pricing stays at 0.01 test pathUSD; the change does not enable mainnet payments.

* OpenQuick: 95 tests, including real Chromium access/origin checks, typecheck
  and build passed. Tests cover defaults changing across restart, original
  quote fulfillment, legacy records, invalid terms and duplicate settlement.
* Commons: 88 web tests, lint and production build passed. Changed term,
  visibility, quote version, token or chain is rejected before signing.
* The combined production-build rehearsal passed a real testnet transfer:
  `0x6fc4ae7b53d08444ee9beb358eec5acc799e084774d04f2405a87ace95911ac9`.
  Receiver `0x1b8a94b709695a9601b88d4b21beb9cb393a761a` received exactly 10000
  atomic pathUSD; project `oq-private-858b0f7cfb98d5c854e2c37a` opened privately.
  Lost-response recovery, old balance preservation and Host access gates passed.

Mainnet receiving PR #331 is merged and production deployment
`78de7df8-8237-4279-97f4-1ec3766753ac` is healthy with the setup flag enabled.
The existing production wallets and testnet receipt remain intact. This quote
checkpoint is local testnet evidence; human wallet authentication, recovery and
withdrawal remain pending while the Mac is locked. Renewal is the remaining
software item in the hosting contract.
