Marketplace Allow-List
The marketplace does not host code. Services live on npm, and @zelavis/marketplace
owns the allow-list: which packages an installation may install, at exactly
which versions, and the digest each must have. Installing a service executes its
code with Platform authority, so “is this on the list” is the trust decision, and
the design exists to make that answer trustworthy.
The list
Section titled “The list”A list is a signed JSON envelope:
{ "keyId": "…", "payload": "<base64url of the list>", "signature": "<base64url Ed25519>" }The payload is { schemaVersion: 1, sequence, issuedAt, expiresAt, services: […] }.
Each service names its npm package, kind (app, plugin or frontend),
maintainer, marketplace card, and its exact versions with the sha512 integrity of
each published tarball. A range or a tag is never a listed version.
Why it can be fetched from anywhere
Section titled “Why it can be fetched from anywhere”The list is signed, so a copy from a mirror, a gist or an API is exactly as trustworthy as one from the primary. An installation is given several sources and uses the first that answers with a list it accepts. A source can never move it backwards:
- Signature. Only keys the installation trusts. Anything else is skipped.
- Sequence. Strictly increasing. A validly signed list older than one already held is a replay (it could re-open a service that was removed) and is ignored.
- Expiry. After
expiresAtthe list is stale for seven days (nothing new is installed, but running services are untouched) and then expired. - Transport. https only, no redirects, bounded size and time.
- Cache. The last accepted list is kept in the System Store and verified again on every read, so an outage changes nothing and an edited cache is ignored.
The list shipped with a release is a floor and a last resort.
The install gate
Section titled “The install gate”When the gate is on (the default), an npm install must name an exact listed
version, is refused before anything is fetched if it is not listed, and is refused
after download if the bytes do not have the listed digest. Other source kinds are
refused unless the operator configured them explicitly. allowlist: false in the
adapter’s services.marketplace option removes the gate and leaves only the
explicit source policy.
Development
Section titled “Development”In a repository checkout, ZELAVIS_OFFICIAL_SERVICES_DIR (set by pnpm dev) points
at zelavis-services/. An official service that is not installed is offered from
there instead of from npm, so it can be tried without publishing anything. It only
ever names packages in the operator’s own checkout.
Operating it
Section titled “Operating it”GET /zelavis/api/v1/runtime/marketplace/allowlist how current the list is (marketplace.view)POST /zelavis/api/v1/runtime/marketplace/allowlist/refresh fetch it again (system.services.manage)SDK: client.marketplace.allowlist() and client.marketplace.refresh().
CLI: zelavis marketplace allowlist and zelavis marketplace refresh.
Sources come from services.marketplace.sources or ZELAVIS_ALLOWLIST_SOURCES
(comma separated). The default is https://zelavis.com/allowlist.json. There are
no keys: the list is plain JSON and its https origin is the trust anchor, the same
as for the installer. A newer list applies to the catalogue at the next start.
Until that file is published, only the list shipped with the release counts.
Publishing the list
Section titled “Publishing the list”Publish changed official services before building the Platform. Then run
pnpm allowlist update, which rebuilds the list from the packages in
zelavis-services/* and the digests npm serves for them, raises sequence and
rewrites the list shipped with the release. pnpm allowlist publish then writes
a plain copy with a fresh expiry to website/public/allowlist.json, which the next
website deploy serves at https://zelavis.com/allowlist.json.
pnpm allowlist check is part of release validation and refuses defaults that
differ from the qualified service versions. A fresh runtime uses the shipped
snapshot to compose its catalogue; background refreshes apply on its next start.
Projects
Section titled “Projects”A Project has a marketplace of its own for the plugins and frontends installed into it, behind the same install gate. It never fetches the sources. The Platform hands its list to each Project (in the Project’s data folder, on every refresh and whenever the Project starts), and the Project parses it again on every read, so a malformed file is refused. The Platform is the Project’s parent authority and the folder is the Project’s own, which is the same trust a Project already places in the Platform. A Project that has been given nothing uses the list shipped with its release.