# at.happyproto.plugin.v1

> Published by [happyproto.at](https://lexicon.garden/identity/did:plc:mo7vq4jbioxwafy5zkcc3eux)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:mo7vq4jbioxwafy5zkcc3eux/at.happyproto.plugin.v1)
- [Documentation](https://lexicon.garden/lexicon/did:plc:mo7vq4jbioxwafy5zkcc3eux/at.happyproto.plugin.v1/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:mo7vq4jbioxwafy5zkcc3eux/at.happyproto.plugin.v1/examples)

## Definitions

### `at.happyproto.plugin.v1#image`

**Type**: `object`

A presentation image. SVG is not accepted, because it can carry script and renders in an operator's dashboard.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `alt` | `string` | No | A description of the image for people who cannot see it. |
| `height` | `integer` | Yes |  |
| `image` | `blob` | Yes |  |
| `width` | `integer` | Yes |  |

### `at.happyproto.plugin.v1`

**Type**: `object`

A HappyView plugin, as one entry in a software.release.manifest's `artifacts`. It carries the module and its manifest.json as blobs, so they are verified by their CIDs, and the manifest's facts in the signed record, so a consent screen renders without downloading the module. Those facts are not trusted: the loader checks them against the module itself and refuses a plugin that misstates what it does. The registry refuses a manifest whose artifact breaks a rule stated here, including the ones a lexicon cannot express.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `allowedHosts` | `array` | No | Hosts the module's outbound requests may reach. |
| `apiVersion` | `string` | Yes | The plugin API version the module targets. Its major version must be 2 or later. |
| `banner` | `ref` → `#image` | No | A wide image shown at the top of the plugin's page. |
| `capabilities` | `array` | Yes | What the module may do. The loader checks it against the module's imports, so a plugin cannot import what this does not cover. |
| `fileExtensions` | `array` | No | Required for an interpreter: the file extensions of the scripts it runs, without the dot. Each is 1 to 16 lowercase letters or digits, none is `json`, and none repeats. |
| `languageId` | `string` | No | Required for an interpreter: the script type it runs. |
| `license` | `string` | Yes | An SPDX expression, or `proprietary`. |
| `manifest` | `blob` | Yes | The module's manifest.json. A module stored as a blob has no directory beside it to hold a sibling file, so this is what says how to load it. |
| `namespace` | `string` | No | Required for a library: the name scripts load it by, which is unique across a HappyView's installed plugins. |
| `package` | `blob` | Yes | The WASM module. |
| `pluginType` | `string` | Yes | What the plugin is. Any other value is refused. |
| `requires` | `unknown` | No | Dependencies, as a map a lexicon cannot type. Each key is `env:<name>`, such as `env:happyview`, or the at-uri of a software.release.project; each value is a Cargo version requirement, such as `>=3.0.0` or `^1.0`, without `\|\|`. |
| `screenshots` | `array` | No |  |
| `sections` | `ref` → `#sections` | Yes |  |

### `at.happyproto.plugin.v1#sections`

**Type**: `object`

Long-form CommonMark shown on the plugin's page. It is rendered as untrusted input, with raw HTML stripped.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `description` | `string` | Yes |  |
| `installation` | `string` | No |  |
| `security` | `string` | No |  |

## Raw Schema

```json
{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "image": {
      "description": "A presentation image. SVG is not accepted, because it can carry script and renders in an operator's dashboard.",
      "properties": {
        "alt": {
          "description": "A description of the image for people who cannot see it.",
          "maxGraphemes": 300,
          "maxLength": 3000,
          "type": "string"
        },
        "height": {
          "minimum": 1,
          "type": "integer"
        },
        "image": {
          "accept": [
            "image/png",
            "image/jpeg",
            "image/webp",
            "image/gif",
            "image/avif"
          ],
          "maxSize": 1000000,
          "type": "blob"
        },
        "width": {
          "minimum": 1,
          "type": "integer"
        }
      },
      "required": [
        "image",
        "width",
        "height"
      ],
      "type": "object"
    },
    "main": {
      "description": "A HappyView plugin, as one entry in a software.release.manifest's `artifacts`. It carries the module and its manifest.json as blobs, so they are verified by their CIDs, and the manifest's facts in the signed record, so a consent screen renders without downloading the module. Those facts are not trusted: the loader checks them against the module itself and refuses a plugin that misstates what it does. The registry refuses a manifest whose artifact breaks a rule stated here, including the ones a lexicon cannot express.",
      "properties": {
        "allowedHosts": {
          "description": "Hosts the module's outbound requests may reach.",
          "items": {
            "maxLength": 256,
            "type": "string"
          },
          "type": "array"
        },
        "apiVersion": {
          "description": "The plugin API version the module targets. Its major version must be 2 or later.",
          "maxLength": 16,
          "type": "string"
        },
        "banner": {
          "description": "A wide image shown at the top of the plugin's page.",
          "ref": "#image",
          "type": "ref"
        },
        "capabilities": {
          "description": "What the module may do. The loader checks it against the module's imports, so a plugin cannot import what this does not cover.",
          "items": {
            "maxLength": 128,
            "type": "string"
          },
          "type": "array"
        },
        "fileExtensions": {
          "description": "Required for an interpreter: the file extensions of the scripts it runs, without the dot. Each is 1 to 16 lowercase letters or digits, none is `json`, and none repeats.",
          "items": {
            "maxLength": 16,
            "minLength": 1,
            "type": "string"
          },
          "maxLength": 8,
          "minLength": 1,
          "type": "array"
        },
        "languageId": {
          "description": "Required for an interpreter: the script type it runs.",
          "maxLength": 64,
          "type": "string"
        },
        "license": {
          "description": "An SPDX expression, or `proprietary`.",
          "maxLength": 256,
          "type": "string"
        },
        "manifest": {
          "accept": [
            "application/json"
          ],
          "description": "The module's manifest.json. A module stored as a blob has no directory beside it to hold a sibling file, so this is what says how to load it.",
          "maxSize": 1000000,
          "type": "blob"
        },
        "namespace": {
          "description": "Required for a library: the name scripts load it by, which is unique across a HappyView's installed plugins.",
          "maxLength": 256,
          "type": "string"
        },
        "package": {
          "accept": [
            "application/wasm"
          ],
          "description": "The WASM module.",
          "maxSize": 16777216,
          "type": "blob"
        },
        "pluginType": {
          "description": "What the plugin is. Any other value is refused.",
          "knownValues": [
            "auth",
            "library",
            "interpreter"
          ],
          "type": "string"
        },
        "requires": {
          "description": "Dependencies, as a map a lexicon cannot type. Each key is `env:<name>`, such as `env:happyview`, or the at-uri of a software.release.project; each value is a Cargo version requirement, such as `>=3.0.0` or `^1.0`, without `||`.",
          "type": "unknown"
        },
        "screenshots": {
          "items": {
            "ref": "#image",
            "type": "ref"
          },
          "maxLength": 8,
          "type": "array"
        },
        "sections": {
          "ref": "#sections",
          "type": "ref"
        }
      },
      "required": [
        "package",
        "manifest",
        "pluginType",
        "apiVersion",
        "capabilities",
        "license",
        "sections"
      ],
      "type": "object"
    },
    "sections": {
      "description": "Long-form CommonMark shown on the plugin's page. It is rendered as untrusted input, with raw HTML stripped.",
      "properties": {
        "description": {
          "maxGraphemes": 2000,
          "maxLength": 20000,
          "type": "string"
        },
        "installation": {
          "maxGraphemes": 2000,
          "maxLength": 20000,
          "type": "string"
        },
        "security": {
          "maxGraphemes": 2000,
          "maxLength": 20000,
          "type": "string"
        }
      },
      "required": [
        "description"
      ],
      "type": "object"
    }
  },
  "id": "at.happyproto.plugin.v1",
  "lexicon": 1
}
```
