Summary
Two things are missing around ApplicationDefinition, and together they let one definition take over releases that belong to another.
Nothing enforces that spec.application.kind is unique across ApplicationDefinitions. There is no such check in internal/marketplace/collision, at admission, or anywhere else in the tree.
updateHelmReleasesForAppDef (internal/controller/applicationdefinition_helmreconciler.go:80) lists HelmReleases across the whole cluster, selecting on apps.cozystack.io/application.kind and apps.cozystack.io/application.group alone, and rewrites spec.chartRef on every match to the one the reconciling definition carries. No ownership relation ties a definition to the releases it rewrites.
Impact
cozystack-api stamps both labels on every tenant application release it creates (pkg/registry/apps/application/rest.go:237). So a second definition declaring an already-claimed kind repoints every existing tenant release of that kind at its own artifact, and the two definitions then rewrite each other's releases on every reconcile.
The definition's object name is the only collision Helm itself would catch, through ownership metadata on an existing object, and the name is independent of the kind. A definition named anything at all can claim a kind that is already in use.
cozystack-api also builds one config.Resource per definition at start-up with no check that two do not name the same kind (pkg/cmd/server/start.go:251).
Not a report against a released line
Putting an ApplicationDefinition on the cluster currently takes the same access as installing a chart, which is admin-level, so this crosses no trust boundary in any release today. It becomes reachable by a third-party repository publisher once the marketplace tap ships, which is why it is worth closing first.
Suggested fix
Reject an ApplicationDefinition whose spec.application.kind is already claimed by another definition, at admission, so the invariant holds whoever creates the object and whatever it is named.
Give ApplicationDefinitionHelmReconciler an ownership relation and rewrite only the HelmReleases a definition actually backs, rather than every release carrying the kind label.
Make a duplicate kind a loud failure at cozystack-api start-up rather than two registrations for one GVK.
Relation to other issues
#4359 proposes decoupling catalog registration from install so an unconfirmed tap installs nothing. This issue is the adjacent invariant: it holds for any repository an operator installs deliberately, tapped or not, so it is deliberately kept separate from that work.
Summary
Two things are missing around
ApplicationDefinition, and together they let one definition take over releases that belong to another.Nothing enforces that
spec.application.kindis unique across ApplicationDefinitions. There is no such check ininternal/marketplace/collision, at admission, or anywhere else in the tree.updateHelmReleasesForAppDef(internal/controller/applicationdefinition_helmreconciler.go:80) lists HelmReleases across the whole cluster, selecting onapps.cozystack.io/application.kindandapps.cozystack.io/application.groupalone, and rewritesspec.chartRefon every match to the one the reconciling definition carries. No ownership relation ties a definition to the releases it rewrites.Impact
cozystack-api stamps both labels on every tenant application release it creates (
pkg/registry/apps/application/rest.go:237). So a second definition declaring an already-claimed kind repoints every existing tenant release of that kind at its own artifact, and the two definitions then rewrite each other's releases on every reconcile.The definition's object name is the only collision Helm itself would catch, through ownership metadata on an existing object, and the name is independent of the kind. A definition named anything at all can claim a kind that is already in use.
cozystack-api also builds one
config.Resourceper definition at start-up with no check that two do not name the same kind (pkg/cmd/server/start.go:251).Not a report against a released line
Putting an ApplicationDefinition on the cluster currently takes the same access as installing a chart, which is admin-level, so this crosses no trust boundary in any release today. It becomes reachable by a third-party repository publisher once the marketplace tap ships, which is why it is worth closing first.
Suggested fix
Reject an ApplicationDefinition whose
spec.application.kindis already claimed by another definition, at admission, so the invariant holds whoever creates the object and whatever it is named.Give
ApplicationDefinitionHelmReconcileran ownership relation and rewrite only the HelmReleases a definition actually backs, rather than every release carrying the kind label.Make a duplicate kind a loud failure at cozystack-api start-up rather than two registrations for one GVK.
Relation to other issues
#4359 proposes decoupling catalog registration from install so an unconfirmed tap installs nothing. This issue is the adjacent invariant: it holds for any repository an operator installs deliberately, tapped or not, so it is deliberately kept separate from that work.