Skip to content

Packaging and signing ​

Package ​

To give your extension to someone, package it. With its folder loaded (see Developing from a folder), open the app's ⋯ menu and choose Package…. Sorus writes one file, <id>-<version>.pagesapp.

They install it with + beside Apps › Install from a file…. Sorus shows what it brings and builds on, and lets them map your types onto theirs, before installing.

A .pagesapp is a JSON file holding every file of the extension:

json
{ "format": "pages-app", "version": 1, "files": { "manifest.json": "<base64>", "…": "…" } }

Updates ​

Bump version and package again. Installing a newer version over an older one updates it, keeping the person's objects; Sorus refuses to replace a version with an older one. An update that asks for more needs approving again; see Permissions.

Installed extensions live in the workspace, so they sync to the person's other devices.

Signing ​

Extensions made by Sorus are signed with its key, which earns them the trusted tier. The signature is signature.json, at the top of the folder:

json
{ "keyId": "pages-2026", "digest": "<hex>", "signature": "<base64>" }
  • digest is a SHA-256 over every other file: for each file, sorted by path, the line path\0<sha-256 of the file, hex>\n.
  • signature is an Ed25519 signature of the digest, by the key keyId names.

When Sorus reads an extension:

  • no signature.json: unsigned, so sandboxed;
  • a signature that matches, by a key Sorus trusts: signed;
  • a key Sorus doesn't know, or files changed after signing: a package is refused. A folder being developed just reads as unsigned.

In the pages-apps repository, node scripts/sign.mjs signs every extension, or node scripts/sign.mjs movies one. The private key lives outside the repositories, in ../.signing/ or wherever $PAGES_SIGNING_KEY points.