<!-- Source: https://docs.biosimulant.com/references/desktop-plugins/packaging -->

# Packaging & Distribution

Plugins are distributed as `.bsiplugin` archives (ZIP files with a specific structure). The Biosimulant platform provides a build script, a plugin registry, and multiple installation paths.

## Package Structure

A `.bsiplugin` archive contains:

```
my-plugin.bsiplugin (ZIP)
├── plugin.json                  # Plugin manifest (required)
├── main.py                      # Your entrypoint script
├── bin/                         # Compiled binaries (auto-marked executable)
│   └── my-tool-aarch64-apple-darwin
├── runtime/                     # Runtime dependencies (auto-marked executable)
│   └── ...
├── integrity/
│   ├── sha256sums.txt           # SHA-256 checksums for every file
│   └── signature.json           # Cryptographic signature
└── ... (any other files your plugin needs)
```

**Info:**

  Files under `bin/` and `runtime/` directories are automatically given executable permissions (0o755) when packaged.

## Building a Package

Use the provided build script to create a `.bsiplugin` archive:

```bash
python scripts/build_plugin_package.py \
  --manifest plugins/my-plugin/plugin.json \
  --payload-dir plugins/my-plugin/ \
  --output artifacts/plugins/my-plugin.bsiplugin
```

### Parameters

| Flag | Required | Description |
|------|----------|-------------|
| `--manifest` | Yes | Path to your `plugin.json` file |
| `--payload-dir` | Yes | Directory containing all files to include in the package |
| `--output` | Yes | Output `.bsiplugin` file path |
| `--signer-id` | No | Signer identifier embedded in the signature |
| `--signing-key` | No | Path to Ed25519 private key PEM, or the PEM value itself |

### Signing

Packages can be signed with Ed25519 keys for integrity verification. Without a signing key, the build script generates a SHA-256 checksum-only signature.

```bash
# Generate a signing key pair
python -c "
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
key = Ed25519PrivateKey.generate()
print(key.private_bytes(serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()).decode())
" > my-signing-key.pem

# Build with signing
python scripts/build_plugin_package.py \
  --manifest plugins/my-plugin/plugin.json \
  --payload-dir plugins/my-plugin/ \
  --output artifacts/plugins/my-plugin.bsiplugin \
  --signer-id "my-org" \
  --signing-key my-signing-key.pem
```

You can also set the `BIOSIMULANT_PLUGIN_SIGNING_KEY` environment variable instead of passing `--signing-key`.

**Warning:**

  Keep your signing key private. If compromised, contact the Biosimulant team to rotate or revoke the signer.

## Distribution Paths

There are three ways to distribute your plugin:

### 1. Local Install (Development)

Install a `.bsiplugin` file directly in the desktop app. Go to **Settings > Plugins** and click **Install from file**, or use the **Plugins** page.

- No registry account needed
- Unsigned packages prompt the user for explicit trust
- Ideal for development and testing

### 2. Registry Upload (Production)

Upload your package to the Biosimulant plugin registry for public distribution.

Go to **Settings > Plugins** and click **Upload to registry**. You can optionally add release notes and choose whether to submit for review immediately.

## Release Lifecycle

Registry releases follow this status workflow:

```
DRAFT → PENDING_APPROVAL → APPROVED → PUBLISHED
                ↓
            REJECTED

PUBLISHED → UNPUBLISHED (reversible)
```

| Status | Visibility |
|--------|------------|
| `DRAFT` | Only visible to the uploader |
| `PENDING_APPROVAL` | Visible to admins for review |
| `APPROVED` | Ready to publish |
| `PUBLISHED` | Visible to all users in the marketplace |
| `REJECTED` | Not visible; uploader can submit a new version |
| `UNPUBLISHED` | Removed from marketplace; can be re-published |

## Compatibility Filtering

The desktop app queries the registry with its version, platform, and architecture. The registry returns only compatible plugins.

Your plugin's `platforms`, `architectures`, and `min_desktop_version` fields control which desktop installations see your plugin in the marketplace.

## Updates

Users can check for updates from **Settings > Plugins** (per-plugin "Check update" button) or from the **Plugins** page. The desktop app compares the installed version against the latest published version in the registry.
