Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
schema: spec-driven
created: 2026-07-06
updated: 2026-07-22
status: draft
notes: >-
Retooled OCI support onto upstream backstage.io/source-location
(url:oci://…) per RHIDP-15739; removed spec.location model.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## Canonical Touchpoints

- None
- RHDHPLAN-1113 — [Agentic] Agents & Skills (AIResource Kinds) in the RHDH Catalog (DP)
- RHIDP-13942 — AIResource: Catalog ingestion (OCI processor + git annotation path)
- RHIDP-15739 — Align OCI AIResource support with upstream source-location (`url:oci://…`); remove `spec.location`

## Context

Expand All @@ -12,92 +14,126 @@ Backstage's catalog supports pluggable entity kinds through three main mechanism
2. Registering processors that validate or enrich entities during ingestion
3. Reusing existing catalog behavior where a new kind fits an established path

For AI assets, the two source types are materially different:
Upstream `AiResource` does **not** define `spec.location`. Skill and rule content is referenced via the standard `backstage.io/source-location` annotation, identical to other Backstage entity kinds.

- **`git`**: A source repository or other URL-reader-compatible location that can reuse existing Backstage ingestion behavior
- **`oci`**: An OCI artifact reference such as `oci://quay.io/org/skills:latest`, which requires explicit validation because existing catalog processors do not understand OCI references directly
For AI assets, two content reference shapes are needed:

The design must keep OCI ingestion air-gap safe. The catalog should validate the reference and index the entity, but it must not fetch manifests, pull layers, or contact registries during processing.
- **Git / HTTPS**: `backstage.io/source-location: url:https://…` (or other UrlReader-compatible URL)
- **OCI**: `backstage.io/source-location: url:oci://registry/repository[:tag|@digest]`

In both cases, the **entity YAML** (`catalog-info.yaml`) is still registered through a normal catalog location (`url` / `file` / git discovery). The OCI reference is metadata on the entity; the catalog does not pull image content during ingest.

The design must keep OCI ingest air-gap safe: validate the reference and index the entity, but do not fetch manifests, pull layers, or contact registries during processing.

## Goals / Non-Goals

**Goals:**

- Implement the upstream-aligned `AIResource` kind in this workspace
- Use `spec.location.target` as the canonical location field
- Reuse existing catalog behavior for git-backed AIResource entities
- Implement the upstream-aligned `AIResource` / `AiResource` kind in this workspace
- Use `backstage.io/source-location` as the canonical content location
- Validate OCI source-location values in location-ref form `url:oci://…`
- Reuse existing catalog behavior for registering entity YAML from git/HTTPS/`file`
- Add lightweight OCI validation with zero outbound network calls
- Support standard entity page rendering, discovery, filtering, and search
- Support RHDH-specific `spec.scope` validation
- Remove any RHDH `spec.location` field used for OCI/git asset location

**Non-Goals:**

- Deep OCI content ingestion
- Deep OCI content ingestion / OCI `UrlReader`
- Catalog location type `oci` for discovering entities from registries
- Private registry authentication
- Separate frontend plugin or marketplace UI
- Additional asset source types beyond `git` and `oci`
- Additional RHDH location fields beyond upstream annotations + `spec.scope`

## Decisions

### D1 - Use upstream `AIResource`, not `AIContext`
### D1 - Use upstream `AiResource` / `AIResource`, not `AIContext`

**Choice**: Implement the upstream `AIResource` entity kind rather than maintaining the older `AIContext` naming.
**Choice**: Implement the upstream `AiResource` entity kind rather than maintaining the older `AIContext` naming.

**Rationale**: Upstream alignment reduces migration cost and keeps this workspace compatible with the Backstage merge path.

### D2 - Use `spec.location.target` as the canonical location field
### D2 - Canonical location is `backstage.io/source-location` (no `spec.location`)

**Choice**: Do not use an RHDH `spec.location` struct. Git/HTTPS and OCI content references both use `metadata.annotations["backstage.io/source-location"]`.

**Rationale**: Matches upstream AIResource design and Backstage feedback. Keeps OCI skill support compatible with future consumers that resolve content via `UrlReader` against the source-location target.

### D3 - OCI uses location-ref form `url:oci://…`

**Choice**: OCI-backed entities MUST set:

**Choice**: Represent both git and OCI locations with `spec.location.target`, discriminated by `spec.location.type`.
```yaml
metadata:
annotations:
backstage.io/source-location: url:oci://quay.io/org/skills:latest
```

**Rationale**: This matches the current RFC direction and avoids separate `url` / `uri` field shapes.
Backstage `parseLocationRef` splits on the first `:`, yielding `{ type: 'url', target: 'oci://quay.io/org/skills:latest' }`.

### D3 - Reuse `UrlReaderProcessor` for git-backed entities
**Rationale**: Bare `oci://…` as the annotation value parses as location type `oci` with a non-URL target (`//quay.io/…`), which breaks future UrlReader integration. Prefixing with `url:` keeps type `url` and preserves a parseable `oci://` target.

**Choice**: Git-backed AIResource entities use the standard `backstage.io/source-location` annotation and the existing `UrlReaderProcessor`.
### D4 - Reuse standard catalog registration for entity YAML

**Rationale**: This keeps the common path simple and avoids duplicating catalog logic that already exists in Backstage.
**Choice**: Entity descriptors are always fetched from normal catalog locations (`url` / `file` / git). No catalog location type `oci` and no OCI `UrlReader` are required to **register** OCI-referenced AIResources.

### D4 - OCI ingestion performs format validation only
**Rationale**: Registration indexes metadata. Fetching skill content from a registry is a separate, later capability.

**Choice**: OCI-backed AIResource entities are validated by a dedicated processor that checks `spec.location.target` format only.
**Verification**: Git/HTTPS-sourced AIResource ingestion via the existing `UrlReaderProcessor` and `backstage.io/source-location` annotation was verified in RHIDP-14557 (happy path, missing source-location warning, and standard catalog registration). That establishes the git skill path; OCI does not need a UrlReader for registration.

### D5 - OCI ingestion performs format validation only

**Choice**: When `backstage.io/source-location` has target scheme `oci://`, a dedicated processor validates format only (non-empty, no surrounding whitespace, well-formed `oci://registry/repository[:tag|@digest]`).

**Rationale**: The catalog indexes the OCI reference as metadata. It should not fetch remote OCI content. This keeps ingestion stateless, air-gap safe, and free of registry dependency or rate-limit concerns.

### D5 - Preserve the `oci://` prefix convention
### D6 - Preserve the `oci://` scheme on the location target

**Choice**: OCI locations must retain the `oci://` scheme prefix.
**Choice**: The source-location **target** (after the `url:` prefix) must use the `oci://` scheme.

**Rationale**: This is the established RHDH convention and provides an unambiguous distinction from ordinary URLs.
**Rationale**: Unambiguous distinction from HTTPS/git URLs; matches established RHDH OCI URI convention.

### D6 - `spec.scope` is an RHDH extension
### D7 - `spec.scope` is an RHDH extension

**Choice**: Support optional `spec.scope` values `organization`, `product`, and `team` as an RHDH-specific extension.

**Rationale**: Scope is needed for RHDH use cases but is not part of the upstream core kind. Keeping it as an extension preserves alignment while meeting local requirements.

### D7 - Use the standard entity page
### D8 - Use the standard entity page

**Choice**: Render AIResource entities through the existing `EntityPage` layout rather than creating a dedicated page.

**Rationale**: The standard entity page already provides metadata rendering, relationships, and TechDocs integration. A custom plugin would add unnecessary complexity for the initial release.
**Rationale**: The standard entity page already provides metadata rendering, relationships, and TechDocs integration. A custom AI catalog frontend is deferred to a future release.

### D8 - Discovery uses standard catalog APIs
### D9 - Discovery uses standard catalog APIs

**Choice**: AIResource entities participate in the existing entity list, by-name lookup, filter, and full-text search APIs.

**Rationale**: AIResource should behave like any other first-class catalog kind rather than requiring special endpoints.

### D10 - Deferred: OCI UrlReader

**Choice**: Do not implement an OCI `UrlReader` in this change.

**Rationale**: A UrlReader is only needed when a consumer must fetch content (or catalog YAML) from `oci://…`. Registration and format validation do not require it. When added later, it registers via `urlReaderFactoriesServiceRef` with `predicate: (url) => url.protocol === 'oci:'`.
Comment thread
gabemontero marked this conversation as resolved.

**Symmetry with git**: The existing Backstage URL readers already cover git/HTTPS skill sources; RHIDP-14557 confirmed that path for AIResource. Deferring an OCI UrlReader is therefore an intentional gap versus the verified git reader path, not an unverified assumption that “no reader is needed for either.”

## Risks / Trade-offs

| Risk | Mitigation |
| -------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Upstream AIResource evolves further | Keep the design aligned to upstream naming and field shapes; limit RHDH-specific additions |
| OCI target ambiguity causes weak validation | Enforce `spec.location.type`, `spec.location.target`, and `oci://` prefix rules explicitly |
| Users expect OCI content inspection | Document clearly that ingestion indexes metadata only and performs no registry I/O |
| RHDH extension behavior drifts from upstream | Keep `spec.scope` isolated as an extension and avoid additional spec divergence |
| Risk | Mitigation |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Upstream AIResource evolves further | Keep the design aligned to upstream annotations; limit RHDH-specific additions to `spec.scope` |
| Wrong location-ref form (`oci://` without `url:`) | Validate `url:` prefix + `oci://` target; document examples clearly |
| Users expect OCI content inspection | Document clearly that ingestion indexes metadata only and performs no registry I/O |
| Stale `spec.location` examples confuse agents | Remove `spec.location` from schema, processor, docs, examples, and OpenSpec |
| RHDH extension behavior drifts from upstream | Keep `spec.scope` isolated as an extension and avoid additional spec divergence |

## Deferred Decisions

- OCI `UrlReader` for content fetch / broader import
- Private OCI registry authentication
- OCI URI to registry-browse URL transformation on the entity page
- Catalog location type `oci` for discovering entities from registries
- OCI URI to registry-browse URL transformation on a custom entity page
- Promotion of change-local specs into long-lived `openspec/specs/`
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@

AI coding tools consume reusable assets such as skills, rules, prompts, and agent definitions that teams publish in source repositories or OCI images. There is no standard way in this workspace to register those assets as catalog entities, validate their location metadata safely, and make them discoverable through standard RHDH catalog APIs and entity pages.

Adding first-class `AIResource` catalog support closes that gap while staying aligned with the upstream Backstage `AIResource` kind.
Adding first-class `AIResource` catalog support closes that gap while staying aligned with the upstream Backstage `AiResource` kind. Upstream intentionally has no `spec.location` field — asset content is referenced via the standard `backstage.io/source-location` annotation.

## What Changes

- Introduce support for the upstream `AIResource` catalog kind in this workspace.
- Support two asset location types under `spec.location.type`: `git` and `oci`.
- Validate AIResource entities during ingestion, including RHDH-specific `spec.scope` support and `oci://` prefix rules.
- Reuse existing Backstage catalog behavior for git-backed entities.
- Add an OCI catalog processor that validates `spec.location.target` format only and makes zero outbound registry calls.
- Introduce support for the upstream `AiResource` / `AIResource` catalog kind in this workspace.
- Use `backstage.io/source-location` as the canonical asset location for both git/HTTPS and OCI-backed entities.
- Represent OCI-backed assets with the Backstage location-ref form `url:oci://…` (location type `url`, target scheme `oci://`).
- Validate AIResource entities during ingestion, including RHDH-specific `spec.scope` support and OCI source-location format rules.
- Reuse existing Backstage catalog behavior for entity YAML registration (git/HTTPS/`file` catalog locations).
- Add an OCI catalog processor that validates OCI `source-location` format only and makes zero outbound registry calls.
- Do **not** introduce RHDH `spec.location` (removed / not used for OCI skill support).
- Render AIResource entities on the standard catalog entity page.
- Expose AIResource entities through standard catalog search and filter APIs.
- Add local workspace documentation and OpenSpec artifacts so implementation agents can work from this workspace directly.
Expand All @@ -21,8 +23,8 @@ Adding first-class `AIResource` catalog support closes that gap while staying al

### New Capabilities

- `ai-resource-entity-schema`: Schema and validation rules for the `AIResource` kind, including `spec.scope` as an RHDH extension and `oci://` validation for OCI locations.
- `ai-resource-catalog-ingestion`: Catalog backend support for git-backed and OCI-backed AIResource ingestion.
- `ai-resource-entity-schema`: Schema and validation rules for the `AIResource` kind, including `spec.scope` as an RHDH extension and OCI `source-location` validation.
- `ai-resource-catalog-ingestion`: Catalog backend support for git/HTTPS-backed and OCI-referenced AIResource ingestion (format validation only for OCI).
- `ai-resource-entity-page`: Standard entity page rendering for AIResource entities, including source-aware location display and TechDocs integration.
- `ai-resource-discovery`: Catalog API, filtering, and full-text search support for AIResource entities.

Expand All @@ -34,23 +36,26 @@ _(none - this is a net-new capability area in this workspace)_

- Parsing or indexing individual skills, rules, prompts, or agents inside an asset
- OCI registry manifest fetching, layer inspection, or metadata enrichment
- An OCI `UrlReader` (deferred; needed only when something must fetch OCI content)
- A catalog location type `oci` / `readLocation` for discovering entities from registries
- Private OCI registry authentication in the initial implementation
- HTTPS archive, ZIP, or TAR support as location types
- A dedicated AI marketplace or custom frontend plugin
- HTTPS archive, ZIP, or TAR support as catalog location types
- A dedicated AI marketplace or custom frontend plugin (future release)
- Tool-runtime-specific integration with Cursor, Copilot, Claude Code, or other AI coding tools

## Canonical Touchpoints

- **PRDs**: None
- **ADRs**: None
- **Long-lived specs (`openspec/specs/`)**: None yet
- **Jira**: RHDHPLAN-1113, RHIDP-13942, RHIDP-15739

**Change type**: feature-spec

## Impact

- **Catalog backend**: Adds AIResource-specific ingestion and OCI validation behavior
- **Schema handling**: Extends upstream AIResource behavior with RHDH-specific validation
- **Catalog backend**: Adds AIResource-specific ingestion and OCI `source-location` validation behavior
- **Schema handling**: Extends upstream AIResource behavior with RHDH-specific `spec.scope` validation only (no `spec.location`)
- **Frontend**: Reuses the standard entity page layout for AIResource entities
- **Catalog API**: No breaking API changes; AIResource appears through standard entity and search endpoints
- **Documentation**: Adds local OpenSpec materials to make the workspace self-contained for implementation
Loading
Loading