Plugin Installation & Security
PluginInstallation, PluginApiKey, and PluginPermissionGrant — the three entities managing per-tenant plugin deployment, API authentication, and permission grants.
When a tenant installs a plugin, three core entities are created: a PluginInstallation record tracking deployment state, a PluginApiKey for secure plugin-to-platform API calls, and PluginPermissionGrant records for each platform capability the plugin is allowed to access.
PluginInstallation Entity
Represents a tenant's installation of a specific PluginDefinition at a particular PluginVersion. A tenant can install the same plugin only once — enforced by a unique constraint on (TenantId + PluginDefinitionId).
| Field | Type | Description |
|---|---|---|
| Id | Guid | Primary key |
| PluginDefinitionId | Guid | FK to the installed PluginDefinition |
| TenantId | Guid | Tenant that installed this plugin (unique per TenantId + PluginDefinitionId) |
| PluginVersionId | Guid | FK to the specific PluginVersion pinned at install time |
| Status | InstallationStatus | Installation lifecycle status (Installing, Active, Inactive, Error, default: Installing) |
| SettingsJson | string? | Tenant-specific configuration overrides as a JSON blob |
| InstalledAt | DateTime | UTC timestamp when the install was initiated |
| InstalledByUserId | Guid | Admin user who triggered the installation |
| LastHealthCheckAt | DateTime? | UTC timestamp of the most recent health check (null = never checked) |
| HealthCheckPassing | bool | Whether the latest health check succeeded (default: true) |
| ConsecutiveHealthCheckFails | int | Count of consecutive health-check failures; reset to 0 on recovery |
Installation Lifecycle
A PluginInstallation starts in Installing status while the platform provisions resources, then transitions to Active. Admins can deactivate/reactivate it. Persistent health-check failures move it to Error.
PluginApiKey Entity
Represents an API key issued to a plugin installation for authenticating plugin-to-platform API calls. Stores the hashed key value, a human-readable prefix for identification, activation status, and optional expiration.
| Field | Type | Description |
|---|---|---|
| Id | Guid | Primary key |
| PluginInstallationId | Guid | FK to the plugin installation this key authenticates |
| TenantId | Guid | Tenant scope for this API key |
| KeyHash | string | Bcrypt / SHA-256 hash of the actual key value (never stored plain) |
| KeyPrefix | string | Human-readable prefix shown in the UI for identification (e.g. "sk_plug_abc") |
| IsActive | bool | Whether this key is currently active and can be used for authentication (default: true) |
| ExpiresAt | DateTime? | Optional expiration timestamp (null = never expires) |
| LastUsedAt | DateTime? | UTC timestamp of the most recent successful API call using this key |
PluginPermissionGrant Entity
Records an explicit permission grant to a plugin installation within a tenant. Each grant authorizes the plugin to access a specific platform capability. Platform admins must explicitly approve each permission during the installation setup wizard.
| Field | Type | Description |
|---|---|---|
| Id | Guid | Primary key |
| PluginInstallationId | Guid | FK to the installation receiving this permission grant |
| TenantId | Guid | Tenant scope for this grant |
| Permission | string | Platform capability being granted (e.g. "users.read", "invoices.create") |
| GrantedByUserId | Guid | Admin user who explicitly approved this permission grant |