Skip to content

feat(#4041): add AI Catalog permissions, graduated visibility, and conditional rules - #4185

Open
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/4041-ai-catalog-permissions
Open

feat(#4041): add AI Catalog permissions, graduated visibility, and conditional rules#4185
fullsend-ai-coder[bot] wants to merge 1 commit into
mainfrom
agent/4041-ai-catalog-permissions

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Define the AI Catalog permission framework for the boost workspace:

Group 1 — Permission Definitions (RHIDP-15271, RHIDP-15306):

  • Add AI_CATALOG_ASSET_RESOURCE_TYPE constant ('ai-catalog-asset')
  • Define ai-catalog.asset.read resource permission (Tier 1 discovery)
  • Define ai-catalog.asset.read.usage-docs resource permission (Tier 2)
  • Define ai-catalog.admin basic permission (management actions)
  • Export all constants and permission arrays from boost-common
  • Register all 3 permissions via permissionsRegistry.addPermissions()
    (included in the existing boostPermissions aggregate)

Group 2 — Graduated Visibility Backend (RHIDP-15271, RHIDP-15272):

  • Implement field-level filtering via stripTier2Fields() that omits
    usageDocs, connectionEndpoints, config, and deploymentParameters
    when ai-catalog.asset.read.usage-docs is denied
  • Implement entity-level filtering on list endpoint using
    authorizeConditional() for ai-catalog.asset.read
  • Implement batch authorizeConditional() for Tier 2 (single check
    applied uniformly to list responses)
  • Add AiCatalogAssetLoader interface for catalog abstraction
  • Add unit tests for field-level filtering

Group 4 — Conditional Permission Rules (RHIDP-15312):

  • Implement isAiAssetCategory rule checking rhdh.io/ai-asset-category
  • Implement isFromConnector rule checking rhdh.io/ai-asset-source
  • Implement isInTenant rule checking namespace or rhdh.io/ai-asset-tenant
  • Each rule implements apply() and toQuery() for catalog query predicates
  • Register all 3 rules via createPermissionIntegrationRouter with
    resourceType 'ai-catalog-asset'
  • Add unit tests for each rule's apply() and toQuery() methods

Closes #4041

Post-script verification

  • Branch is not main/master (agent/4041-ai-catalog-permissions)
  • Secret scan passed (gitleaks — c91e22821f3dd7e2daf287e349aeec360eb34c7d..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

…nditional rules

Define the AI Catalog permission framework for the boost workspace:

Group 1 — Permission Definitions (RHIDP-15271, RHIDP-15306):
- Add AI_CATALOG_ASSET_RESOURCE_TYPE constant ('ai-catalog-asset')
- Define ai-catalog.asset.read resource permission (Tier 1 discovery)
- Define ai-catalog.asset.read.usage-docs resource permission (Tier 2)
- Define ai-catalog.admin basic permission (management actions)
- Export all constants and permission arrays from boost-common
- Register all 3 permissions via permissionsRegistry.addPermissions()
  (included in the existing boostPermissions aggregate)

Group 2 — Graduated Visibility Backend (RHIDP-15271, RHIDP-15272):
- Implement field-level filtering via stripTier2Fields() that omits
  usageDocs, connectionEndpoints, config, and deploymentParameters
  when ai-catalog.asset.read.usage-docs is denied
- Implement entity-level filtering on list endpoint using
  authorizeConditional() for ai-catalog.asset.read
- Implement batch authorizeConditional() for Tier 2 (single check
  applied uniformly to list responses)
- Add AiCatalogAssetLoader interface for catalog abstraction
- Add unit tests for field-level filtering

Group 4 — Conditional Permission Rules (RHIDP-15312):
- Implement isAiAssetCategory rule checking rhdh.io/ai-asset-category
- Implement isFromConnector rule checking rhdh.io/ai-asset-source
- Implement isInTenant rule checking namespace or rhdh.io/ai-asset-tenant
- Each rule implements apply() and toQuery() for catalog query predicates
- Register all 3 rules via createPermissionIntegrationRouter with
  resourceType 'ai-catalog-asset'
- Add unit tests for each rule's apply() and toQuery() methods

Closes #4041
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from durandom as a code owner August 5, 2026 22:04
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Agent PR ready for human review label Aug 5, 2026
@rhdh-gh-app

rhdh-gh-app Bot commented Aug 5, 2026

Copy link
Copy Markdown

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @red-hat-developer-hub/backstage-plugin-boost-backend
  • @red-hat-developer-hub/backstage-plugin-boost-common

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-boost-backend workspaces/boost/plugins/boost-backend none v0.1.4
@red-hat-developer-hub/backstage-plugin-boost-common workspaces/boost/plugins/boost-common none v0.1.4

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@mareklibra mareklibra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sending comments from the first review round. Besides those commented by bots and failing CI.


// AI Catalog permission integration router with conditional rules
// (task 4.7: register isAiAssetCategory, isFromConnector, isInTenant)
const aiCatalogPermissionRouter = createPermissionIntegrationRouter({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createPermissionIntegrationRouter for ai-catalog-asset registers rules but omits getResources. Without it, /apply-conditions cannot resolve resourceRefs and conditional detail authorization will throw NotImplementedError. Please add getResources (catalog lookup by entity ref) or document/defer conditional detail evaluation explicitly and avoid authorize()+resourceRef until then.

});
router.use(permissionIntegrationRouter);

// AI Catalog permission integration router with conditional rules

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createAiCatalogRoutes is never wired into the boost router. Permission registration alone does not deliver graduated-visibility enforcement. Either mount the routes with a real/stub AiCatalogAssetLoader, or clearly mark this PR as definitions+rules only and drop the “list/detail endpoint” claims from the description.

resource.metadata.annotations?.['rhdh.io/ai-asset-tenant'];
return annotation === tenant;
},
toQuery: ({ tenant }: IsInTenantParams) => ({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isInTenant.apply() accepts metadata.namespace OR rhdh.io/ai-asset-tenant, but toQuery() only emits the annotation key. Please emit an anyOf of namespace + annotation predicates (or document that tenant identity is annotation-only and change apply() to match).

resource.metadata.annotations?.['rhdh.io/ai-asset-category'];
return annotation === category;
},
toQuery: ({ category }: IsAiAssetCategoryParams) => ({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be confirmed: toQuery() keys should likely be metadata.annotations.rhdh.io/ai-asset-* (catalog EntitiesSearchFilter shape), matching Backstage HAS_ANNOTATION. Bare annotation names won’t filter via catalog query APIs.

key: 'rhdh.io/ai-asset-category',
values: [category],
}),
} as any) as unknown as PermissionRule<

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer fixing createPermissionRule typing (resourceRef + zod schema) instead of as any / double casts on each rule.

In general, retyping is a sign of (suspected) bad design.

@gabemontero gabemontero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #4041 (comment) about switching from the use of read to access in the permission names

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review Agent PR ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI Catalog Permissions, Backend Enforcement, Conditional Rules (issue 3 of 29)

2 participants