mirror of
https://github.com/different-ai/openwork
synced 2026-04-25 17:15:34 +02:00
Introduce org-scoped marketplaces so teams can curate and share groups of plugins with consistent access rules. This adds the schema, admin routes, RBAC updates, and PRD coverage needed for marketplace-backed plugin catalogs. Co-authored-by: src-opn <src-opn@users.noreply.github.com>
8.6 KiB
8.6 KiB
New Plugin Arch Admin API
This document describes the authenticated admin/API-consumer surface for managing the new plugin architecture.
Use this for:
- OpenWork admin UI
- direct authenticated API clients
- backend route planning
Base prefix:
/v1/orgs/:orgId/...
Principles
- expose logical resources, not raw tables;
- return current projections for current-state list/detail endpoints;
- keep version history endpoints explicit;
- keep connector sync async and observable;
- keep type-specific convenience endpoints optional but available where UI clarity benefits.
Current implementation note:
- until dedicated org-capability persistence exists, create/manage-account style admin actions are gated by org owner/admin membership in the endpoint layer.
Config objects
List/search config objects
GET /v1/orgs/:orgId/config-objects
Suggested query params:
typestatussourceModepluginIdconnectorInstanceIdqlimitcursorincludeDeleted
Returns one row per config object, not one row per version.
Get one config object
GET /v1/orgs/:orgId/config-objects/:configObjectId
Create config object
POST /v1/orgs/:orgId/config-objects
Suggested body shape:
{
"type": "skill",
"sourceMode": "cloud",
"pluginIds": ["plugin_123"],
"input": {
"rawSourceText": "...",
"parserMode": "opencode"
}
}
Create a new version for an object
POST /v1/orgs/:orgId/config-objects/:configObjectId/versions
Suggested body shape:
{
"input": {
"rawSourceText": "..."
},
"reason": "manual edit"
}
Lifecycle endpoints
POST /v1/orgs/:orgId/config-objects/:configObjectId/archivePOST /v1/orgs/:orgId/config-objects/:configObjectId/deletePOST /v1/orgs/:orgId/config-objects/:configObjectId/restore
Object/plugin membership endpoints
GET /v1/orgs/:orgId/config-objects/:configObjectId/pluginsPOST /v1/orgs/:orgId/config-objects/:configObjectId/pluginsDELETE /v1/orgs/:orgId/config-objects/:configObjectId/plugins/:pluginId
Object access endpoints
GET /v1/orgs/:orgId/config-objects/:configObjectId/accessPOST /v1/orgs/:orgId/config-objects/:configObjectId/accessDELETE /v1/orgs/:orgId/config-objects/:configObjectId/access/:grantId
Config object versions
GET /v1/orgs/:orgId/config-objects/:configObjectId/versionsGET /v1/orgs/:orgId/config-objects/:configObjectId/versions/:versionIdGET /v1/orgs/:orgId/config-objects/:configObjectId/versions/latestGET /v1/orgs/:orgId/config-objects/:configObjectId/versions/compare?from=:versionA&to=:versionB
Type-specific convenience endpoints
These should sit on top of the shared config-object model.
Skills
GET /v1/orgs/:orgId/skillsPOST /v1/orgs/:orgId/skillsGET /v1/orgs/:orgId/skills/:configObjectIdPOST /v1/orgs/:orgId/skills/:configObjectId/versionsPOST /v1/orgs/:orgId/skills/validatePOST /v1/orgs/:orgId/skills/preview
Agents
GET /v1/orgs/:orgId/agentsPOST /v1/orgs/:orgId/agentsGET /v1/orgs/:orgId/agents/:configObjectIdPOST /v1/orgs/:orgId/agents/:configObjectId/versionsPOST /v1/orgs/:orgId/agents/validate
Commands
GET /v1/orgs/:orgId/commandsPOST /v1/orgs/:orgId/commandsGET /v1/orgs/:orgId/commands/:configObjectIdPOST /v1/orgs/:orgId/commands/:configObjectId/versionsPOST /v1/orgs/:orgId/commands/validatePOST /v1/orgs/:orgId/commands/render-preview
Tools
GET /v1/orgs/:orgId/toolsPOST /v1/orgs/:orgId/toolsGET /v1/orgs/:orgId/tools/:configObjectIdPOST /v1/orgs/:orgId/tools/:configObjectId/versionsPOST /v1/orgs/:orgId/tools/analyzePOST /v1/orgs/:orgId/tools/validate
MCPs
GET /v1/orgs/:orgId/mcpsPOST /v1/orgs/:orgId/mcpsGET /v1/orgs/:orgId/mcps/:configObjectIdPOST /v1/orgs/:orgId/mcps/:configObjectId/versionsPOST /v1/orgs/:orgId/mcps/validatePOST /v1/orgs/:orgId/mcps/:configObjectId/test-connectionPOST /v1/orgs/:orgId/mcps/:configObjectId/install-check
Plugins
GET /v1/orgs/:orgId/pluginsGET /v1/orgs/:orgId/plugins/:pluginIdPOST /v1/orgs/:orgId/pluginsPATCH /v1/orgs/:orgId/plugins/:pluginIdPOST /v1/orgs/:orgId/plugins/:pluginId/archivePOST /v1/orgs/:orgId/plugins/:pluginId/restore
Plugin membership endpoints
GET /v1/orgs/:orgId/plugins/:pluginId/config-objectsPOST /v1/orgs/:orgId/plugins/:pluginId/config-objectsDELETE /v1/orgs/:orgId/plugins/:pluginId/config-objects/:configObjectIdGET /v1/orgs/:orgId/plugins/:pluginId/resolved
Optional plugin release endpoints
GET /v1/orgs/:orgId/plugins/:pluginId/releasesPOST /v1/orgs/:orgId/plugins/:pluginId/releasesGET /v1/orgs/:orgId/plugins/:pluginId/releases/:releaseId
Plugin access endpoints
GET /v1/orgs/:orgId/plugins/:pluginId/accessPOST /v1/orgs/:orgId/plugins/:pluginId/accessDELETE /v1/orgs/:orgId/plugins/:pluginId/access/:grantId
Marketplaces
GET /v1/orgs/:orgId/marketplacesGET /v1/orgs/:orgId/marketplaces/:marketplaceIdPOST /v1/orgs/:orgId/marketplacesPATCH /v1/orgs/:orgId/marketplaces/:marketplaceIdPOST /v1/orgs/:orgId/marketplaces/:marketplaceId/archivePOST /v1/orgs/:orgId/marketplaces/:marketplaceId/restore
Marketplace/plugin membership endpoints
GET /v1/orgs/:orgId/marketplaces/:marketplaceId/pluginsPOST /v1/orgs/:orgId/marketplaces/:marketplaceId/pluginsDELETE /v1/orgs/:orgId/marketplaces/:marketplaceId/plugins/:pluginId
Marketplace access endpoints
GET /v1/orgs/:orgId/marketplaces/:marketplaceId/accessPOST /v1/orgs/:orgId/marketplaces/:marketplaceId/accessDELETE /v1/orgs/:orgId/marketplaces/:marketplaceId/access/:grantId
Connector accounts
GET /v1/orgs/:orgId/connector-accountsPOST /v1/orgs/:orgId/connector-accountsGET /v1/orgs/:orgId/connector-accounts/:connectorAccountIdPOST /v1/orgs/:orgId/connector-accounts/:connectorAccountId/disconnect
Connector instances
GET /v1/orgs/:orgId/connector-instancesPOST /v1/orgs/:orgId/connector-instancesGET /v1/orgs/:orgId/connector-instances/:connectorInstanceIdPATCH /v1/orgs/:orgId/connector-instances/:connectorInstanceIdPOST /v1/orgs/:orgId/connector-instances/:connectorInstanceId/archivePOST /v1/orgs/:orgId/connector-instances/:connectorInstanceId/disablePOST /v1/orgs/:orgId/connector-instances/:connectorInstanceId/enable
Connector instance access endpoints
GET /v1/orgs/:orgId/connector-instances/:connectorInstanceId/accessPOST /v1/orgs/:orgId/connector-instances/:connectorInstanceId/accessDELETE /v1/orgs/:orgId/connector-instances/:connectorInstanceId/access/:grantId
Connector targets
GET /v1/orgs/:orgId/connector-instances/:connectorInstanceId/targetsPOST /v1/orgs/:orgId/connector-instances/:connectorInstanceId/targetsGET /v1/orgs/:orgId/connector-targets/:connectorTargetIdPATCH /v1/orgs/:orgId/connector-targets/:connectorTargetIdPOST /v1/orgs/:orgId/connector-targets/:connectorTargetId/resync
Example GitHub target body:
{
"type": "github",
"remoteId": "org/repo",
"targetKind": "repository_branch",
"config": {
"repositoryId": 123456,
"repositoryFullName": "org/repo",
"branch": "main",
"ref": "refs/heads/main"
}
}
Connector mappings
GET /v1/orgs/:orgId/connector-targets/:connectorTargetId/mappingsPOST /v1/orgs/:orgId/connector-targets/:connectorTargetId/mappingsPATCH /v1/orgs/:orgId/connector-mappings/:connectorMappingIdDELETE /v1/orgs/:orgId/connector-mappings/:connectorMappingIdPOST /v1/orgs/:orgId/connector-mappings/:connectorMappingId/preview
Example mapping body:
{
"mappingKind": "path",
"selector": "/sales/skills/**",
"objectType": "skill",
"pluginId": "plugin_123",
"autoAddToPlugin": true,
"config": {
"parserMode": "opencode"
}
}
Connector sync events
GET /v1/orgs/:orgId/connector-sync-eventsGET /v1/orgs/:orgId/connector-sync-events/:connectorSyncEventIdPOST /v1/orgs/:orgId/connector-sync-events/:connectorSyncEventId/retry
GitHub-specific admin endpoints
POST /v1/orgs/:orgId/connectors/github/setupPOST /v1/orgs/:orgId/connectors/github/accountsGET /v1/orgs/:orgId/connectors/github/accounts/:connectorAccountId/repositoriesPOST /v1/orgs/:orgId/connectors/github/validate-target
Response conventions
List:
{
"items": [],
"nextCursor": null
}
Detail:
{
"item": {}
}
Mutation:
{
"ok": true,
"item": {}
}
Async action:
{
"ok": true,
"queued": true,
"job": {
"id": "job_123"
}
}