Plugin-Plattform

Wie Owlat erweitert wird: ein validiertes Manifest, ein Capability-Modell und drei Ausführungsstufen.

Die Variationspunkte von Owlat — Versandtransporte, Agentenschritte, Entwurfsstrategien, Autonomie-Gates, Automatisierungen, Webhook-Events, Import-Provider, Crons, Navigation, Einstellungen — sind alle über Plugins erreichbar. Ein Plugin ist ein npm-Paket, das ein validiertes Manifest exportiert und optional statische Module hinter den Verträgen aus @owlat/plugin-kit.

Die Plattform hat drei bewusst gewählte Eigenschaften:

  1. Ein Manifest. Alles, was der Host braucht, um ein Plugin zusammenzusetzen, zu berechtigen, per Flag zu steuern, zu budgetieren und darzustellen, sind Daten in definePlugin(...). Die Validierung ruft niemals Plugin-Code auf.
  2. Deklaration ist keine Befugnis. Ein Manifest fordert Capabilities an. Ein Betreiber gewährt sie. Beides wird zum Zeitpunkt jeder vom Host durchgeführten Operation erneut geprüft.
  3. Kein beliebiger Laufzeitcode. Nichts lädt zur Laufzeit JavaScript in Convex oder in den Browser. Gebündelter Code wird zur Build-Zeit komponiert; nicht vertrauenswürdiger Code läuft außerhalb des Prozesses (eine verbundene App) oder hinter einer Betriebssystemgrenze (ein Sandbox-Worker-Job).
Wo die Verträge liegen

@owlat/plugin-kit ist die öffentliche Kompatibilitätsgrenze und das einzige Paket, das ein Plugin-Autor importiert. Seine Major-Version ist die Kompatibilitätslinie — einzelne Contribution-Schnittstellen tragen keine eigenen Versionen. Vor 1.0 folgt es der Version des Owlat-Repositorys, und Verträge können sich zusammen mit der Anwendung brechend ändern.

Die drei Stufen

StufeWas es istInstallationVertrauen
1 — Gebündeltes PluginEin npm-Paket, das in plugins.config.ts gelistet und in die Convex- und Nuxt-Builds komponiert wirdKonfiguration bearbeiten → Codegen → Rebuild → DeploymentDasselbe Vertrauen wie der eigene deployte Code des Betreibers. Capabilities und Flags reduzieren die Befugnis; sie sind keine Sandbox
2 — Verbundene AppEin externer HTTPS-Dienst mit plugin-gebundenen API-Keys und Webhooks, dazu ein spezifiziertes signiertes synchrones Hook-Protokoll, dessen Laufzeit-Adapter nicht mitgeliefert wird — siehe Verbundene AppsIm Dashboard registrieren; sofort wirksam, ohne RebuildNicht vertrauenswürdiger Netzwerk-Peer. Jede Antwort wird strikt validiert, bereinigt, geklemmt und begrenzt
3 — Sandbox-Worker-JobEin spezifiziertes Worker-Protokoll hinter der code-worker-Betriebssystemgrenze; ein hostseitiger Enqueue-Adapter wird nicht mitgeliefertReserviertNicht vertrauenswürdiger Prozess. Keine ambienten Zugangsdaten, harte Obergrenzen für CPU/Speicher/Zeit, vom Host kontrolliertes Kommando

Für jede Stufe gibt es ein gepflegtes Referenz-Plugin:

StufeReferenzWas es beisteuert
1examples/plugins/escalation-guardEinen Agentenschritt, eine Entwurfsstrategie, alle drei Automatisierungs-Registries, ein Webhook-Event sowie Navigations- und Einstellungseinträge — alles im selben Prozess
2examples/plugins/slack-approvalsEin rein einschränkendes Hold-Gate, das außerhalb des Prozesses über das signierte Hook-Protokoll bedient wird; überhaupt keine In-Process-Beiträge
3examples/plugins/deliverability-labEinen Seed-List-Job auf der Sandbox-Queue, dazu ein Tier-1-Versand-Gate, Cron- und UI-Einträge sowie llm:invoke für host-vermittelte Generierung

Ein Plugin kann mehrere Stufen gleichzeitig nutzen, so wie es das Deliverability Lab tut. examples/conformance treibt bei jedem Testlauf alle drei durch den echten Host, das Codegen und das CLI.

Anatomie eines Plugins

