Skip to content

Commit 106b9f0

Browse files
feat(boost): add AI Catalog frontend architecture and OpenSpec
Add frontend architecture specification and OpenSpec change for the AI Catalog Discovery UI (RHDHPLAN-1509). This is the first frontend feature for the boost workspace. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 033a0b5 commit 106b9f0

7 files changed

Lines changed: 696 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
schema: spec-driven
2+
created: 2026-06-30
3+
status: draft
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Design: AI Catalog Frontend
2+
3+
## Context
4+
5+
Boost has a backend with 30+ API routes and 9 plugin packages but no frontend. The AI Catalog is the first frontend feature. The plugin architecture must support future domains (chat, admin, agent gallery) without restructuring.
6+
7+
## Goals
8+
9+
- NFS-only frontend plugin using Backstage Blueprints
10+
- Browse page for marketplace-style AI asset discovery
11+
- Entity page extensions for asset details and adoption actions
12+
- Dev app shell for local development
13+
- BUI component library for new UI components
14+
15+
## Non-Goals
16+
17+
- Chat UI, admin panels, or agent gallery (future domains)
18+
- Custom entity detail pages (use existing catalog pages)
19+
- RHDH dynamic plugin packaging (Scalprum/export-dynamic deferred)
20+
- Custom search collator for global search (rely on default catalog indexing)
21+
22+
## Decisions
23+
24+
### Decision 1: NFS-only plugin, no legacy entry point
25+
26+
This is a new plugin with no existing consumers. The default export from `src/index.ts` is `createFrontendPlugin`. No `src/alpha.tsx`, no `createPlugin` from `@backstage/core-plugin-api`.
27+
28+
### Decision 2: Standalone browse page + entity extensions
29+
30+
Two surface types:
31+
32+
- `PageBlueprint` at `/ai-catalog` for the card grid browse view. The existing catalog table at `/catalog` does not support card layout, category grouping, or inline adoption actions — a dedicated page is needed.
33+
- `EntityCardBlueprint` and `EntityContentBlueprint` on existing catalog entity pages for AI-specific cards and tabs. No custom detail page.
34+
35+
### Decision 3: catalogApiRef for data, BoostApiClient for download proxy only
36+
37+
The browse page queries AI assets through the standard `catalogApiRef` — no custom boost backend routes for browsing. The only custom backend interaction is the download proxy route for git-hosted asset ZIP downloads.
38+
39+
### Decision 4: Single isAiAsset filter, components handle kind differences
40+
41+
One `isAiAsset(entity)` condition filter for all entity page Blueprints. The filter checks entity kind and `spec.type` against the AI asset entity model (see below). Individual components handle kind-specific rendering differences internally — e.g., the download card checks `spec.location.type` and renders nothing when absent.
42+
43+
### Decision 5: Client-side pagination
44+
45+
`catalogApi.getEntities()` returns the full matching dataset. Client-side pagination is sufficient for the Dev Preview target of ~500 assets. If catalogs grow beyond this, the hook internals can switch to `queryEntities` (cursor-based) without changing components.
46+
47+
### Decision 6: BUI for UI components, PatternFly chatbot for future chat
48+
49+
BUI (`@backstage/ui`) is the component library for all new UI. MUI v5 as fallback where BUI lacks coverage. PatternFly AI chatbot (`@patternfly/chatbot`) is reserved for the future chat domain to maintain consistency with Lightspeed.
50+
51+
### Decision 7: RBAC graceful degradation
52+
53+
Permission checks for `ai-catalog.asset.read.usage-docs` default to allow when the permission is not yet registered (RHDHPLAN-1508 not built). Content is shown, and enforcement activates automatically when RBAC lands.
54+
55+
## Entity Model
56+
57+
Backstage v1.51.0 introduced `AiResource` kind and `API` with `spec.type: mcp-server` via `@backstage/plugin-catalog-backend-module-ai-model`. Boost uses upstream kinds where available:
58+
59+
| Category | Entity Kind | spec.type | Notes |
60+
|---|---|---|---|
61+
| Skills | AiResource | skill | Upstream. disciplines, categories, agents, dependsOn |
62+
| Rules | AiResource | rule | Upstream. category (required), rationale (required) |
63+
| MCP Servers | API | mcp-server | Upstream. spec.remotes list |
64+
| Agents | Component | ai-agent | Boost-defined |
65+
| Models | Resource | ai-model | Boost-defined. RFC #33060 pending |
66+
| Tools | Resource | ai-tool | Boost-defined (Kagenti) |
67+
| Vector Stores | Resource | vector-store | Boost-defined |
68+
69+
## Components
70+
71+
### AiCatalogPage
72+
Browse page with card grid, search, and filters. PluginHeader provided by the framework.
73+
- Card grid grouped by category with responsive layout
74+
- Debounced keyword search (300ms)
75+
- Filter controls: category, lifecycle, tags, owner, source connector (AND logic)
76+
- Filter/search state in URL query params
77+
- Pagination, sort (name, last updated)
78+
- Loading skeletons, empty state with clear-filters, error state with retry
79+
80+
### AiAssetCard
81+
Card displaying key metadata for one AI asset. Used in the browse grid.
82+
- Name, truncated description, category icon/badge, lifecycle badge
83+
- Tags, owner, version, source connector indicator
84+
- Click navigates to catalog entity detail page
85+
86+
### AiAssetSummaryCard
87+
EntityCardBlueprint on entity overview. Shows AI-specific metadata.
88+
- Category badge, current/recommended version, source attribution, lifecycle
89+
90+
### DownloadAdoptCard
91+
EntityCardBlueprint on entity overview. Conditional on spec.location.type.
92+
- git: Download button triggers ZIP download via backend proxy
93+
- oci: docker/podman toggle with copyable pull command
94+
- Absent: card not rendered
95+
96+
### VersionListCard
97+
EntityCardBlueprint on entity overview. Shows all versions of the asset.
98+
- Current/recommended highlighted
99+
- Click navigates to that version's entity page
100+
101+
### UsageTab
102+
EntityContentBlueprint tab. RBAC-gated usage documentation.
103+
- With usage-docs permission: TechDocs content or external links
104+
- Without permission: "Contact owner for access" affordance
105+
106+
## Design Reference
107+
108+
UX prototype: https://agentic-524bde.pages.redhat.com/skill-marketplace/overview (VPN required)
109+
110+
## Acceptance Criteria
111+
112+
### AiCatalogPage
113+
- Developer sees card grid grouped by category at /ai-catalog
114+
- Search filters cards within 300ms
115+
- Multiple filters narrow results with AND logic
116+
- Filter state in URL survives refresh and is shareable
117+
- Empty state when no match; error state when catalog unreachable
118+
- Keyboard navigable through all interactive elements
119+
120+
### AiAssetCard
121+
- Card displays all metadata fields from entity
122+
- Click navigates to catalog entity detail page
123+
124+
### AiAssetSummaryCard
125+
- Renders on AI asset entity pages only
126+
- Shows category, version, source, lifecycle
127+
128+
### DownloadAdoptCard
129+
- Download button on git assets triggers ZIP download
130+
- Docker/podman toggle on OCI assets with copyable pull command
131+
- Not rendered when spec.location.type absent
132+
133+
### VersionListCard
134+
- Shows all versions; current highlighted
135+
- Click navigates to version's entity page
136+
137+
### UsageTab
138+
- Renders TechDocs when annotation present; external links as fallback
139+
- Shows "Contact owner" when user lacks usage-docs permission
140+
- Tab only appears on AI asset entities
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Proposal: AI Catalog Frontend
2+
3+
## Why
4+
5+
Developers need a single place to discover AI agents, skills, MCP servers, AI models, and model servers available in their organization. These assets are already registered in the Backstage Software Catalog via ingestion connectors (RHDHPLAN-1507, 1510–1512), but the generic catalog table view is not optimized for marketplace-style discovery — card layout, category grouping, contextual filtering, and download/copy actions are absent.
6+
7+
The existing catalog entity detail pages provide metadata, TechDocs, and relationships out of the box. Rather than rebuilding detail pages, the frontend extends them with AI-specific cards and tabs using NFS Blueprints.
8+
9+
## What Boost Builds
10+
11+
### AI Catalog Browse Page
12+
13+
A standalone page at `/ai-catalog` with a card grid for discovering AI assets:
14+
15+
- Cards grouped by category (skills, rules, MCP servers, agents, models)
16+
- Search bar with debounced keyword filtering
17+
- Multi-faceted filter controls (category, lifecycle, tags, owner, source connector)
18+
- Pagination, sort, loading/empty/error states
19+
- Card click navigates to the existing catalog entity detail page
20+
21+
### Entity Page Extensions
22+
23+
NFS Blueprint extensions that render on catalog entity pages for AI assets:
24+
25+
- AI Asset Summary Card — category, version, source, lifecycle
26+
- Download/Adopt Card — ZIP download for git assets, docker/podman pull command for OCI assets
27+
- Version List Card — all versions with navigation
28+
- Usage Tab — RBAC-gated usage documentation (TechDocs or external links)
29+
30+
### Dev App Shell
31+
32+
`packages/app` and `packages/backend` for local development and testing, following the adoption-insights/orchestrator pattern.
33+
34+
## Impact
35+
36+
- `plugins/boost/` — new NFS frontend plugin
37+
- `packages/app/` — new dev app shell
38+
- `packages/backend/` — new dev backend
39+
- `boost-backend` — new download proxy route (`GET /api/boost/catalog/download`)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Browse View
2+
3+
> **Status: Draft** — Pre-implementation specification. Subject to change during implementation.
4+
5+
The AI Catalog browse page provides marketplace-style discovery for AI assets registered in the Backstage Software Catalog.
6+
7+
## Requirements
8+
9+
### Requirement: Card Grid Display
10+
11+
AI assets render as a card grid grouped by category.
12+
13+
#### Scenario: Browse page loads with assets
14+
15+
- **WHEN** the developer navigates to `/ai-catalog`
16+
- **THEN** the page displays a card grid of AI asset entities from the catalog
17+
- **AND** cards are grouped by category (skills, rules, MCP servers, agents, models)
18+
- **AND** each card shows name, description, category badge, lifecycle, tags, owner, version, and source
19+
20+
#### Scenario: Card navigation to entity detail
21+
22+
- **WHEN** the developer clicks an asset card
23+
- **THEN** the browser navigates to the catalog entity detail page for that entity (e.g., `/catalog/default/airesource/my-skill`)
24+
- **AND** the browse page state is preserved for back navigation
25+
26+
#### Scenario: Responsive layout
27+
28+
- **WHEN** the viewport is desktop width
29+
- **THEN** the card grid renders 3 columns
30+
- **WHEN** the viewport is mobile width
31+
- **THEN** the card grid renders 1 column
32+
33+
### Requirement: Keyword Search
34+
35+
The search bar filters visible cards by keyword.
36+
37+
#### Scenario: Search filters cards
38+
39+
- **WHEN** the developer types a keyword in the search bar
40+
- **THEN** cards are filtered within 300ms (debounced)
41+
- **AND** matching is against entity name, description, and tags
42+
43+
#### Scenario: Search state in URL
44+
45+
- **WHEN** the developer types a search term
46+
- **THEN** the search term is reflected in the URL query params (`?q=...`)
47+
- **AND** loading the URL directly reproduces the same filtered view
48+
49+
### Requirement: Multi-Faceted Filters
50+
51+
Filter controls narrow the card grid by entity metadata.
52+
53+
#### Scenario: Filters combine as AND
54+
55+
- **WHEN** the developer selects category "skill" AND lifecycle "production"
56+
- **THEN** only cards matching both criteria are shown
57+
58+
#### Scenario: Filter state in URL
59+
60+
- **WHEN** filters are active
61+
- **THEN** filter state is persisted in URL query params
62+
- **AND** the URL is shareable and survives page refresh
63+
- **AND** back/forward browser navigation updates filters correctly
64+
65+
#### Scenario: Clear filters
66+
67+
- **WHEN** the developer clears all filters
68+
- **THEN** the URL resets to the base path
69+
- **AND** the full unfiltered card grid is restored
70+
71+
### Requirement: Loading, Empty, and Error States
72+
73+
#### Scenario: Loading state
74+
75+
- **WHEN** the catalog API request is in progress
76+
- **THEN** skeleton cards are shown as loading placeholders
77+
78+
#### Scenario: Empty state
79+
80+
- **WHEN** no assets match the current filters
81+
- **THEN** the page shows "No AI assets match your filters" with a clear-filters action
82+
83+
#### Scenario: Error state
84+
85+
- **WHEN** the catalog API is unreachable
86+
- **THEN** the page shows an error message with a Retry button
87+
- **AND** the error does not crash the RHDH shell (error boundary)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Entity Page Extensions
2+
3+
> **Status: Draft** — Pre-implementation specification. Subject to change during implementation.
4+
5+
NFS Blueprint extensions that render on existing catalog entity pages for AI assets. All extensions use the `isAiAsset` condition filter and do not render on non-AI entities.
6+
7+
## Requirements
8+
9+
### Requirement: AI Asset Summary Card
10+
11+
#### Scenario: Summary card renders on AI entity
12+
13+
- **WHEN** a developer views a catalog entity page for an AI asset
14+
- **THEN** the AI Asset Summary Card shows the entity's category badge, current version, source connector attribution, and lifecycle state
15+
16+
#### Scenario: Summary card absent on non-AI entity
17+
18+
- **WHEN** a developer views a catalog entity page for a non-AI entity (e.g., a regular Component or API)
19+
- **THEN** the AI Asset Summary Card is not rendered
20+
21+
### Requirement: Download/Adopt Card
22+
23+
#### Scenario: Git asset download
24+
25+
- **WHEN** the entity has `spec.location.type: git`
26+
- **THEN** the card shows a Download button
27+
- **AND** clicking the button triggers a ZIP download via the backend proxy
28+
- **AND** a loading indicator is shown during download
29+
- **AND** an error toast is shown on failure
30+
31+
#### Scenario: OCI asset pull command
32+
33+
- **WHEN** the entity has `spec.location.type: oci`
34+
- **THEN** the card shows a docker/podman segmented toggle
35+
- **AND** the pull command is displayed below the toggle using `spec.location.target`
36+
- **AND** switching the toggle instantly updates the displayed command
37+
- **AND** the Copy button copies the currently displayed command to clipboard
38+
39+
#### Scenario: No location type
40+
41+
- **WHEN** the entity does not have `spec.location.type`
42+
- **THEN** the Download/Adopt Card is not rendered
43+
44+
### Requirement: Version List Card
45+
46+
#### Scenario: Version list with navigation
47+
48+
- **WHEN** the entity has multiple versions (linked by shared asset identifier)
49+
- **THEN** the Version List Card shows all versions
50+
- **AND** the current/recommended version is visually highlighted
51+
- **AND** clicking a version navigates to that version's catalog entity page
52+
53+
### Requirement: Usage Tab
54+
55+
#### Scenario: TechDocs available
56+
57+
- **WHEN** the entity has the `backstage.io/techdocs-ref` annotation
58+
- **THEN** the Usage tab renders TechDocs content for the entity
59+
60+
#### Scenario: TechDocs not available
61+
62+
- **WHEN** the entity does not have the TechDocs annotation
63+
- **THEN** the Usage tab renders external links (source registry, repository, download location) from entity metadata
64+
65+
#### Scenario: RBAC gated — permission granted
66+
67+
- **WHEN** the user has the `ai-catalog.asset.read.usage-docs` permission (or the permission is not yet registered)
68+
- **THEN** the Usage tab shows full usage content
69+
70+
#### Scenario: RBAC gated — permission denied
71+
72+
- **WHEN** the user has `ai-catalog.asset.read` but not `ai-catalog.asset.read.usage-docs`
73+
- **THEN** the Usage tab shows a "Contact owner for access" affordance instead of usage content
74+
75+
#### Scenario: Tab visibility
76+
77+
- **WHEN** a developer views a non-AI entity page
78+
- **THEN** the Usage tab is not present in the entity page tabs
79+
80+
### Requirement: Backend Download Proxy
81+
82+
#### Scenario: Successful download
83+
84+
- **WHEN** the frontend calls `GET /api/boost/catalog/download` with a valid entity ref
85+
- **THEN** the backend resolves `spec.location.target`, authenticates to GitHub via Backstage SCM integrations, and streams the ZIP archive response
86+
87+
#### Scenario: Unauthorized download
88+
89+
- **WHEN** the user lacks catalog entity read permission for the requested entity
90+
- **THEN** the backend returns 403
91+
92+
#### Scenario: Download failure
93+
94+
- **WHEN** the GitHub API is unreachable or returns an error
95+
- **THEN** the backend returns an appropriate error status with a message

0 commit comments

Comments
 (0)