Publishing & Manifest
prebit.app.toml, full reference, and how a submission is reviewed.
A submission is a manifest (prebit.app.toml) + extension assets
(templates/CSS/sandboxed JS, if you have any) + screenshots + policy URLs.
Your backend source is never part of it — it never runs on Prebit's
infrastructure, so it isn't relevant to review.
Full manifest reference
manifest_version = 1
minimum_platform = "1.0"
runtime = "v1" # sandboxed extension-runtime version — versioned
# independently of minimum_platform
name = "Reviews"
version = "1.2.0"
developer_org = "acme-labs"
permissions = ["read_products", "read_customer_pii"]
capabilities = ["can_write_extension_storage", "can_use_billing_api"]
blocks = ["review-widget", "rating-stars"] # app_block — not built yet
embeds = ["review-popup"] # app_embed — Extension Runtime
webhooks = ["order.created", "product.deleted"] # delivered to YOUR server
background_jobs = [{ id = "sync-reviews", capability = "can_register_background_job" }]
scheduled_jobs = [{ id = "nightly-import", cron = "0 2 * * *" }]
network_origins = ["https://api.reviews-acme.com"] # sandbox connect-src allowlist ONLY
billing = "prebit" # or "external"
price = 299
[compatibility]
platform = ">=1.0"
runtime = ">=1.0"
theme = ">=2.0"
sdk = ">=0.1.0" # informational — @prebit/sdk version this was built against
cli = ">=0.1.0" # informational — prebit-cli version this was built against
[performance_budget]
bundle_kb = 150
css_kb = 30Field reference
| Field | Notes |
|---|---|
manifest_version | Must be 1 |
name | 1–80 chars |
version | Must be semver x.y.z |
permissions | Free-form strings today — scopes/capabilities aren't cross-validated against a fixed enum for permissions |
capabilities | Must be one of the known capability strings — see Authentication |
blocks / embeds | Non-empty identifiers. blocks isn't usable yet (app_block not built) |
webhooks | Short topic names — see Webhooks for the mapping |
network_origins | Each entry must be a safe public https:// origin — a connect-src allowlist only, never an executable-script allowlist |
billing | "external" (default) or "prebit" — see Billing |
price | Required, must be positive, if billing = "prebit" |
compatibility.sdk / .cli | Informational today — not enforced by the review scanner, but a template/tool can warn on a mismatch |
network_origins is a sandbox fetch-destination allowlist ONLY. It is
never treated as permission to load executable JavaScript from that
origin — every reviewed extension asset must be self-contained. See
Review Process.
Submitting
prebit build . # parses + scans locally, stages dist/
prebit publish . # re-checks, then submitsThe submission runs the full automated scan synchronously — a submission with any blocking error is rejected outright, never stored as "pending." See Review Process for exactly what's checked. A successful submission still needs manual review (permissions, screenshots, pricing) before it can be approved and installed by merchants.
Versioning
Every AppRelease is immutable — a version can't be edited in place, only
superseded by a new submission with a higher semver version. Submitting
the same version twice is rejected (409).
Signing (optional until your org registers a key)
If your DeveloperOrganization has registered a publisher signing key,
every submission must include a valid publisherSignature or it's
rejected. Orgs without a registered key yet skip this check.
import { buildReleaseSignaturePayload, signPayload } from "@prebit/sdk";
import crypto from "crypto";
const manifestHash = crypto.createHash("sha256").update(manifestToml, "utf8").digest("hex");
const payload = buildReleaseSignaturePayload(manifestHash, assetContentHashes);
const publisherSignature = signPayload(privateKeyPem, payload);prebit publish --private-key <path> does this for you.