import { definePlugin } from '@owlat/plugin-kit';

export const helloPlugin = definePlugin({
    id: 'hello-owlat',
    version: '0.1.0',
    capabilities: ['plugin-storage:read', 'plugin-storage:write'],
    // Storage capabilities REQUIRE a flag: access must be revocable at runtime.
    flag: { default: false },
});
FeldBedeutung
idKleingeschriebenes Kebab-Case, ≤ 64 Zeichen. Bildet den Namensraum für Flags, Storage, Ausgaben, Audit-Zuordnung und jede beigesteuerte Art
versionSemantische Version
capabilitiesAngeforderte Host-Operationen, domain:action, exakte Übereinstimmung, höchstens 64
contributesReine Datendeskriptoren je Contribution-Bucket, höchstens 256 pro Bucket
flag{ default, requiredEnvVars? }. Erforderlich, sobald das Plugin irgendetwas beisteuert, Plugin-Storage anfordert oder llm:invoke anfordert
llmBudget{ dailyUsd }. Zusammen mit llm:invoke erforderlich; eine harte Obergrenze pro UTC-Tag
componentEin bedingungsunabhängiger Convex-Component-Export, installiert unter einem injektiven plugin_<id>-Namensraum
settingsSchemaDeklaratives Betreiberformular; der Host rendert, validiert und redigiert es

Wie ein gebündeltes Plugin in die Produktion gelangt

  1. Der Paketname wird der eingecheckten plugins.config.ts im Wurzelverzeichnis hinzugefügt.
  2. bun run plugins:codegen (oder owlat-plugins codegen) prüft Identität, Lockfile-Integrität und Realpath-Eingrenzung des installierten Pakets, importiert ausschließlich dessen Manifest-Einstiegspunkt, validiert einen unveränderlichen Snapshot und schreibt die eingecheckten Convex- und Nuxt-Kompositionsdateien, sortiert nach Manifest-ID.
  3. Builds und CI führen bun run plugins:check aus, sodass eine veraltete oder ungültige Komposition den Build fail-closed scheitern lässt.
  4. Das Deployment wird neu gebaut. Das Feature-Flag des Plugins startet mit seinem deklarierten Standardwert — normalerweise false —, sodass nichts läuft, bis ein Betreiber es aktiviert und Capabilities gewährt.
Ein Manifest ist keine Sandbox

Der Code eines gebündelten Plugins läuft in Owlats eigenen Prozessen. Capability-Deklarationen, Gewährungen, Flags und host-vermittelte Dienste reduzieren, was ein gebündeltes Plugin erreichen kann, und machen seine Aktionen zuordenbar — sie schließen feindlichen Code nicht ein. Alles, dem Sie nicht vollständig vertrauen, gehört in eine verbundene App (Stufe 2) oder einen Sandbox-Job (Stufe 3).

Paketübersicht

PaketRolle
packages/plugin-kitÖffentliche Verträge: definePlugin, Capability-Konstanten, jeder Contribution-Typ. Das einzige Paket, das ein Plugin importiert
packages/plugin-hostPrivater, laufzeitneutraler Durchsetzungskern, den sich Convex und Nuxt teilen: Capability-Prüfungen, Flags, Reihenfolge, Gate-Ergebnisse, Policy für nicht vertrauenswürdigen Text
packages/plugin-codegenBuild-Werkzeug, dem der einzige Kompositionspunkt und die generierten Kataloge/Registries gehören
packages/plugin-cliowlat-plugins — create, add, remove, codegen, dev
examples/plugins/*Gepflegte Referenz-Plugins, die die echten Contribution-Punkte durchspielen
examples/conformanceDie Konformitätsgalerie: Lifecycle-Suites (install/add/remove/disable/upgrade) und Full-Pipeline-Replay-Suites über diesen Referenzen, dazu der Paritätsnachweis für Plugin-Provider — ein Fixture-ESP-Bundle, das durch die ausgelieferten Module für Routing, Dispatch, Messung, Return-Path und Zugangsdatenformulare getrieben wird

Weiterlesen

Architekturentscheidungen: ADR-0049 (Plattformvertrag), ADR-0050 (Entwurfsstrategien), ADR-0051 (geordnete Autonomie-Gates), ADR-0052 (verbundene Apps und signierte Hooks), ADR-0053 (Sandbox-Plugin-Jobs).