feat(#4041): add AI Catalog permissions, graduated visibility, and conditional rules - #4185
feat(#4041): add AI Catalog permissions, graduated visibility, and conditional rules#4185fullsend-ai-coder[bot] wants to merge 1 commit into
Conversation
…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
Missing ChangesetsThe following package(s) are changed by this PR but do not have a changeset:
See CONTRIBUTING.md for more information about how to add changesets. Changed Packages
|
|
|
mareklibra
left a comment
There was a problem hiding this comment.
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({ |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) => ({ |
There was a problem hiding this comment.
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) => ({ |
There was a problem hiding this comment.
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< |
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
See #4041 (comment) about switching from the use of read to access in the permission names



Define the AI Catalog permission framework for the boost workspace:
Group 1 — Permission Definitions (RHIDP-15271, RHIDP-15306):
(included in the existing boostPermissions aggregate)
Group 2 — Graduated Visibility Backend (RHIDP-15271, RHIDP-15272):
usageDocs, connectionEndpoints, config, and deploymentParameters
when ai-catalog.asset.read.usage-docs is denied
authorizeConditional() for ai-catalog.asset.read
applied uniformly to list responses)
Group 4 — Conditional Permission Rules (RHIDP-15312):
resourceType 'ai-catalog-asset'
Closes #4041
Post-script verification
agent/4041-ai-catalog-permissions)c91e22821f3dd7e2daf287e349aeec360eb34c7d..HEAD)