// manifest.proto — the static plugin manifest (WO-WZ-001). // // PluginManifest is the wire form of everything that is *static data* in // core/plugin/registration.go (PluginRegistration). It is produced once at // publish time by calling the guest's DESCRIBE hook and stored as manifest.pb // inside the .bnp artifact; the CMS loader reads it without instantiating the // wasm module. // // Function-valued registration fields cannot cross the wire; they map to // either a hook (Load/Unload/JobHandlers/MediaHooks/HTTPHandler), a boolean // presence flag here, or an artifact directory (Assets → assets/, // Schemas → schemas/, Migrations → migrations/). See core/docs/wasm-abi.md // for the full field-by-field mapping. syntax = "proto3"; package abi.v1; option go_package = "git.dev.alexdunmow.com/block/pluginsdk/abi/v1;abiv1"; // PluginManifest mirrors the static surface of plugin.PluginRegistration. message PluginManifest { // ABI major version the plugin was built against. The host rejects // manifests whose major version it does not support. uint32 abi_version = 1; // PluginRegistration.Name / .Version. string name = 2; string version = 3; // PluginRegistration.Dependencies. repeated Dependency dependencies = 4; // Blocks registered via BlockRegistry.Register (captured by DESCRIBE). repeated BlockMeta blocks = 5; // Blocks registered via BlockRegistry.RegisterTemplateOverride[WithSource]. repeated BlockTemplateOverride block_template_overrides = 6; // Templates registered via TemplateRegistry (captured by DESCRIBE). repeated string template_keys = 7; // TemplateRegistry.Register repeated SystemTemplateMeta system_templates = 8; // RegisterSystemTemplate repeated PageTemplateMeta page_templates = 9; // RegisterPageTemplate repeated string email_wrapper_system_keys = 10; // RegisterEmailWrapper // PluginRegistration.AdminPages. repeated AdminPage admin_pages = 11; // PluginRegistration.SettingsSchema / .ThemePresets / .BundledFonts (JSON). bytes settings_schema = 12; bytes theme_presets = 13; bytes bundled_fonts = 14; // PluginRegistration.MasterPages. repeated MasterPageDefinition master_pages = 15; // PluginRegistration.AIActions. repeated AiAction ai_actions = 16; // RBAC roles for the plugin's own Connect services, merged from // ServiceRegistration (full method name → role, e.g. // "/symposium.v1.ForumService/CreateThread" → "admin"). map rbac_method_roles = 17; // PluginRegistration.CSSManifest. CssManifest css_manifest = 18; // PluginRegistration.RequiredIconPacks. repeated string required_icon_packs = 19; // PluginRegistration.DirectoryExtensions (static fields only; the // panel-section / pin-decorator callbacks are counted so the host knows // how many guest callbacks exist). DirectoryExtensions directory_extensions = 20; // Job types the plugin handles (keys of PluginRegistration.JobHandlers). // The host dispatches these via the JOB hook. repeated string job_types = 21; // Content types the plugin registered RAG content fetchers for // (RAGService.RegisterContentFetcher inverts to a manifest declaration; // the host calls back via the RAG_FETCH hook). repeated string rag_content_fetcher_types = 22; // PluginRegistration.SettingsPanel — Module Federation path of the // settings panel component ("" when the plugin has none). string settings_panel = 23; // Presence flags for function-valued registration fields that invert to // hooks at runtime. bool has_http_handler = 24; // PluginRegistration.HTTPHandler → HANDLE_HTTP bool has_load_hook = 25; // PluginRegistration.Load → LOAD bool has_unload_hook = 26; // PluginRegistration.Unload → UNLOAD bool has_media_hooks = 27; // PluginRegistration.MediaHooks → MEDIA_HOOK bool has_provisioner = 28; // PluginRegistration.RegisterWithProvisioner // Core CMS services the plugin mounts with custom RBAC roles // (CoreServiceBindings.Bind becomes a static declaration; the host // constructs and mounts the handlers). repeated CoreServiceBinding core_service_bindings = 29; // data_dir requests a persistent per-plugin /data preopen at load. Its // source of truth is the plugin.mod `data_dir = true` key, which lives // outside the guest code, so DESCRIBE cannot populate it: the packer // (`ninja plugin build`) stamps it into the manifest from plugin.mod so // the loader reads one source. OFF by default. bool data_dir = 30; // Template tags the plugin provides (blocks.RegisterTag). For each name the // host registers a pongo2 tag that invokes the guest via HOOK_RENDER_TAG. // Captured by DESCRIBE from the blocks tag registry (Register-time). repeated string declared_tags = 31; // Template filters the plugin provides (blocks.RegisterFilter). For each // name the host registers a pongo2 filter that invokes the guest via // HOOK_APPLY_FILTER. Captured by DESCRIBE from the blocks filter registry. repeated string declared_filters = 32; // codeless marks a declarative artifact with NO plugin.wasm (WO-WZ-020): // the host runs it entirely — block definitions from the artifact's // blocks/ dir (blocks.yaml manifest-FS layout), seed data from seed/, // assets/migrations as usual — and never instantiates a guest. A codeless // manifest MUST NOT declare any computing hook (http handler, jobs, // load/unload, RAG fetchers, media hooks, tags/filters, provisioner, // service bindings, directory callbacks); the packer and the host reader // both reject the combination. Not produced by DESCRIBE (there is no guest // to describe): `ninja plugin build` synthesizes the manifest from // plugin.mod + the artifact's declarative files. bool codeless = 33; } // Dependency mirrors plugin.Dependency. message Dependency { string plugin = 1; string min_version = 2; bool required = 3; } // BlockMeta mirrors blocks.BlockMeta. Source is omitted: the host assigns it // from the manifest's plugin name at load time. message BlockMeta { string key = 1; string title = 2; string description = 3; // blocks.BlockCategory string ("content", "layout", "navigation", "blog", // "theme"). string category = 4; bool has_internal_slot = 5; bool hidden = 6; string editor_js = 7; } // BlockTemplateOverride captures BlockRegistry.RegisterTemplateOverride and // RegisterTemplateOverrideWithSource registrations. message BlockTemplateOverride { string template_key = 1; string block_key = 2; // Override source label; empty for plain RegisterTemplateOverride. string source = 3; } // SystemTemplateMeta mirrors templates.SystemTemplateMeta. message SystemTemplateMeta { string key = 1; string title = 2; string description = 3; } // PageTemplateMeta mirrors templates.PageTemplateMeta plus the system // template it was registered under. message PageTemplateMeta { string system_key = 1; string key = 2; string title = 3; string description = 4; repeated string slots = 5; } // AdminPage mirrors plugin.AdminPage. message AdminPage { string key = 1; string title = 2; string icon = 3; string route = 4; } // AiAction mirrors plugin.AIAction. message AiAction { string key = 1; string title = 2; string description = 3; string default_provider = 4; string default_model = 5; } // CssManifest mirrors plugin.CSSManifest. message CssManifest { map npm_packages = 1; repeated string css_directives = 2; string input_css_append = 3; } // DirectoryExtensions mirrors the static fields of plugin.DirectoryExtensions. message DirectoryExtensions { repeated string boolean_filter_fields = 1; repeated string select_filter_fields = 2; map badge_labels = 3; // Counts of the callback slices (PanelSections / PinDecorators) so the host // knows how many guest callbacks the plugin registered. Their invocation // hook is a runtime-WO concern. uint32 panel_section_count = 4; uint32 pin_decorator_count = 5; } // BadgeLabel mirrors the [2]string value of DirectoryExtensions.BadgeLabels. message BadgeLabel { string positive = 1; string negative = 2; } // MasterPageDefinition mirrors plugin.MasterPageDefinition. message MasterPageDefinition { string key = 1; string title = 2; repeated string page_templates = 3; repeated MasterPageBlock blocks = 4; } // MasterPageBlock mirrors plugin.MasterPageBlock. message MasterPageBlock { string block_key = 1; string title = 2; // JSON encoding of the block's content map. bytes content_json = 3; optional string html_content = 4; string slot = 5; int32 sort_order = 6; } // CoreServiceBinding mirrors a plugin.CoreServiceBindings.Bind call: mount // the named core-provided Connect service with these RBAC roles. message CoreServiceBinding { string service_name = 1; map method_roles = 2; }