Repository navigation
Commit 67a8674
authored
feat(marketplace): community marketplace for External-Apps repositories (#3940)
## What this PR does
Implements the community marketplace for Cozystack External-Apps
repositories, per the approved design proposals **community#18** and
**community#23**, building on the **community#12** authoring workflow.
Anyone can publish an External-Apps repository over OCI, discover it,
connect it to a cluster, and install its apps the same way official
packages are installed, with a publication gate that keeps the index
safe.
Additive by construction: the existing PackageSource / External-Apps
pipeline is untouched, no CRD is added or migrated, and existing
installs and upgrades are unaffected. Per-package version pinning stays
out of scope, siding with #18.
Components:
- **cozypkg CLI** — new `validate`, `init`, `push`, `tap`/`untap`,
`search`. Scaffold a repository, publish it as an OCI artifact, register
it on a cluster in one command (optional pull secret for private
repositories), and discover packages through a metadata-only community
index. `validate` lints a repository offline (schema, chart paths, `helm
lint`, dependsOn, ApplicationDefinition wiring, privileged components);
with `--require-signature` it verifies a keyless cosign signature.
- **Marketplace backend** — a read/write, cluster-scoped `Tap` resource
in the existing `core.cozystack.io` group (a computed virtual resource:
no new group, no CRD, no etcd). Lists connected repositories and the
packages they expose, connects a repository (recording intent as a
labeled Flux `OCIRepository`), and disconnects one. Catalog metadata
only, never a pull credential.
- **Tap materializer** — a controller in cozystack-controller that, once
source-controller has pulled a connected repository's artifact, fetches
it over the Flux artifact URL (digest-verified, size-bounded,
path-traversal-guarded) and materializes the PackageSource(s) it carries
under the `community.` prefix, so a dashboard-connected tap becomes
installable without the apiserver pulling artifacts.
- **Publication gate** — a template for a `cozystack/packages-index`
repository: a metadata-only entry format and a GitHub Actions gate that
validates every changed entry with `cozypkg validate` (mandatory cosign
against the entry's recorded identity) under a two-lane merge policy
(owner version bump auto-merges on signed validation; a new entry or a
security-relevant edit goes to maintainer review).
- **Dashboard** — a Repositories view in the console marketplace, backed
by `Tap`, to browse and connect/disconnect repositories.
Access control: reading the catalog is open to authenticated users
(metadata only); connecting and disconnecting require cluster-admin via
the delegated apiserver RBAC.
Verification: `go build` / `go vet` / `go test`, dashboard `pnpm
typecheck` + eslint, and the gate's `shellcheck` are all green.
Server-side authz denial and the end-to-end
connect→materialize→disconnect round-trip are not exercised here
(hermetic change) and are the main follow-up.
### Screenshots
The dashboard Repositories view is included, but screenshots are not
attached: rendering it needs a live cluster running the new `Tap`
apiserver, which this static change cannot stand up. Tracked as a
follow-up (a cozystack-pr-test run on a disposable cluster); this is one
reason the PR is a draft.
### Downstream repositories
Walked the trigger map against the diff. This is additive tooling plus a
new virtual resource; it does not force a change in any listed
repository, and `external-apps-example` keeps working on the existing
chart model. Left every box empty (rather than ticking "No downstream
repository is affected") so a maintainer can confirm — in particular
whether `external-apps-example` should later gain a PackageSource-based
example that `cozypkg init` now scaffolds.
- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:
### Release note
```release-note
feat(marketplace): add a community marketplace for External-Apps repositories — cozypkg validate/init/push/tap/untap/search, a cluster-scoped Tap API in core.cozystack.io with an operator-side artifact materializer, keyless cosign verification, a two-lane publication gate, and a dashboard Repositories view
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added Marketplace repository connections (“Taps”) with dashboard
management, readiness status, package catalogs, and optional
credentials.
- Added repository search by name, source, and package metadata.
- Added a searchable community package index with version-pinned
resolution.
- Added `cozypkg init`, `push`, `tap`, and `untap` commands.
- Added offline repository and artifact validation with optional chart
linting and signature checks.
- Added safeguards requiring confirmation before installing packages
with privileged components.
- Added automatic synchronization of tapped package catalogs.
- **Documentation**
- Added community package index guidance, validation workflow, and an
example entry.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->53 files changed
Lines changed: 6475 additions & 54 deletions
File tree
- api/api-rules
- cmd
- cozypkg/cmd
- cozystack-operator
- hack/packages-index
- entries
- github-workflows
- scripts
- internal
- marketplace
- collision
- naming
- tapconst
- operator
- packages/system
- cozystack-api
- templates
- tests
- cozystack-basics
- templates
- tests
- cozystack-controller/templates
- dashboard/images/console
- apps/console/src
- lib
- routes
- packages/types/src
- pkg
- apiserver
- apis/core
- fuzzer
- v1alpha1
- generated/openapi
- registry/core/tap
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
3 | 5 | | |
4 | 6 | | |
5 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
29 | 28 | | |
| 29 | + | |
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
40 | | - | |
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | | - | |
45 | | - | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
59 | 60 | | |
60 | 61 | | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
119 | 120 | | |
120 | 121 | | |
121 | 122 | | |
122 | | - | |
| 123 | + | |
123 | 124 | | |
124 | 125 | | |
125 | 126 | | |
| |||
178 | 179 | | |
179 | 180 | | |
180 | 181 | | |
181 | | - | |
| 182 | + | |
182 | 183 | | |
183 | 184 | | |
184 | 185 | | |
| |||
240 | 241 | | |
241 | 242 | | |
242 | 243 | | |
243 | | - | |
| 244 | + | |
244 | 245 | | |
245 | 246 | | |
246 | 247 | | |
| |||
354 | 355 | | |
355 | 356 | | |
356 | 357 | | |
357 | | - | |
| 358 | + | |
358 | 359 | | |
359 | 360 | | |
360 | 361 | | |
| |||
462 | 463 | | |
463 | 464 | | |
464 | 465 | | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
465 | 478 | | |
466 | 479 | | |
467 | 480 | | |
| |||
541 | 554 | | |
542 | 555 | | |
543 | 556 | | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
544 | 592 | | |
545 | 593 | | |
| 594 | + | |
546 | 595 | | |
547 | 596 | | |
548 | 597 | | |
549 | | - | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
0 commit comments