# Publish

> Two distribution gates — a tenant-private app your organisation signs itself, or a store app that Sollar reviews.

Source: https://miniapp.sollar.com/start/publish/

---

Sollar has **two distribution gates**, and the difference is not cosmetic.

| | Tenant-private | Store |
|---|---|---|
| Who publishes | Your organisation, for its own staff | A developer, for anyone |
| Sollar review | **None** | Required |
| Verified entity | You are already a customer | Required |
| Visible to | Your organisation only | The public catalogue |
| Countersigned by | Your organisation's CA | The Sollar store key |

If you are building your own ERP for your own employees, you want **tenant-private**. Your release
cycle should not depend on a vendor's review queue, and it does not.

A package cannot be both. Declaring both channels is a validation error, not a warning.

## Tenant-private

```json title="manifest.json"
"distribution": { "channel": "tenant-private", "tenants": ["acme-corp"] }
```

```sh
sollar build
sollar upload
sollar submit --tenant acme-corp
```

There is no review. The package is countersigned by your organisation's CA, so there is still a
verifiable chain — Sollar's client refuses a package without a countersignature from either the
store or an organisation CA. What you skip is our queue, not the cryptography.

Your tenant administrator controls which mini apps are available and which permissions are allowed
organisation-wide.

## Store

```json title="manifest.json"
"distribution": { "channel": "store" }
```

```sh
sollar submit
```

You will need a verified entity — an individual with verified identity for apps that touch no
sensitive data, or a registered organisation for everything else. Sensitive categories (health,
finance, education involving minors) require additional qualification documents.

## Version states

Four states coexist:

```
development  →  trial  →  in review  →  published
(your latest    (named     (ONE at        (what users
 upload)         testers)   a time)        run)
```

**Only one version can be in review at a time.** Re-submitting **overwrites** the one in review
rather than queueing behind it.

**Trial builds reach named testers only** — project members and testers you list explicitly. They
must be members of your organisation.

## Rollout

```sh
sollar release                # everyone at once
sollar release --phased       # 1% → 2% → 5% → 10% → 20% → 50% → 100%
```

The phased curve is fixed at one step per day, and you can pause at any step. A fixed curve is
better than a free percentage because it takes the decision away from the worst moment to make it —
nobody chooses a good percentage at 3am with the error graph climbing.

## Rollback

```sh
sollar rollback 2.4.0
```

This republishes the code of `2.4.0` **as a new version number** — `2.4.2` — in about a minute,
without review.

It is not a true revert, and that is deliberate: monotonic versions are how clients know they need
to update. Moving the number backwards breaks that guarantee and creates ambiguity about what is
installed.

Rollback skips review because the code was already reviewed. Publishing never-reviewed code this way
is abuse, and the platform detects it by comparing hashes against previously approved versions.

## Mandatory updates

Sollar can force an update independently of you. This is a security mechanism: a mini app with a
known vulnerability cannot be left to its developer's release schedule.

- **Recommended** — downloaded in the background, applied on next open.
- **Mandatory** — the client refuses to open the old version. Reserved for security revocation.

## What review checks

Beyond the obvious:

1. The manifest validates, and every permission's `purpose` is plausible for what the app does.
2. Every host in the network allowlist is justifiable.
3. The CSP meets the minimum — no remote script, no `unsafe-eval`.
4. An SBOM is present and no dependency carries a known high-severity CVE.
5. No remote script loading, no `eval`, no obfuscation that defeats review.
6. `actions[]` describe honestly what they do, and `destructive` is marked where it is destructive.
7. Report and block paths work; age rating is declared.

Common rejection reasons, several inherited from what WeChat learned the hard way: induced sharing
or following (requiring a share before the app becomes usable), false or fraudulent content,
auto-playing media, cross-promotion or ranking of other mini apps — and, specific to Sollar, a
misleading manifest, actions that lie about being destructive, and any attempt to collect user
credentials inside the runtime WebView.

## Before you submit to the public store

Read [Store compliance](/compliance/). Your mini app runs inside Sollar's iOS and Android apps, and
under [Apple Guideline 4.7](/compliance/apple/) **Sollar is responsible for everything it hosts** —
a mini app that violates a guideline puts the whole host app at risk, not just itself.

The one that surprises people most: **there is no in-app payment API**, and the rules differ by
platform. See [Monetisation](/compliance/#monetisation).
