design-proposal: cozymarketplace supplementary — backend, private sources, publication validation#23
Conversation
…rces, publication validation Supplementary to cozystack#18 by @kvaps. Accepts the repository-centric model and fills three concrete pieces that cozystack#18 lists as open questions or leaves implicit: in-cluster backend for the dashboard marketplace view, secretRef on PackageSourceRef for one-command private taps, and a cozypkg validate subcommand plus CI gate for publication validation. Per-package version pinning remains out of scope, siding with cozystack#18. Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
|
Warning Review limit reached
Next review available in: 17 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis pull request adds a new design proposal document for Cozymarketplace Phase 1, describing a server-side marketplace backend, a TapIndex cache controller, a secretRef field for private repositories, a cozypkg validate CLI, CI gating, and related security, testing, and rollout considerations. ChangesDesign Proposal Document
Estimated code review effort: 1 (Trivial) | ~5 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a supplementary design proposal for Cozymarketplace, detailing the backend endpoints, private repository support, and publication validation. Feedback on the proposal highlights an inconsistency regarding the namespace of the referenced Secret, pointing out that the PackageSourceRef struct contains a Namespace field while the text states the Secret must reside in cozy-system.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| type PackageSourceRef struct { | ||
| Kind, Name, Namespace, Path string | ||
| SecretRef *corev1.LocalObjectReference // NEW; nil preserves current behaviour | ||
| } | ||
| ``` | ||
|
|
||
| The `packagesource-reconciler` sets `spec.secretRef` on the materialized Flux source when `SecretRef != nil`. Secret format depends on source kind, matching what Flux source-controller already documents: `kubernetes.io/dockerconfigjson` for OCI; Opaque with `username`+`password` or `bearerToken` for Git over HTTPS; Opaque with `identity` (PEM private key) and `known_hosts` for Git over SSH. The Secret must exist in `cozy-system` before the reconciler runs; otherwise Flux reports a failed condition until it appears. This is symmetric with the platform-source change already in flight in `cozystack/cozystack#2472` — that PR closed the gap for the bootstrap platform source; this CRD field closes the same gap for every user-tapped repository. |
There was a problem hiding this comment.
There is an inconsistency between the PackageSourceRef struct definition and the described namespace behavior for the referenced Secret:
- The
PackageSourceRefstruct (lines 69-72) contains aNamespacefield, indicating that the referenced or materialized Flux source can reside in namespaces other thancozy-system. - However, line 75 (and line 117) states that the Secret must exist in
cozy-system.
Since Flux's spec.secretRef is namespace-scoped and cannot reference secrets across namespaces, the Secret must reside in the same namespace as the materialized Flux source (i.e., the namespace specified by PackageSourceRef.Namespace). If all materialized Flux sources are strictly created in cozy-system, the Namespace field in PackageSourceRef might be redundant or misleading.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@design-proposals/cozymarketplace-supplementary/README.md`:
- Around line 52-63: The marketplace read endpoints are currently described as
open to any authenticated user, which leaks tap/package metadata across tenants
when private taps exist. Update the access model in the `cozystack-api`
marketplace handlers so `GET /marketplace/taps`, `GET
/marketplace/taps/{name}/packages`, and `GET /marketplace/search` only return
taps the caller is authorized to view; add tap-level visibility checks or filter
by the caller’s allowed taps in the `TapIndex`-backed response path.
- Around line 79-81: The GitHub Actions validator flow currently trusts
PR-supplied `source.url`, creating an arbitrary outbound fetch path; tighten the
`cozypkg validate` workflow by adding an allowlist for permitted schemes/hosts
or by running the validator in a network-restricted sandbox before it is used on
PRs. Update the README/workflow description around the `validate` subcommand and
the PR-triggered meta-index job so the `source.url` and `source.tag` inputs are
explicitly constrained before any fetch occurs.
- Around line 115-117: Clarify the tap-removal retention flow by adding an
explicit finalizer/orphaning path in the tap and package lifecycle logic, since
helm.sh/resource-policy: keep alone does not protect controller-owned Package
CRs. Update the tap-removal handling referenced by the OrphanedSource behavior
so installed Package resources remain intact and are marked orphaned until
re-tapped or deleted via cozypkg del, rather than relying only on Helm
retention.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fe5e6b3d-7a1f-4ba0-8e9b-3f8894270d9a
📒 Files selected for processing (1)
design-proposals/cozymarketplace-supplementary/README.md
| The dashboard reads marketplace state through a small set of endpoints layered into `cozystack-api`, which already mediates dashboard access to platform CRs and existing auth/RBAC. No new component, no new CRDs — the marketplace state is fully derived from `PackageSource` plus the parsed artifact contents. | ||
|
|
||
| | Method | Path | Purpose | | ||
| |---|---|---| | ||
| | `GET` | `/marketplace/taps` | List connected taps with metadata. | | ||
| | `GET` | `/marketplace/taps/{name}/packages` | Packages exposed by one tap. | | ||
| | `GET` | `/marketplace/search?q=<query>` | Search across all taps by name, tag, description. | | ||
| | `POST` | `/marketplace/taps` | Connect a tap; creates `PackageSource` and, when given, the `Secret`. | | ||
| | `DELETE` | `/marketplace/taps/{name}` | Disconnect a tap. Lifecycle of installed `Package` CRs is an open question (see below). | | ||
|
|
||
| A `TapIndex` cache controller in the same binary watches `OCIRepository.status.artifact.revision`, pulls the parsed `marketplace.yaml` on each revision change, and serves the GET endpoints from memory. Without it, every search would hit OCI per request. Cluster-admin is required for `POST` and `DELETE`, matching the existing `Package` cluster-scoped model. `GET` is open to any authenticated user so tenant-admins can browse. | ||
|
|
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file='design-proposals/cozymarketplace-supplementary/README.md'
echo '--- around lines 1-140 ---'
nl -ba "$file" | sed -n '1,140p'
echo
echo '--- search for auth / private / visibility terms ---'
rg -n -i 'auth|authorization|private|tenant|rbac|cluster-admin|search|browse|visibility|secretref|secret ref|tap' "$file"Repository: cozystack/community
Length of output: 224
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file='design-proposals/cozymarketplace-supplementary/README.md'
echo '--- around lines 1-140 ---'
cat -n "$file" | sed -n '1,140p'
echo
echo '--- search for auth / private / visibility terms ---'
rg -n -i 'auth|authorization|private|tenant|rbac|cluster-admin|search|browse|visibility|secretref|secret ref|tap' "$file"Repository: cozystack/community
Length of output: 24411
Scope marketplace browse/search to authorized taps.
GET /marketplace/taps, /marketplace/taps/{name}/packages, and /marketplace/search should not be open to every authenticated user if private taps are supported; otherwise tap names, packages, tags, and descriptions leak across tenants. Scope these endpoints to the caller’s allowed taps or add tap-level visibility checks.
🧰 Tools
🪛 LanguageTool
[grammar] ~58-~58: Ensure spelling is correct
Context: ...e/search?q=| Search across all taps by name, tag, description. | |POST` |...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/cozymarketplace-supplementary/README.md` around lines 52 -
63, The marketplace read endpoints are currently described as open to any
authenticated user, which leaks tap/package metadata across tenants when private
taps exist. Update the access model in the `cozystack-api` marketplace handlers
so `GET /marketplace/taps`, `GET /marketplace/taps/{name}/packages`, and `GET
/marketplace/search` only return taps the caller is authorized to view; add
tap-level visibility checks or filter by the caller’s allowed taps in the
`TapIndex`-backed response path.
Move private-repository credential handling off a proposed PackageSourceRef.secretRef field and onto the Flux source created at tap time, matching the merged cozystack/cozystack#2472 pattern: the PackageSource reconciler only reads SourceRef to build the ArtifactGenerator and never creates the source, so the field would have had no reconcile path. Derive marketplace state from PackageSource plus ApplicationDefinition rather than a new marketplace.yaml, and align tap and untap semantics, the community index, and the validation reuse with community#12. No CRD change and no migration. Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
…s to cozymarketplace supplementary Add two mermaid diagrams (backend/tap architecture and the author/push/validate CI-gate flow) and scannable bold lead-ins on the Goals section, matching the visual structure of the sibling proposals Signed-off-by: IvanHunters <xorokhotnikov@gmail.com> cozystack#18 and cozystack#12.
Supplementary, not competing, to #18 by Andrei Kvapil (@kvaps). Accepts the repository-centric model and the meta-index design as-is; fills in three concrete pieces that #18 lists as open questions or leaves implicit:
cozystack-api, aTapIndexcache controller, and well-defined RBAC.SecretRefonPackageSourceRef— additive, nil-default CRD field so that one-commandcozypkg tapworks against private OCI/Git sources. Symmetric with the platform-source change already in flight in feat(operator): support private OCI registry credentials for platform source cozystack#2472.cozypkg validate+ CI gate — offline linter for marketplace repositories, reused in a GitHub Actions workflow that validates submissions before they appear in the meta-index.Per-package version pinning is explicitly out of scope, siding with #18.
Rendered:
design-proposals/cozymarketplace-supplementary/README.mdRelated: #18 (parent proposal), cozystack/cozystack#2472 (already-in-flight private platform source), cozystack/cozystack#2455 (motivation issue).
Opening as Draft for early feedback before #18 lands.
Summary by CodeRabbit