Plugins move Pomavo from a fixed ticketing product to an extensible platform you can shape per organization. You can install capabilities from a marketplace, place widgets directly on tickets, and keep each tenant in control of what runs in its workspace.
A per-organization plugin marketplace
The new marketplace gives you a central place to discover, install, update, and remove plugins for one organization at a time. That per-org installation model matters in a multi-tenant product: one team can install GitHub widgets and a theme while another team keeps the default experience.
Each plugin has a manifest with identity, version, description, categories, optional setup screens, widget definitions, lifecycle hooks, settings, and resources. Pomavo stores the manifest, readme, icon, version, release tag, and status so admins can review what they are enabling before anything appears in the UI.
| Marketplace concept | What you get |
|---|---|
| Manifest id | A stable plugin identity across versions |
| Version | A specific published build you can install or switch to |
| Release tag | Stable, beta, or alpha channel metadata |
| Categories | Browsing signals such as widget, productivity, integration, or theme |
| Readme | Plugin-provided setup and usage guidance |
| Icon | A marketplace visual, stored as a public asset |
| Status | Draft or published lifecycle control |
The install flow is permission-gated through the same admin model described in Admin. You need the right plugin permission to install, view, manage, update, or uninstall a plugin.
Plugin installation is tenant-scoped. Installing a plugin in one organization never activates it in another organization.
Versioning, update, and uninstall you can trust
Plugins are now versioned rather than treated as a single mutable record. You can publish a new version under the same manifest id, install a specific version, and switch an existing installation to a newer published version.
The update path is intentionally conservative. Pomavo checks that the target version has the same manifest id, verifies it is published, removes any duplicate target installation, deletes old cloned resources, repoints the installation, and then clones the new version's resources into the organization.
| Lifecycle action | Result |
|---|---|
| Install | Creates an enabled installation, saves default settings, clones resources, provisions integration access, and queues the install lifecycle job |
| Update | Switches the installation to the latest stable version or to a selected published version |
| Uninstall preview | Shows cloned automations, integration permissions, and API keys that can be removed |
| Uninstall | Removes the installation, optionally deletes cloned automations, cleans integration references, and queues the uninstall lifecycle job |
Lifecycle webhooks are called from the worker, not the browser. They receive install or uninstall events, organization context, the installation id, a shared secret, the Pomavo API base URL, and integration API keys when the plugin requested them.
Plugin resources: templates, workflows, and automations
The marketplace is not just a widget registry. A plugin can bring operational assets with it. Pomavo snapshots plugin resources at publish time and clones them into the installing organization at install time.
This is especially useful for repeatable process packs. You can package automations, integration references, and future resource types behind a single install flow, then let each organization receive its own copy rather than sharing mutable source records.
| Resource step | Why it matters |
|---|---|
| Validate resources | Pomavo checks that referenced resources exist in the source organization |
| Clone to snapshot org | The published plugin gets a stable resource snapshot |
| Clone to target org | Each installation receives tenant-local copies |
| Map source to cloned ids | Updates and uninstall know exactly what was created |
| Delete org resources | Uninstall can remove plugin-owned resources cleanly |
The first-party GitHub plugin
The first major plugin is GitHub. It connects repository work to Pomavo tickets by matching ticket keys such as TASK-465 in branches, commits, and pull requests. Once installed, development activity appears directly on the ticket instead of living in a separate tab.
The plugin is delivered through the same Plugins system, so you install it per organization, connect repositories through setup, and place its widgets in ticket layouts. The docs for GitHub explain the user-facing flow: reference ticket keys in branch names, commit messages, PR titles, or PR descriptions and Pomavo links the activity automatically.
| GitHub widget | What it shows |
|---|---|
github-stats | A compact activity summary for the ticket |
github-prs | Pull requests linked to the ticket, including status such as open, closed, merged, or draft |
github-commits | Commits linked by ticket key, with SHA, message, and author context |
github-branches | Branches whose names reference the ticket key |
The integration uses GitHub App installation auth through Octokit, stores the organization connection, receives secure webhook events, and indexes linked development data per organization. Ticket widgets then query by the ticket key so the panel stays fast and tenant-scoped.
Sandboxed widgets and the SDK message protocol
Widgets run in sandboxed iframes. The plugin cannot read the Pomavo DOM, cookies, local storage, or arbitrary host state. It communicates through a typed postMessage protocol wrapped by the Pomavo SDK.
The handshake is designed to be explicit:
Plugin signals ready
The iframe loads and announces that its app is initialized.
Plugin requests context
The widget asks Pomavo for the context it is allowed to see.
Host delivers context
Pomavo returns scoped settings, a short-lived plugin token, organization information, user information, and the ticket reference when rendered on a ticket.
Host pushes updates
Theme changes and other relevant host events are sent through the structured channel.
Plugin requests resize
The widget asks for the height it needs so the iframe fits the content.
This keeps extension points useful without making the host page porous. It also makes plugin behavior testable because the communication surface is explicit and typed. Read more in Extensibility and the Security Model.
Layout code for ticket screens
Ticket screens now have a JSX-like layout-code system edited in Monaco. Instead of only arranging fields through forms, you can write a layout that combines fields, labels, wrappers, plugin widgets, spacing, and triggers.
<Row>
<Column width={8}>
<Font size="lg">
<Field id="title-field" mandatory />
</Font>
<Field id="description-field" heightAutoExpand />
</Column>
<Column width={4}>
<Plugin manifestId="com.pomavo.github-integration" widgetId="github-prs" />
<Spacer height={2} />
<Collapsible title="Development" defaultExpanded>
<Plugin manifestId="com.pomavo.github-integration" widgetId="github-commits" />
</Collapsible>
</Column>
</Row>Monaco highlights tags and attributes, validates parse errors, autocompletes installed plugin manifests and widget ids, and decorates field ids with human-readable labels. The same parser concepts are shared across the web app, UI package, and backend validation so the editor and renderer stay aligned.
Layout-code tags and attributes
Layout code supports structural containers, visual wrappers, interactive wrappers, field leaves, label leaves, plugin leaves, and spacers. The system uses a 12-column grid model at the root and validates numeric ranges, unknown attributes, invalid fields, invalid labels, and overlapping cells.
| Tag | Role | Common attributes |
|---|---|---|
Row | Horizontal layout container | width, height, x, y, align |
Column | Vertical layout container | width, height, x, y, align |
Section | Grouping container | width, height, title |
Collapsible | Expandable container | title, defaultExpanded |
Color | Text color wrapper | value, from, class, id |
Font | Font size wrapper | size |
Trigger | Interaction wrapper | target |
Field | Renders a template field | id, mandatory, showIfEmpty, truncateLines, variant |
Label | Renders a system or field label | id, type, truncateLines |
Plugin | Renders a plugin widget | manifestId, widgetId |
Spacer | Adds intentional empty space | height, width |
Subdomain routing and the reverse proxy
Pomavo now supports subdomain-based organization routing at the edge. The application can serve organizations by short name, while nginx routes traffic to the right internal services and forwards the original host where needed.
That routing work is important for plugin and auth behavior. It lets cookies work across organization subdomains, keeps plugin iframes on stable origins, and prepares the product for public deployment patterns where docs, app, auth, API, plugin, and CDN hosts are separated.
The reverse proxy also became the point where development hostnames and upstream ports are injected from Aspire endpoints rather than hard-coded. That makes the local topology closer to production and reduces drift between developer machines and deployment.
Template management and operator tooling
Template management received a deeper overhaul so layouts, fields, screens, and plugin placements can evolve together. You can build ticket pages that expose just the information a team needs, then place plugin widgets where they make sense for that template.
Operators also get a stronger Admin story. The Job Explorer lets you browse jobs and runs, filter by type and status, open a run-log viewer, inspect timestamped log lines, and follow child jobs. When plugin install, uninstall, resource cloning, GitHub indexing, or automation work misbehaves, you can inspect the exact run rather than guessing.
| Admin capability | Useful when |
|---|---|
| Job list | You need to see queued, running, successful, errored, requeued, or terminated work |
| Run detail | You need payload, status, timing, and result data for a job run |
| Log viewer | You need multi-line execution logs and stack traces |
| Child job summary | You need to follow fan-out from one operation into sub-jobs |
| Search index explorer | You need to verify indexed ticket or GitHub data |
Load testing the new extension surface
The plugin and routing work added more moving pieces: iframe widgets, lifecycle callbacks, marketplace flows, GitHub ingest, admin job pages, and per-organization routing. The k6 load-test suite gives you a repeatable way to exercise those public paths under pressure.
The goal is not just throughput. You want to know that tenant scoping remains intact, the API stays responsive while background work continues in the Job Pipeline, and widget-heavy ticket pages do not turn into a bottleneck.
Extensible core
New capabilities can ship as plugins instead of core product changes.
Tenant choice
Each organization installs, updates, and removes only the plugins it needs.
Safe widgets
Sandboxed iframes and typed SDK messages keep host and plugin boundaries clear.
Operational visibility
Admin job logs make plugin lifecycle and resource cloning observable.
Next, the same plugin foundation can support richer marketplace packs, more first-party integrations, and deeper widget placement across Pomavo without weakening tenant isolation.