Apply namespace bans to AI Catalog item visibility
What does this MR do and why?
Group and project policies deny a banned member everything through prevent_all, but Ai::Catalog::ItemPolicy and the two visibility scopes on Ai::Catalog::Item derived membership on their own, so a ban did not carry over to private and restricted catalog items.
This MR makes item access follow the container policies. ItemPolicy now also requires read_project (private items) and read_group on the top-level group (restricted items). The list scopes add a NOT EXISTS on namespace_bans to their membership subquery, which is a no-op for users with no bans and for admins.
Note for reviewers: requiring read_project and read_group means item reads now also respect other container-level denials such as SSO enforcement and IP restrictions.
References
https://gitlab.com/gitlab-org/gitlab/-/work_items/612769
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Database Review
Explore level listing of AI Catalog Items
Query plan - https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/56736/commands/161116
Click to expand
SELECT "ai_catalog_items".*
FROM "ai_catalog_items"
WHERE "ai_catalog_items"."deleted_at" IS NULL
AND "ai_catalog_items"."organization_id" = 1
AND "ai_catalog_items"."item_type" = 2
AND (
"ai_catalog_items"."visibility" = 2
OR EXISTS (
SELECT 1
FROM "project_authorizations"
WHERE "project_authorizations"."project_id" = "ai_catalog_items"."project_id"
AND "project_authorizations"."user_id" = 26121709
AND "project_authorizations"."access_level" >= 10
AND NOT (
EXISTS (
SELECT 1
FROM "projects"
INNER JOIN "namespaces"
ON "namespaces"."id" = "projects"."project_namespace_id"
AND "namespaces"."type" = 'Project'
WHERE "projects"."id" = "ai_catalog_items"."project_id"
AND (namespaces.traversal_ids[1] IN (9970))
)
)
)
)
AND "ai_catalog_items"."visibility" != 1
ORDER BY
"ai_catalog_items"."last_30_day_usage_count" DESC,
"ai_catalog_items"."id" DESC
LIMIT 21Related to #612769