Skip to content

feat(controlplane): scope CAS mappings to products - #3360

Merged
migmartri merged 1 commit into
mainfrom
feat/product-scoped-cas-mappings
Aug 21, 2026
Merged

feat(controlplane): scope CAS mappings to products#3360
migmartri merged 1 commit into
mainfrom
feat/product-scoped-cas-mappings

Conversation

@migmartri

@migmartrimigmartri commented Aug 20, 2026

Copy link
Copy Markdown
Member

Refs PFM-6978

What

CAS mappings can now be scoped to a product, in addition to a project, and the artifact download lookup honours product memberships.

Artifacts stored in the CAS carry the project they belong to so the download lookup can enforce project RBAC. Evidence attached to a product-level override has no project, so its mapping ends up unscoped and unreachable for any user whose organization role has RBAC enabled, and unreachable for product-only roles regardless.

Changes

  • cas_mappings gains an optional product_id. Products live in a downstream database, so it is a plain UUID reference with no edge and no foreign key, following the workflow_run_id precedent.
  • CASMappingCreateOpts accepts a ProductID, and the two scopes are mutually exclusive: the download filter grants access on either one, so a mapping carrying both would be reachable by the members of two unrelated resources.
  • Organization RBAC information is now expressed as biz.RBACScopes (visible projects and products per organization) instead of a bare project map, so the two dimensions cannot be transposed at a call site. Product memberships already live in this database, written by the Chainloop platform, so the filter only reads rows that are already stored.
  • The per-organization download predicate becomes project_id IN (visible projects) OR product_id IN (visible products). A subject with no grants still matches nothing.
  • Adds ListByDigestInOrg, an unfiltered lookup of an artifact's existing scopes and backends. It has no consumer in this repository; the Chainloop platform needs it to reconcile mappings for evidence uploaded before this scope existed, and it has to ship in the same release the platform bumps to for the scope itself.
  • Referrer lookups are unchanged: they are project-scoped only and take the project dimension of the scopes.

The column is additive and inert on its own: nothing in this repository writes it, and an all-NULL column changes no existing query result.

Testing

Integration tests cover the filter across project-only, product-only, both and neither grants, and pin the cross-repository contract by seeding a product membership row directly and asserting the download honours it.

AI disclosure

This contribution was produced with AI assistance (Claude Code); the affected commit carries an Assisted-by: trailer.

🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri

@chainloop-platform

chainloop-platformBot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

AI Session Checks — 🟡 79% · ✅ 0 failing

Avg scoreSessionsFailing policiesAttributionFilesLinesTotal Duration
🟡 79%1✅ 0100% AI / 0% Human12+518 / -12412h2m46s

🟡 79% — 100% AI — ✅ All policies passing

Aug 20, 2026 22:07 UTC · 12h2m46s · $73.92 · 1.4k in / 319.9k out · claude-code 2.1.238 (claude-opus-5)

View session details ↗

Change Summary

  • Adds optional product_id scoping to controlplane CAS mappings plus the ent migration/codegen.
  • Carries product-aware RBAC scopes through download lookup, membership collection, and related callers.
  • Expands integration coverage for product membership access and merges the rebase with project-validation cases.

AI Session Overall Score

🟡 79% — Well-implemented feature, but planning and final verification stayed a step short.

AI Session Analysis Breakdown

🟢 92% · scope-discipline

🟢 Post-rebase changes stayed inside the intended controlplane CAS-mapping surface. · High Impact

🟢 92% · user-trust-signal

No notes.

🟢 90% · solution-quality

🟢 AI enforced project-product mutual exclusion instead of trusting callers not to dual-scope rows. · High Impact

🟡 72% · alignment

🟠 User asked to commit and push, but the session stopped after force-push prep and build checks. · Medium Severity

💡 When the last ask is operational, either execute it or say clearly that you are stopping short.

🟡 68% · verification

🟢 AI added and reran focused integration tests, including a fail-then-restore proof. · High Impact

🟠 Post-rebase wider validation still ended with untouched pkg/biz casbackend integration failures, so final verification stopped short. · Medium Severity

💡 Before force-pushing after a rebase, rerun the change tests and one clean baseline for unrelated failing suites.

🟡 The cascredential.go token-branch refactor has no direct test coverage. · Low Severity

🟡 67% · context-and-planning

🟠 The spec gave scope, but the multi-file change still ran without any shared plan or plan-mode step. · Medium Severity

💡 For multi-file changes, write a short visible plan before editing so reviews and rebases have checkpoints.


File Attribution

████████████████████ 100% AI / 0% Human

StatusAttributionFileLines
modifiedaiapp/controlplane/pkg/biz/casmapping_integration_test.go+209 / -33
modifiedaiapp/controlplane/pkg/biz/mocks/CASMappingRepo.go+89 / -15
modifiedaiapp/controlplane/pkg/biz/casmapping.go+75 / -23
modifiedaiapp/controlplane/pkg/data/casmapping.go+59 / -16
modifiedaiapp/controlplane/pkg/biz/membership.go+63 / -11
modifiedaiapp/controlplane/pkg/biz/project.go+0 / -12
modifiedaiapp/controlplane/internal/service/cascredential.go+5 / -5
modifiedaiapp/controlplane/pkg/data/ent/migrate/schema.go+5 / -4
modifiedaiapp/controlplane/pkg/biz/referrer.go+4 / -3
modifiedaiapp/controlplane/pkg/data/ent/schema/casmapping.go+5 / -1
modifiedaiapp/controlplane/pkg/data/ent/migrate/migrations/atlas.sum+2 / -1
createdaiapp/controlplane/pkg/data/ent/migrate/migrations/20260820221508.sql+2 / -0

Policies (4)

StatusPolicyMaterialMessages
✅ Passedai-config-ai-agents-allowedai-coding-session-d81e13-
✅ Passedai-config-no-dangerous-commandsai-coding-session-d81e13-
✅ Passedai-config-no-secretsai-coding-session-d81e13-
✅ Passedai-config-mcp-servers-allowedai-coding-session-d81e13-

Security Checks — ✅ 2 passing

PR info

StatusPolicyMessages
✅ Passedpr-description-required-
✅ Passedpr-user-story-linked-

⏭️ 3 scans not applied

ScanReason
vulnerability-scanno manifest/lockfile changed
github-actions-scanno workflow files changed
iac-scanno IaC files changed

View attestation ↗


Powered by Chainloop and Chainloop Trace

@cubic-dev-aicubic-dev-aiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 18 files

Re-trigger cubic

@migmartri
migmartri requested a review from a teamAugust 21, 2026 09:30
Artifacts stored in the CAS are scoped to a project so that the download
lookup can honour project RBAC. Evidence attached to a product-level override
has no project, so its mapping ends up unscoped and unreachable for any user
whose organization role has RBAC enabled.
Add an optional product_id to cas_mappings and extend the download filter, so
that a mapping is reachable through a project OR a product membership. Product
memberships already live in this database, written by the Chainloop platform,
so the filter only needs to read rows it already stores.
The column is additive and inert on its own: nothing here writes it, and an
all-NULL column changes no existing query result.
Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
Chainloop-Trace-Sessions: d81e130c-5011-4bf4-99bc-9902a6fafb43
@migmartri
migmartriforce-pushed the feat/product-scoped-cas-mappings branch from deab390 to 03d3d87CompareAugust 21, 2026 10:10
@migmartri
migmartri merged commit 5bc93ac into mainAug 21, 2026
17 checks passed
@migmartri
migmartri deleted the feat/product-scoped-cas-mappings branch August 21, 2026 11:05
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@migmartri@tknura