From 0798f1a197110632b4951c2e0c8d1e9457b4f2db Mon Sep 17 00:00:00 2001 From: gazarenkov Date: Tue, 30 Jun 2026 14:25:37 +0300 Subject: [PATCH 1/4] adr-010 initial --- .../004-plugin-infrastructure-support.md | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 decisions/004-plugin-infrastructure-support.md diff --git a/decisions/004-plugin-infrastructure-support.md b/decisions/004-plugin-infrastructure-support.md new file mode 100644 index 0000000..7196a4f --- /dev/null +++ b/decisions/004-plugin-infrastructure-support.md @@ -0,0 +1,187 @@ +# ADR: Plugin Infrastructure Support (deploymentPatches and clusterResources) + +## Context + +**Problem**: Plugins requiring additional infrastructure (sidecars, init containers, volumes, cluster resources) need manual user configuration outside the plugin definition, breaking portability and complicating air-gap deployments. + +**Current state:** +- Plugins with infrastructure require manual Backstage CR customization +- Users must know which plugins need sidecars, volumes, or cluster resources +- Plugin requirements not self-documented +- Air-gap image discovery requires manual documentation review +- No standard way for plugins to declare dependencies + +**Examples**: +- Init container for additional data preparation +- Volume for data storage +- Additional K8s cluster resources certain plugin depends on (e.g. SonataFlowPlatform for Orchestrator plugin) + +Users must manually add these to Backstage CR, duplicating this knowledge across all instances. + +**Who is impacted:** +- **Plugin developers**: Cannot ship complete, portable plugin configurations +- **Users**: Must manually configure infrastructure for each plugin (error-prone) +- ?**Air-gap users**: Cannot automatically discover all required images (plugins + infrastructure) +- **Documentation**: Plugin infrastructure requirements scattered across docs, not in code + +**Constraints:** +- Must work with operator reconciliation patterns +- Must support air-gap image discovery workflows +- Must preserve Kubernetes resource semantics (strategic merge, owner references) +- Must handle plugin ordering and conflict resolution +- Must be optional (not all plugins need infrastructure) + +## Decision + +Enable plugins to declare infrastructure requirements inline via `deploymentPatches` and `clusterResources` fields in plugin configuration, allowing plugins to be self-contained and portable. + +**Implementation approach:** + +1. **deploymentPatches field**: + - Plugins specify Kubernetes Deployment patches + - Applied via strategic merge to Backstage Deployment + - Supports: initContainers, sidecars, volumes, volumeMounts, env vars + +2. **clusterResources field**: + - Plugins specify standalone Kubernetes resources + - Operator creates/updates these as separate objects + - Applied with owner reference to Backstage CR (lifecycle management) + - Supports: ConfigMaps, Secrets, Services, Jobs, etc. + +3. **Template variable substitution**: + - `{{backstage-name}}` replaced with Backstage CR name + - `{{backstage-namespace}}` replaced with Backstage CR namespace + - Enables unique resource naming per instance + +4. **Application order**: + - Plugins processed in order (catalog → flavour → user config merge order) + - Later plugins can override earlier patches (strategic merge) + - ClusterResources created after deployment patches applied + +5. **Air-gap image discovery**: + - Extract container images from `deploymentPatches.spec.template.spec.containers` + - Extract container images from `deploymentPatches.spec.template.spec.initContainers` + - Combine with plugin package images for complete manifest + - Accessible via ConfigMaps generated by operator (ADR-003) + +**Example:** + +```yaml +# dynamic-plugins.yaml +plugins: + - package: lightspeed-plugin + pluginConfig: + # ... normal plugin config ... + + # Infrastructure requirements + deploymentPatches: + - spec: + template: + spec: + initContainers: + - name: rag-init + image: registry.redhat.io/rhdh/rag-init:1.8 + volumeMounts: + - name: rag-data + mountPath: /rag + volumes: + - name: rag-data + emptyDir: {} + + clusterResources: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: lightspeed-config-{{backstage-name}} + data: + lcs-config.yaml: | + server: + port: 8080 + logLevel: info +``` + +**Operator behavior:** + +1. For each enabled plugin (after merge): + - Extract `deploymentPatches` and apply to Deployment via strategic merge + - Extract `clusterResources` and create/update as standalone objects + - Set owner references on clusterResources to Backstage CR + +2. Generate deployment with all patches applied + +3. Create clusterResources with owner references + +## Alternatives Considered + +### Alternative 1: Separate PluginInfrastructure CRD +- **Approach**: Create dedicated CRD for plugin infrastructure requirements +- **Rejected because**: + - Splits plugin definition across multiple resources + - More complex (need to link Plugin → PluginInfrastructure) + - Doesn't improve portability (still separate resources) + - Additional CRD to maintain + +### Alternative 3: Operator SDK Bundle Annotations +- **Approach**: Use OLM bundle annotations for plugin dependencies +- **Rejected because**: + - Couples plugins to OLM (doesn't work outside OLM) + - Not applicable to Backstage plugins (different resource model) + - Doesn't solve inline infrastructure declaration + +## Consequences + +### Positive + +✅ **Self-contained plugins**: Infrastructure requirements inline with plugin config (portable) +✅ **Air-gap discovery**: Extract all images (plugin + infrastructure) from ConfigMaps automatically +✅ **No manual configuration**: Users don't need to know plugin infrastructure requirements +✅ **Standard pattern**: Consistent way for all plugins to declare infrastructure needs +✅ **Lifecycle management**: Owner references ensure cleanup when Backstage CR deleted +✅ **Strategic merge**: Standard Kubernetes semantics for patch application + +### Negative + +❌ **Operator complexity**: Deployment patch application and cluster resource management adds code +❌ **Testing burden**: Need to test patch conflicts, merge order, resource creation failures +❌ **Security concerns**: Plugins can request arbitrary containers, volumes (need validation/policy) +❌ **Conflict resolution**: Later plugins can override earlier patches (surprising behavior if unintentional) +❌ **Debugging difficulty**: Final deployment is merged result (harder to trace which plugin added what) +❌ **Template variable scope**: Limited to `{{backstage-name}}` and `{{backstage-namespace}}` (may need more) + +### Neutral + +⚖️ **Optional feature**: Not all plugins need infrastructure (complexity only when used) +⚖️ **Plugin ordering matters**: Merge order affects final result (predictable but requires understanding) +⚖️ **ClusterResources scope**: Namespaced resources only (cluster-scoped resources not supported for safety) +⚖️ **Image discovery automation**: Enables automation but requires parsing Deployment patches (format-specific) + +## Notes + +**Related ADRs:** +- ADR-002 (DevHubPluginCatalog) provides catalog infrastructure for plugin storage +- ADR-003 (Operator-Based Plugin Configuration) provides config merging that includes deploymentPatches + +**Security considerations:** +- Plugins can request privileged containers (need admission control/policy) +- Volume mounts can access host filesystem (need validation) +- ClusterResources limited to namespaced resources (no ClusterRoles, CRDs, etc.) +- Consider: OPA/Kyverno policies to restrict plugin infrastructure capabilities + +**Implementation details:** +- Strategic merge uses `k8s.io/apimachinery/pkg/util/strategicpatch` +- Owner references set to Backstage CR (ensures garbage collection) +- Template substitution before resource creation + +**Air-gap workflow:** +1. Create DevHubPluginCatalog (ADR-002) +2. Operator generates `-catalog-original` ConfigMap +3. Admin extracts plugin images from package URLs +4. Admin extracts infrastructure images from `deploymentPatches` in ConfigMap +5. Admin mirrors all images to internal registry +6. Deploy Backstage CR with mirrored catalog + +**Open questions for implementation:** +- Validation policy: Should operator validate requested infrastructure? (e.g., no privileged containers) +- Conflict detection: Should operator warn on patch conflicts? +- Resource limits: Should there be limits on number of clusterResources per plugin? +- Cluster-scoped resources: Future support for ClusterRoles, etc.? (security implications) From 4f7067a7f54ad7ca972cdec1187f02ed031a7f11 Mon Sep 17 00:00:00 2001 From: gazarenkov Date: Tue, 30 Jun 2026 14:34:05 +0300 Subject: [PATCH 2/4] adr-010 initial --- decisions/010-app-config-validation.md | 200 +++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 decisions/010-app-config-validation.md diff --git a/decisions/010-app-config-validation.md b/decisions/010-app-config-validation.md new file mode 100644 index 0000000..6aa2013 --- /dev/null +++ b/decisions/010-app-config-validation.md @@ -0,0 +1,200 @@ +# ADR-010: Operator App-Config Validation + +## Context + +**Problem**: App-config errors are only discovered at Backstage runtime, after deployment, when plugins fail to load or behave incorrectly. + +**Current state:** +- Backstage validates configs at startup, but errors only appear in pod logs +- No validation occurs during CR reconciliation — operator blindly passes config to Backstage +- Configuration errors require pod restart to diagnose +- ADR-003 introduced "early validation" concept but without specific validation mechanisms + +**Types of errors only discovered at runtime:** +1. **Schema violations**: Wrong types, missing required fields, invalid values +2. **Missing references**: Env vars that don't exist, files that aren't mounted + +**Two categories of plugins require validation:** + +1. **Core plugins** (hardcoded/non-dynamic): Plugins built into RHDH image + - Discovered from RHDH's `packages/backend/package.json` and `packages/app/package.json` dependencies + +2. **Dynamic plugins**: Plugins loaded at runtime from catalog + - Discovered from catalog `index.json` + +Both configure via **app-config**. Schemas are fetched from respective plugin source repositories. + +**Who is impacted:** +- **Operators/SREs**: Invalid configs cause runtime failures, not reconciliation failures +- **Users**: No feedback on config errors until pod starts and plugin fails +- **Debugging**: Must read Backstage pod logs to understand issues + +**Constraints:** +- Schemas defined in upstream plugin source repos, not in RHDH +- TypeScript schemas require conversion to JSON Schema +- Not all plugins have schemas — schema validation should be best-effort +- Must not block deployment for plugins without schemas + +## Decision + +Implement two complementary validation mechanisms during Backstage CR reconciliation: + +1. **Existence validation**: Verify that referenced env vars and files exist +2. **Schema validation**: Validate app-config against plugin JSON schemas + +### 1. Existence Validation + +Verify that config references resolve to actual data: + +| Pattern | Validation | +|---------|------------| +| `${VAR}` | Env var exists (in ConfigMap, Pod env, etc.) | +| `$env: VAR` | Env var exists | +| `$file: path` | File/mount exists | +| `$include: path` | File exists | + +**Behavior:** +- Non-secret references: fail if not found +- Secret references: warn only (may not have access) +- Report missing references in CR status + +### 2. Schema Validation + +Generate JSON Schema files during plugin catalog creation for both core and dynamic plugins. + +**Schema extraction during catalog build** (in `rhdh-plugin-export-overlays`): + +**For core plugins:** +- Fetch `packages/backend/package.json` and `packages/app/package.json` from RHDH repo +- Extract plugin dependencies +- For each plugin, resolve source repository and fetch `configSchema` +- Convert TypeScript schemas to JSON Schema using `ts-json-schema-generator` + +**For dynamic plugins:** +- For each plugin in catalog `index.json`, extract repository info from `io.backstage.dynamic-packages` +- Fetch `configSchema` from plugin source repo +- Convert TypeScript schemas to JSON Schema + +**Catalog index image contents** (extended): +``` +catalog-index/ +├── index.json +├── dynamic-plugins.default.yaml +├── schemas/ # NEW +│ ├── manifest.json # Plugin inventory with schema status +│ ├── backstage-plugin-catalog-backend.json # Core plugin +│ ├── backstage-plugin-kubernetes-backend.json +│ ├── backstage-community-plugin-acr.json # Dynamic plugin +│ └── ... +└── ... +``` + +**Schema manifest format**: +```json +{ + "generatedAt": "2026-06-29T10:00:00Z", + "corePlugins": ["backstage-plugin-catalog-backend", ...], + "dynamicPlugins": ["backstage-community-plugin-acr", ...], + "pluginsWithSchema": ["backstage-plugin-kubernetes-backend", ...], + "pluginsWithoutSchema": ["backstage-plugin-home", ...], + "stats": { + "totalPlugins": 150, + "corePlugins": 30, + "dynamicPlugins": 120, + "withSchema": 55, + "withoutSchema": 95 + } +} +``` + +**Environment variable handling in schema validation:** + +Config values may contain env var references (`${VAR}`, `$env: VAR`) substituted at Backstage runtime. + +- **Stage 1**: Treat env var patterns as wildcard — accept any type, warn +- **Stage 2**: Resolve non-secret env vars and validate; for Secrets — warn only + +**Schema validation behavior:** +- Schemas set `additionalProperties: true` (allow unknown fields for forward compatibility) +- Validation is non-blocking for plugins without schemas +- Strict JSON Schema draft-07 validation + +### Operator Validation Flow + +During reconciliation (extends ADR-003): +1. Load schemas from default-config (populated by DHPC from catalog) +2. **Existence validation**: Check all `${VAR}`, `$env:`, `$file:`, `$include:` references +3. **Schema validation**: Validate app-config against plugin schemas +4. Report validation errors/warnings in CR status +5. Fail reconciliation on errors (fail fast) + +### CR Status Reporting + +```yaml +status: + conditions: + - type: AppConfigValid + status: "False" + reason: ValidationFailed + message: | + Existence errors: + - ${DATABASE_URL}: env var not found + - $file: /etc/secrets/api-key: file not mounted + + Schema errors (backstage-plugin-kubernetes-backend): + - $.kubernetes.clusterLocatorMethods[0].type: must be one of [config, gke, ...] + - $.kubernetes.serviceLocatorMethod: required property missing +``` + +## Alternatives Considered + +### Alternative 1: Schema extraction at operator runtime +- **Approach**: Operator fetches schemas from plugin source repos during reconciliation +- **Rejected because**: Requires network access during reconciliation; slow; unreliable; not air-gap compatible + +### Alternative 2: Manual schema curation in operator +- **Approach**: Maintain curated JSON schemas in operator repo for known plugins +- **Rejected because**: High maintenance burden; schemas drift from upstream; doesn't scale + +### Alternative 3: Schema extraction during plugin OCI build +- **Approach**: Include schema in each plugin's OCI image, extract at init container time +- **Rejected because**: Schemas scattered across images; harder to aggregate; doesn't cover core plugins + +## Consequences + +### Positive + +✅ **Fail fast**: Invalid configs caught during reconciliation, not at runtime +✅ **Clear error messages**: Validation errors in CR status with specific field paths +✅ **Two-layer validation**: Catches both missing references and schema violations +✅ **CI/CD friendly**: Validate configs without deploying pods +✅ **Consistent with ADR-003**: Extends early validation pattern +✅ **Complete coverage**: Validates both core and dynamic plugins +✅ **Best-effort**: Plugins without schemas still get existence validation +✅ **Air-gap compatible**: Schemas bundled in catalog image, no runtime fetching + +### Negative + +❌ **Build complexity**: Catalog build must handle TypeScript-to-JSON-Schema conversion +❌ **Larger catalog image**: Schema files add ~2-5MB to catalog index image + +### Neutral + +⚖️ **Requires ts-json-schema-generator**: Build dependency for TypeScript schema conversion +⚖️ **Best-effort schema validation**: Silent pass for schema-less plugins +⚖️ **additionalProperties: true**: Allows unknown fields (forward compatible but less strict) +⚖️ **Env var limitation**: `${VAR}` values treated as wildcards in schema validation (Stage 1) + +## Notes + +**Related ADRs:** +- ADR-003 (Operator-Based Plugin Configuration Processing) — this extends early validation +- ADR-002 (DevHubPluginCatalog CRD) — catalog provides schema files + +**Implementation phases:** +1. Add existence validation to operator reconciliation loop +2. Add schema extraction to catalog build scripts (`rhdh-plugin-export-overlays`) +3. Include schemas in catalog index OCI image +4. Add schema validation to operator reconciliation loop +5. Report validation results in CR status +6. (Future) Resolve non-secret env vars for full schema validation \ No newline at end of file From 4f40088f99aee29446096bd2dbfa5c847ab13108 Mon Sep 17 00:00:00 2001 From: gazarenkov Date: Tue, 30 Jun 2026 14:35:02 +0300 Subject: [PATCH 3/4] adr-010 initial --- .../004-plugin-infrastructure-support.md | 187 ------------------ 1 file changed, 187 deletions(-) delete mode 100644 decisions/004-plugin-infrastructure-support.md diff --git a/decisions/004-plugin-infrastructure-support.md b/decisions/004-plugin-infrastructure-support.md deleted file mode 100644 index 7196a4f..0000000 --- a/decisions/004-plugin-infrastructure-support.md +++ /dev/null @@ -1,187 +0,0 @@ -# ADR: Plugin Infrastructure Support (deploymentPatches and clusterResources) - -## Context - -**Problem**: Plugins requiring additional infrastructure (sidecars, init containers, volumes, cluster resources) need manual user configuration outside the plugin definition, breaking portability and complicating air-gap deployments. - -**Current state:** -- Plugins with infrastructure require manual Backstage CR customization -- Users must know which plugins need sidecars, volumes, or cluster resources -- Plugin requirements not self-documented -- Air-gap image discovery requires manual documentation review -- No standard way for plugins to declare dependencies - -**Examples**: -- Init container for additional data preparation -- Volume for data storage -- Additional K8s cluster resources certain plugin depends on (e.g. SonataFlowPlatform for Orchestrator plugin) - -Users must manually add these to Backstage CR, duplicating this knowledge across all instances. - -**Who is impacted:** -- **Plugin developers**: Cannot ship complete, portable plugin configurations -- **Users**: Must manually configure infrastructure for each plugin (error-prone) -- ?**Air-gap users**: Cannot automatically discover all required images (plugins + infrastructure) -- **Documentation**: Plugin infrastructure requirements scattered across docs, not in code - -**Constraints:** -- Must work with operator reconciliation patterns -- Must support air-gap image discovery workflows -- Must preserve Kubernetes resource semantics (strategic merge, owner references) -- Must handle plugin ordering and conflict resolution -- Must be optional (not all plugins need infrastructure) - -## Decision - -Enable plugins to declare infrastructure requirements inline via `deploymentPatches` and `clusterResources` fields in plugin configuration, allowing plugins to be self-contained and portable. - -**Implementation approach:** - -1. **deploymentPatches field**: - - Plugins specify Kubernetes Deployment patches - - Applied via strategic merge to Backstage Deployment - - Supports: initContainers, sidecars, volumes, volumeMounts, env vars - -2. **clusterResources field**: - - Plugins specify standalone Kubernetes resources - - Operator creates/updates these as separate objects - - Applied with owner reference to Backstage CR (lifecycle management) - - Supports: ConfigMaps, Secrets, Services, Jobs, etc. - -3. **Template variable substitution**: - - `{{backstage-name}}` replaced with Backstage CR name - - `{{backstage-namespace}}` replaced with Backstage CR namespace - - Enables unique resource naming per instance - -4. **Application order**: - - Plugins processed in order (catalog → flavour → user config merge order) - - Later plugins can override earlier patches (strategic merge) - - ClusterResources created after deployment patches applied - -5. **Air-gap image discovery**: - - Extract container images from `deploymentPatches.spec.template.spec.containers` - - Extract container images from `deploymentPatches.spec.template.spec.initContainers` - - Combine with plugin package images for complete manifest - - Accessible via ConfigMaps generated by operator (ADR-003) - -**Example:** - -```yaml -# dynamic-plugins.yaml -plugins: - - package: lightspeed-plugin - pluginConfig: - # ... normal plugin config ... - - # Infrastructure requirements - deploymentPatches: - - spec: - template: - spec: - initContainers: - - name: rag-init - image: registry.redhat.io/rhdh/rag-init:1.8 - volumeMounts: - - name: rag-data - mountPath: /rag - volumes: - - name: rag-data - emptyDir: {} - - clusterResources: - - apiVersion: v1 - kind: ConfigMap - metadata: - name: lightspeed-config-{{backstage-name}} - data: - lcs-config.yaml: | - server: - port: 8080 - logLevel: info -``` - -**Operator behavior:** - -1. For each enabled plugin (after merge): - - Extract `deploymentPatches` and apply to Deployment via strategic merge - - Extract `clusterResources` and create/update as standalone objects - - Set owner references on clusterResources to Backstage CR - -2. Generate deployment with all patches applied - -3. Create clusterResources with owner references - -## Alternatives Considered - -### Alternative 1: Separate PluginInfrastructure CRD -- **Approach**: Create dedicated CRD for plugin infrastructure requirements -- **Rejected because**: - - Splits plugin definition across multiple resources - - More complex (need to link Plugin → PluginInfrastructure) - - Doesn't improve portability (still separate resources) - - Additional CRD to maintain - -### Alternative 3: Operator SDK Bundle Annotations -- **Approach**: Use OLM bundle annotations for plugin dependencies -- **Rejected because**: - - Couples plugins to OLM (doesn't work outside OLM) - - Not applicable to Backstage plugins (different resource model) - - Doesn't solve inline infrastructure declaration - -## Consequences - -### Positive - -✅ **Self-contained plugins**: Infrastructure requirements inline with plugin config (portable) -✅ **Air-gap discovery**: Extract all images (plugin + infrastructure) from ConfigMaps automatically -✅ **No manual configuration**: Users don't need to know plugin infrastructure requirements -✅ **Standard pattern**: Consistent way for all plugins to declare infrastructure needs -✅ **Lifecycle management**: Owner references ensure cleanup when Backstage CR deleted -✅ **Strategic merge**: Standard Kubernetes semantics for patch application - -### Negative - -❌ **Operator complexity**: Deployment patch application and cluster resource management adds code -❌ **Testing burden**: Need to test patch conflicts, merge order, resource creation failures -❌ **Security concerns**: Plugins can request arbitrary containers, volumes (need validation/policy) -❌ **Conflict resolution**: Later plugins can override earlier patches (surprising behavior if unintentional) -❌ **Debugging difficulty**: Final deployment is merged result (harder to trace which plugin added what) -❌ **Template variable scope**: Limited to `{{backstage-name}}` and `{{backstage-namespace}}` (may need more) - -### Neutral - -⚖️ **Optional feature**: Not all plugins need infrastructure (complexity only when used) -⚖️ **Plugin ordering matters**: Merge order affects final result (predictable but requires understanding) -⚖️ **ClusterResources scope**: Namespaced resources only (cluster-scoped resources not supported for safety) -⚖️ **Image discovery automation**: Enables automation but requires parsing Deployment patches (format-specific) - -## Notes - -**Related ADRs:** -- ADR-002 (DevHubPluginCatalog) provides catalog infrastructure for plugin storage -- ADR-003 (Operator-Based Plugin Configuration) provides config merging that includes deploymentPatches - -**Security considerations:** -- Plugins can request privileged containers (need admission control/policy) -- Volume mounts can access host filesystem (need validation) -- ClusterResources limited to namespaced resources (no ClusterRoles, CRDs, etc.) -- Consider: OPA/Kyverno policies to restrict plugin infrastructure capabilities - -**Implementation details:** -- Strategic merge uses `k8s.io/apimachinery/pkg/util/strategicpatch` -- Owner references set to Backstage CR (ensures garbage collection) -- Template substitution before resource creation - -**Air-gap workflow:** -1. Create DevHubPluginCatalog (ADR-002) -2. Operator generates `-catalog-original` ConfigMap -3. Admin extracts plugin images from package URLs -4. Admin extracts infrastructure images from `deploymentPatches` in ConfigMap -5. Admin mirrors all images to internal registry -6. Deploy Backstage CR with mirrored catalog - -**Open questions for implementation:** -- Validation policy: Should operator validate requested infrastructure? (e.g., no privileged containers) -- Conflict detection: Should operator warn on patch conflicts? -- Resource limits: Should there be limits on number of clusterResources per plugin? -- Cluster-scoped resources: Future support for ClusterRoles, etc.? (security implications) From 62af82ecd44412534b631bd9c9a3b5472ce2b51b Mon Sep 17 00:00:00 2001 From: gazarenkov Date: Thu, 9 Jul 2026 10:52:31 +0300 Subject: [PATCH 4/4] emphasize validation of plugins from catalog only, added where core plugins schema included --- decisions/010-app-config-validation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/decisions/010-app-config-validation.md b/decisions/010-app-config-validation.md index 6aa2013..ad93b21 100644 --- a/decisions/010-app-config-validation.md +++ b/decisions/010-app-config-validation.md @@ -33,6 +33,7 @@ Both configure via **app-config**. Schemas are fetched from respective plugin so - Schemas defined in upstream plugin source repos, not in RHDH - TypeScript schemas require conversion to JSON Schema - Not all plugins have schemas — schema validation should be best-effort +- Schema validation only for plugins in a catalog (schemas extracted at catalog build time) - Must not block deployment for plugins without schemas ## Decision @@ -65,6 +66,7 @@ Generate JSON Schema files during plugin catalog creation for both core and dyna **Schema extraction during catalog build** (in `rhdh-plugin-export-overlays`): **For core plugins:** +- Core plugin schemas are included only in the [Default Catalog](https://github.com/redhat-developer/rhdh-adr/blob/main/decisions/002-devhub-plugin-catalog-crd.md) only - Fetch `packages/backend/package.json` and `packages/app/package.json` from RHDH repo - Extract plugin dependencies - For each plugin, resolve source repository and fetch `configSchema`