From 14dcca83dc56a746d46e9e217fb8cfb02edd52fe Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Sat, 30 May 2026 11:35:15 -0700 Subject: [PATCH 1/2] Create a skill to author HIPs Signed-off-by: George Jenkins --- skills/hip-author-workspace/evals/evals.json | 26 + .../feature-hip/eval_metadata.json | 47 ++ .../feature-hip/with_skill/grading.json | 46 ++ .../with_skill/outputs/hip-9999.md | 344 +++++++++++++ .../feature-hip/with_skill/timing.json | 1 + .../feature-hip/without_skill/grading.json | 46 ++ .../without_skill/outputs/hip-9999.md | 470 ++++++++++++++++++ .../feature-hip/without_skill/timing.json | 1 + .../process-hip/eval_metadata.json | 47 ++ .../process-hip/with_skill/grading.json | 51 ++ .../with_skill/outputs/hip-9999.md | 242 +++++++++ .../process-hip/with_skill/timing.json | 1 + .../process-hip/without_skill/grading.json | 51 ++ .../without_skill/outputs/hip-9999.md | 351 +++++++++++++ .../process-hip/without_skill/timing.json | 1 + .../iteration-1/vague-idea/eval_metadata.json | 47 ++ .../vague-idea/with_skill/grading.json | 51 ++ .../vague-idea/with_skill/outputs/hip-9999.md | 303 +++++++++++ .../vague-idea/with_skill/timing.json | 1 + .../vague-idea/without_skill/grading.json | 51 ++ .../without_skill/outputs/hip-9999.md | 455 +++++++++++++++++ .../vague-idea/without_skill/timing.json | 1 + skills/hip-author/SKILL.md | 174 +++++++ skills/hip-author/references/hip-template.md | 156 ++++++ 24 files changed, 2964 insertions(+) create mode 100644 skills/hip-author-workspace/evals/evals.json create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/timing.json create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/eval_metadata.json create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/timing.json create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/timing.json create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/eval_metadata.json create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md create mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json create mode 100644 skills/hip-author/SKILL.md create mode 100644 skills/hip-author/references/hip-template.md diff --git a/skills/hip-author-workspace/evals/evals.json b/skills/hip-author-workspace/evals/evals.json new file mode 100644 index 00000000..f579a439 --- /dev/null +++ b/skills/hip-author-workspace/evals/evals.json @@ -0,0 +1,26 @@ +{ + "skill_name": "hip-author", + "evals": [ + { + "id": 0, + "name": "feature-hip", + "prompt": "I want to write a HIP for adding native support for chart signing using Sigstore/cosign instead of the current PGP-based provenance system. The current .prov file approach is clunky and almost nobody uses it because PGP key management is painful. Cosign is already the standard in the container ecosystem and it would make chart verification way more accessible.", + "expected_output": "A well-structured HIP document with all required sections, proper YAML preamble with hip: 9999, type: feature, status: draft. Should address backwards compatibility with existing .prov files.", + "files": [] + }, + { + "id": 1, + "name": "process-hip", + "prompt": "I think we should create a formal process for how Helm handles security embargoes and coordinated disclosure with downstream distributors. Right now the SECURITY.md covers reporting but there's no documented process for how we coordinate with distro maintainers who package Helm before a CVE goes public.", + "expected_output": "A well-structured HIP document with type: process, addressing the coordination gap in security disclosure. Should reference existing SECURITY.md and governance docs.", + "files": [] + }, + { + "id": 2, + "name": "vague-idea", + "prompt": "I have a half-baked idea - what if Helm charts could somehow declare their resource requirements or dependencies on cluster capabilities? Like, a chart could say 'I need an ingress controller' or 'I need at least 3 nodes' and helm install would check that before deploying. I'm not sure if this is even feasible or if it's too broad.", + "expected_output": "Should help refine the vague idea into something concrete before producing any HIP text. Should probe scope, suggest narrowing, and only proceed to drafting after the idea is focused.", + "files": [] + } + ] +} diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json b/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json new file mode 100644 index 00000000..587ff20e --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json @@ -0,0 +1,47 @@ +{ + "eval_id": 0, + "eval_name": "feature-hip", + "prompt": "I want to write a HIP for adding native support for chart signing using Sigstore/cosign instead of the current PGP-based provenance system. The current .prov file approach is clunky and almost nobody uses it because PGP key management is painful. Cosign is already the standard in the container ecosystem and it would make chart verification way more accessible.", + "assertions": [ + { + "name": "valid_yaml_preamble", + "description": "HIP starts with valid YAML frontmatter containing all required fields (hip, title, authors, created, type, status)", + "type": "structural" + }, + { + "name": "placeholder_hip_number", + "description": "Uses hip: 9999 (or quoted '9999') as placeholder, not an invented number", + "type": "structural" + }, + { + "name": "type_is_feature", + "description": "type field is set to 'feature'", + "type": "structural" + }, + { + "name": "status_is_draft", + "description": "status field is set to 'draft'", + "type": "structural" + }, + { + "name": "all_required_sections", + "description": "Contains all required sections: Abstract, Motivation, Rationale, Specification, Backwards compatibility, Security implications, How to teach this, Reference implementation, Rejected ideas, Open issues, References", + "type": "structural" + }, + { + "name": "abstract_concise", + "description": "Abstract is roughly 100-300 words (not a full page, not a single sentence)", + "type": "quality" + }, + { + "name": "backwards_compat_addresses_prov", + "description": "Backwards compatibility section explicitly addresses migration from existing .prov/PGP system", + "type": "content" + }, + { + "name": "specification_has_details", + "description": "Specification section contains concrete technical details (CLI flags, file formats, or workflow descriptions), not just hand-waving", + "type": "content" + } + ] +} diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json new file mode 100644 index 00000000..263c24ea --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json @@ -0,0 +1,46 @@ +{ + "eval_name": "feature-hip", + "variant": "with_skill", + "expectations": [ + { + "text": "valid_yaml_preamble", + "passed": true, + "evidence": "Found valid YAML frontmatter" + }, + { + "text": "placeholder_hip_number", + "passed": true, + "evidence": "Found hip: 9999 placeholder" + }, + { + "text": "status_is_draft", + "passed": true, + "evidence": "status is draft" + }, + { + "text": "all_required_sections", + "passed": true, + "evidence": "All 11 required sections present" + }, + { + "text": "abstract_concise", + "passed": true, + "evidence": "Abstract is 145 words (target: 100-300)" + }, + { + "text": "type_is_feature", + "passed": true, + "evidence": "type is feature" + }, + { + "text": "backwards_compat_addresses_prov", + "passed": true, + "evidence": "Backwards compat section references .prov/PGP" + }, + { + "text": "specification_has_details", + "passed": true, + "evidence": "Specification is 733 words, has code examples" + } + ] +} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md new file mode 100644 index 00000000..b296ab72 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md @@ -0,0 +1,344 @@ +--- +hip: 9999 +title: "Native Chart Signing with Sigstore/Cosign" +authors: ["User "] +created: "2026-05-30" +type: "feature" +status: "draft" +--- + +## Abstract + +This HIP proposes replacing Helm's current PGP-based chart provenance system (`.prov` files) with native support for Sigstore/cosign signing and verification. The existing provenance mechanism, introduced in Helm 2, requires chart publishers to manage PGP keys and consumers to obtain and trust those keys manually. This friction has led to near-zero adoption in practice, leaving the vast majority of Helm charts deployed without any signature verification. + +Sigstore's cosign has become the de facto signing standard in the container ecosystem, offering keyless signing via OIDC identity, transparency log integration through Rekor, and a dramatically simpler user experience. This proposal adds `helm sign` and `helm verify` subcommands backed by cosign, stores signatures as OCI artifacts alongside charts in OCI registries, and introduces a `cosign` verification mode for `helm install` and `helm upgrade`. The existing PGP-based `.prov` system remains available but is deprecated in favor of the new approach. + +## Motivation + +### The PGP Provenance Problem + +Helm has supported chart provenance since Helm 2 through `.prov` files containing PGP signatures. Despite existing for years, this system sees almost no real-world usage. The reasons are well-documented: + +**Key management burden:** Chart publishers must generate, secure, rotate, and distribute PGP keys. Consumers must discover, import, and decide to trust those keys. There is no standard keyserver or trust model for the Helm ecosystem, so every publisher invents their own distribution mechanism (README instructions, website downloads, out-of-band communication). + +**Tooling friction:** The `helm package --sign` workflow requires a local PGP keyring. CI/CD pipelines must be configured with PGP secret keys, which creates secret management overhead. The `helm verify` command requires the public key to be pre-imported, which means consumers must perform manual setup before verification can occur. + +**Ecosystem disconnect:** The container ecosystem has broadly adopted Sigstore/cosign for image signing. Organizations that sign their container images with cosign must use an entirely separate signing infrastructure for their Helm charts. This duplication is wasteful and confusing. + +**No transparency or auditability:** PGP signatures provide no public transparency log. There is no way to audit when a chart was signed, by whom, or whether a key has been compromised without the publisher explicitly communicating revocation. + +### Who Is Affected + +- **Chart publishers** (e.g., Bitnami, major open-source projects, enterprise platform teams) who want to provide verifiable charts but find PGP too burdensome to set up and maintain. +- **Cluster operators and security teams** who want to enforce chart verification policies but cannot because the charts they consume are unsigned. +- **Enterprise compliance teams** who need audit trails for software supply chain integrity and cannot get them from the current system. +- **CI/CD pipeline authors** who must integrate signing into automated workflows and find PGP key management in pipelines painful. + +### The Sigstore Opportunity + +Sigstore has achieved broad adoption in the cloud-native ecosystem. Cosign is used to sign container images across major registries, and tools like Kyverno and OPA Gatekeeper can enforce cosign signature policies. By aligning Helm chart signing with the same infrastructure, chart verification becomes a natural extension of existing supply chain security practices rather than a separate, parallel system. + +## Rationale + +### Why Sigstore/Cosign Over Other Approaches + +**Keyless signing via OIDC:** Cosign's keyless mode lets publishers sign charts using their existing identity (GitHub Actions OIDC, Google Cloud identity, etc.) without managing long-lived signing keys. This eliminates the single biggest barrier to adoption. A chart published from a GitHub Actions workflow can be signed automatically with zero key management. + +**Transparency log (Rekor):** Every signature is recorded in an immutable, publicly auditable transparency log. This provides the auditability that PGP signatures lack and enables detection of compromised signing identities. + +**OCI-native storage:** Cosign stores signatures as OCI artifacts alongside the signed content. Since Helm 3.8+ supports OCI registries as a first-class chart storage mechanism, cosign signatures fit naturally into the same registry infrastructure. No separate `.prov` file hosting is needed. + +**Ecosystem alignment:** kubectl, Kyverno, OPA Gatekeeper, Tekton, and other CNCF projects already integrate with Sigstore. Using the same signing infrastructure for Helm charts means organizations can enforce unified supply chain policies across container images and Helm charts. + +### How Other Projects Handle This + +- **Container images:** Cosign is the standard. Registries like Docker Hub, GitHub Container Registry, and Amazon ECR support cosign signatures as OCI artifacts. +- **Kubernetes manifests:** The Kubernetes project signs release artifacts with cosign. +- **Linux packages:** Sigstore is being adopted for npm (via npmjs provenance), Python (via PEP 740), and other package ecosystems. + +Helm is an outlier in the CNCF ecosystem by still relying exclusively on PGP for provenance. + +### Key Tradeoffs + +- **Dependency on Sigstore infrastructure:** Keyless signing requires access to Sigstore's Fulcio CA and Rekor transparency log (or self-hosted equivalents). This is acceptable because Sigstore infrastructure is operated by the Linux Foundation and has strong availability commitments, and organizations can run private instances. +- **Two signing systems during transition:** Maintaining both PGP and cosign signing adds complexity, but a clean break would strand the small number of existing PGP provenance users. Deprecation with a clear timeline is the pragmatic path. +- **OCI registry requirement for signatures:** Cosign signatures stored as OCI artifacts require an OCI-compatible registry. Charts distributed via HTTP repositories cannot use this signature storage mechanism, though they can use cosign with key-based signing and detached signatures. + +## Specification + +### New CLI Commands + +#### `helm sign` + +Signs a packaged chart (`.tgz`) using cosign. + +```bash +# Keyless signing (uses OIDC identity, records in Rekor) +helm sign mychart-1.0.0.tgz + +# Key-based signing +helm sign mychart-1.0.0.tgz --key cosign.key + +# Sign and push signature to OCI registry +helm sign mychart-1.0.0.tgz --push oci://registry.example.com/charts + +# Sign with custom Rekor and Fulcio endpoints (private Sigstore) +helm sign mychart-1.0.0.tgz \ + --rekor-url https://rekor.internal.example.com \ + --fulcio-url https://fulcio.internal.example.com +``` + +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--key` | (none) | Path to cosign private key. If omitted, keyless signing is used. | +| `--push` | (none) | OCI registry reference to push signature to. | +| `--rekor-url` | `https://rekor.sigstore.dev` | Rekor transparency log URL. | +| `--fulcio-url` | `https://fulcio.sigstore.dev` | Fulcio CA URL for keyless signing. | +| `--output` | (none) | Write detached signature to file instead of pushing to registry. | +| `--tlog-upload` | `true` | Upload signature to transparency log. Set to `false` for air-gapped environments using key-based signing. | + +#### `helm verify` + +Verifies a chart's cosign signature. + +```bash +# Verify using keyless identity (checks Rekor + Fulcio certificate) +helm verify mychart-1.0.0.tgz \ + --certificate-identity user@example.com \ + --certificate-oidc-issuer https://accounts.google.com + +# Verify using a public key +helm verify mychart-1.0.0.tgz --key cosign.pub + +# Verify a chart in an OCI registry (fetches signature from registry) +helm verify oci://registry.example.com/charts/mychart --version 1.0.0 \ + --certificate-identity-regexp '.*@example\.com' \ + --certificate-oidc-issuer https://accounts.google.com + +# Verify with a detached signature file +helm verify mychart-1.0.0.tgz --signature mychart-1.0.0.tgz.sig --key cosign.pub +``` + +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--key` | (none) | Path to cosign public key for key-based verification. | +| `--certificate-identity` | (none) | Expected signer identity for keyless verification (exact match). | +| `--certificate-identity-regexp` | (none) | Regex pattern for signer identity. | +| `--certificate-oidc-issuer` | (none) | Expected OIDC issuer for keyless verification. | +| `--certificate-oidc-issuer-regexp` | (none) | Regex pattern for OIDC issuer. | +| `--signature` | (none) | Path to detached signature file. | +| `--rekor-url` | `https://rekor.sigstore.dev` | Rekor URL for transparency log verification. | + +### Verification on Install/Upgrade + +The `helm install` and `helm upgrade` commands gain a `--verify-cosign` flag: + +```bash +# Verify cosign signature before installing +helm install myrelease oci://registry.example.com/charts/mychart \ + --version 1.0.0 \ + --verify-cosign \ + --certificate-identity-regexp '.*@bitnami\.com' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com + +# Verify with public key +helm install myrelease oci://registry.example.com/charts/mychart \ + --version 1.0.0 \ + --verify-cosign \ + --key cosign.pub +``` + +When `--verify-cosign` is specified, the chart is not installed unless signature verification succeeds. This is distinct from the existing `--verify` flag, which uses PGP provenance. + +### Signature Storage + +For charts in OCI registries, cosign signatures are stored as OCI artifacts using cosign's standard tagging convention (`sha256-.sig`). This is the same mechanism used for container image signatures and requires no custom infrastructure. + +For charts distributed outside of OCI registries (e.g., HTTP chart repositories), signatures can be stored as detached `.cosign.sig` files alongside the chart `.tgz` in the repository index, or verified against the Rekor transparency log by digest. + +### Data Structures + +The chart repository `index.yaml` gains an optional `cosignSignature` field: + +```yaml +entries: + mychart: + - version: 1.0.0 + digest: sha256:abc123... + urls: + - https://example.com/charts/mychart-1.0.0.tgz + cosignSignature: + type: "detached" + url: "https://example.com/charts/mychart-1.0.0.tgz.cosign.sig" +``` + +For OCI registries, no index changes are needed since cosign's standard OCI artifact discovery mechanism is used. + +### Integration with `helm package` + +A convenience flag is added to `helm package`: + +```bash +# Package and sign in one step +helm package mychart/ --cosign-sign +helm package mychart/ --cosign-sign --cosign-key cosign.key +``` + +### Deprecation of PGP Provenance + +The existing PGP-based `--sign`, `--verify`, and `--keyring` flags on `helm package`, `helm verify`, and `helm install` are deprecated but not removed. They will emit deprecation warnings directing users to the cosign-based equivalents. A future major version of Helm may remove PGP provenance support entirely. + +### Edge Cases + +- **Air-gapped environments:** Key-based signing with `--tlog-upload=false` supports environments without internet access to Sigstore infrastructure. Verification uses the public key directly without Rekor. +- **Multiple signatures:** A chart can have multiple cosign signatures (e.g., signed by both the chart author and an enterprise security review). `helm verify` succeeds if any provided identity/key matches. +- **Chart dependencies:** `helm dependency update` does not verify dependency signatures. Signature verification applies to the final packaged chart. A future HIP could address recursive dependency verification. +- **Helm plugins:** The signing and verification logic is implemented in Helm core, not as a plugin, to ensure consistent behavior and avoid the bootstrapping problem of needing to verify a plugin before using it. + +## Backwards Compatibility + +This proposal is fully backwards compatible. All changes are additive: + +- **New commands:** `helm sign` and `helm verify` (with cosign) are new. The existing `helm verify` command for PGP provenance is preserved under `helm verify --legacy-pgp` (or simply continues to work when a `--keyring` is specified, since the flag combination is unambiguous). +- **New flags:** `--verify-cosign` on `helm install` / `helm upgrade` is new and opt-in. The existing `--verify` flag for PGP is unchanged. +- **Index format:** The `cosignSignature` field in `index.yaml` is optional. Older Helm clients ignore unknown fields. +- **OCI registries:** Cosign signatures as OCI artifacts do not interfere with chart storage or retrieval. Older Helm clients that do not understand cosign simply skip verification. + +No existing workflow breaks. Users who currently use PGP provenance (a very small number) can continue to do so. The deprecation warning is informational and does not change behavior. + +This feature is additive and appropriate for a minor version release. + +## Security Implications + +### Improvements Over Current System + +- **Transparency log:** Rekor provides a public, append-only record of every signing event. If a signing key or identity is compromised, the transparency log enables detection and forensic analysis. +- **Short-lived certificates:** Keyless signing uses short-lived certificates (typically 10-minute validity) rather than long-lived PGP keys, reducing the window of exposure if credentials are compromised. +- **Identity-based trust:** Instead of trusting opaque PGP key IDs, consumers trust identifiable entities (email addresses, CI/CD pipeline identities) bound to OIDC issuers, making trust decisions more intuitive. + +### Attack Surface Considerations + +- **Sigstore infrastructure dependency:** Keyless signing depends on Fulcio and Rekor availability. If these services are unavailable, keyless signing fails. Mitigation: support key-based signing as a fallback, and support private Sigstore deployments. +- **OIDC identity compromise:** If an attacker compromises the OIDC identity used for signing (e.g., a GitHub Actions workflow token), they could sign malicious charts. Mitigation: the Rekor transparency log records all signing events, enabling detection. Organizations should monitor Rekor for unexpected signing events on their identities. +- **Signature stripping:** An attacker with registry write access could remove cosign signatures. Mitigation: `--verify-cosign` on install causes a hard failure if no valid signature is found, preventing installation of unsigned charts. Registry access controls remain the primary defense. +- **Cosign library vulnerabilities:** Embedding cosign's verification logic in Helm adds cosign's dependency tree to Helm's attack surface. Mitigation: use cosign as a well-maintained Go library with active security response, and track upstream releases. + +### Misuse Scenarios + +- A malicious chart author could sign a chart with a legitimate-looking but unrelated identity. Users must verify the `--certificate-identity` matches the expected publisher, not just that "a signature exists." +- Policy enforcement tools (Kyverno, OPA) should be used in production to codify trusted identities rather than relying on manual `--verify-cosign` invocations. + +## How to Teach This + +### Documentation Additions + +1. **Chart Signing Guide:** A new top-level documentation page covering both keyless and key-based signing workflows, replacing the current provenance documentation as the recommended approach. +2. **Supply Chain Security Guide:** A conceptual guide explaining how cosign chart signing fits into a broader supply chain security strategy alongside image signing, SBOM generation, and policy enforcement. +3. **Migration Guide:** Step-by-step instructions for chart publishers currently using PGP provenance to switch to cosign signing. +4. **CI/CD Examples:** Ready-to-use workflow examples for GitHub Actions, GitLab CI, and other popular CI systems showing how to sign charts in automated pipelines. + +### Key Example Pattern + +The simplest and most common pattern for a chart publisher using GitHub Actions: + +```yaml +# .github/workflows/release.yml +- name: Package and sign chart + run: | + helm package mychart/ + helm sign mychart-*.tgz --push oci://ghcr.io/${{ github.repository }} +``` + +For a consumer: + +```bash +helm install myrelease oci://ghcr.io/org/charts/mychart \ + --version 1.0.0 \ + --verify-cosign \ + --certificate-identity-regexp '.*@myorg\.com' \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com +``` + +### How This Fits into Existing Helm Concepts + +Signing and verification are presented as an optional but recommended step in the chart lifecycle: author, package, **sign**, push, **verify**, install. This mirrors the existing provenance concept but with dramatically lower friction. The `helm sign` / `helm verify` commands are direct analogs of the existing PGP provenance workflow, so users familiar with the old system can map concepts directly. + +## Reference Implementation + +No reference implementation exists yet. The implementation will involve: + +1. Adding the `cosign` Go library (`github.com/sigstore/cosign/v2`) as a dependency to the Helm project. +2. Implementing `helm sign` and `helm verify` subcommands in `cmd/helm/`. +3. Adding `--verify-cosign` and related flags to `helm install` and `helm upgrade`. +4. Adding the `--cosign-sign` convenience flag to `helm package`. +5. Extending the OCI registry client to discover and store cosign signatures as OCI artifacts. +6. Adding the optional `cosignSignature` field to the repository index parser. +7. Adding deprecation warnings to the existing PGP provenance flags. +8. Comprehensive tests covering keyless signing, key-based signing, verification modes, air-gapped scenarios, and error handling. + +A proof-of-concept branch will be linked here once development begins. + +## Rejected Ideas + +### Cosign as a Helm Plugin + +Implementing signing as an external plugin (e.g., `helm-cosign`) was considered. This was rejected because: +- Plugins must themselves be trusted, creating a bootstrapping problem. +- Plugin installation is an extra step that reduces adoption. +- Core integration ensures consistent behavior across all Helm installations. +- The Helm project should own its supply chain security story. + +### Notation (Microsoft) Instead of Cosign + +Notation is another Sigstore-adjacent signing tool focused on the OCI ecosystem. It was rejected in favor of cosign because: +- Cosign has significantly broader adoption in the Kubernetes/CNCF ecosystem. +- Cosign's keyless signing mode is more mature. +- Most organizations already use cosign for container image signing. +- Supporting both would add complexity without proportional benefit. Notation support could be added in a future HIP if demand warrants it. + +### Requiring Cosign for All Charts + +Making chart signing mandatory was rejected because: +- It would break the existing ecosystem where nearly all charts are unsigned. +- Chart repositories and registries would need universal signing support. +- Development and testing workflows should not require signing infrastructure. +- Signing should be encouraged through tooling and documentation, not mandated. + +### Removing PGP Provenance Immediately + +A clean break from PGP was considered. This was rejected because: +- Some users may have invested in PGP provenance workflows. +- A deprecation period gives the community time to migrate. +- Both systems can coexist without technical conflict. + +### Using In-Toto Attestations Instead of Raw Signatures + +In-toto attestations provide richer metadata than raw signatures (e.g., build provenance, SBOM linkage). While valuable, this was rejected as the initial scope because: +- Raw signatures solve the immediate adoption problem with minimal complexity. +- In-toto attestation support can be layered on top in a future HIP. +- Cosign supports both raw signatures and attestations, so the foundation supports future extension. + +## Open Issues + +1. **Flag naming for legacy PGP:** Should the existing `--verify` flag be renamed to `--verify-pgp` or should it remain as-is with `--verify-cosign` being the new addition? The current proposal keeps `--verify` unchanged for backwards compatibility. +2. **Default verification in future major version:** Should a future Helm 4.x make `--verify-cosign` the default behavior for OCI registry installs? This is out of scope for this HIP but worth discussing. +3. **Recursive dependency verification:** Should `helm dependency update` verify cosign signatures on dependencies? This adds complexity and is deferred to a future proposal. +4. **Private Sigstore configuration:** How should private Fulcio/Rekor endpoints be configured persistently (environment variables, Helm configuration file, or both)? +5. **Cosign library versioning:** How will Helm track cosign library updates, and what is the compatibility commitment? + +## References + +- [Sigstore](https://www.sigstore.dev/) +- [Cosign Documentation](https://docs.sigstore.dev/cosign/signing/overview/) +- [Helm Provenance and Integrity](https://helm.sh/docs/topics/provenance/) +- [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) +- [Cosign OCI Signature Storage](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md) +- [Rekor Transparency Log](https://docs.sigstore.dev/logging/overview/) +- [Fulcio Certificate Authority](https://docs.sigstore.dev/certificate_authority/overview/) +- [Kyverno Sigstore Verification](https://kyverno.io/docs/writing-policies/verify-images/sigstore/) +- [SLSA Supply Chain Framework](https://slsa.dev/) +- [HIP-0001: HIP Purpose and Guidelines](https://github.com/helm/community/blob/main/hips/hip-0001.md) diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json new file mode 100644 index 00000000..10d51517 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json @@ -0,0 +1 @@ +{"total_tokens": 48451, "duration_ms": 150057, "total_duration_seconds": 150.1} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json new file mode 100644 index 00000000..3364bcba --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json @@ -0,0 +1,46 @@ +{ + "eval_name": "feature-hip", + "variant": "without_skill", + "expectations": [ + { + "text": "valid_yaml_preamble", + "passed": true, + "evidence": "Found valid YAML frontmatter" + }, + { + "text": "placeholder_hip_number", + "passed": true, + "evidence": "Found hip: 9999 placeholder" + }, + { + "text": "status_is_draft", + "passed": true, + "evidence": "status is draft" + }, + { + "text": "all_required_sections", + "passed": true, + "evidence": "All 11 required sections present" + }, + { + "text": "abstract_concise", + "passed": true, + "evidence": "Abstract is 110 words (target: 100-300)" + }, + { + "text": "type_is_feature", + "passed": true, + "evidence": "type is feature" + }, + { + "text": "backwards_compat_addresses_prov", + "passed": true, + "evidence": "Backwards compat section references .prov/PGP" + }, + { + "text": "specification_has_details", + "passed": true, + "evidence": "Specification is 1097 words, has code examples" + } + ] +} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md new file mode 100644 index 00000000..152386f4 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md @@ -0,0 +1,470 @@ +--- +hip: 9999 +title: "Native Chart Signing and Verification with Sigstore/Cosign" +authors: [""] +created: "2026-05-30" +type: "feature" +status: "draft" +--- + +## Abstract + +This HIP proposes replacing Helm's current PGP-based chart provenance system (`.prov` files) with native support for Sigstore/cosign signing and verification. The current provenance mechanism suffers from extremely low adoption due to the complexity of PGP key management, lack of integration with modern identity providers, and an opaque verification workflow. Sigstore provides keyless signing via OIDC identity, transparency logging via Rekor, and a verification model already established as the standard in the container image ecosystem. This proposal introduces `helm sign` and `helm verify` commands backed by cosign, stores signatures as OCI artifacts alongside chart packages in OCI registries, and maintains backward compatibility with the existing `.prov` system during a deprecation period. + +## Motivation + +### The Current State of Chart Provenance + +Helm has supported chart provenance since Helm 2 through PGP-based `.prov` files. The system requires chart publishers to maintain PGP keypairs, distribute public keys out-of-band, and package `.prov` files alongside `.tgz` chart archives. Despite being available for years, adoption is negligibly low across the ecosystem. Several factors contribute to this: + +**PGP key management is burdensome.** Publishers must generate keypairs, protect private keys, establish key rotation policies, and distribute public keys through a side channel. There is no standardized discovery mechanism for Helm chart signing keys. Users must manually locate, download, and import the correct public key before verification can occur. + +**The verification workflow is disconnected.** Running `helm verify` requires the user to have already obtained and trusted the publisher's public key. There is no integration with any identity provider, certificate authority, or transparency log. Users have no easy way to determine whether a chart was signed by a legitimate publisher without prior out-of-band key exchange. + +**The ecosystem has moved on.** The container ecosystem has converged on Sigstore (cosign, Rekor, Fulcio) as the standard for artifact signing and verification. Kubernetes itself, along with major container registries, CI/CD platforms, and policy engines, support Sigstore natively. Helm charts distributed as OCI artifacts sit in the same registries as container images but lack the same signing primitives. + +**OCI registries are now first-class.** Helm 3.8+ supports OCI registries as a native chart storage backend. OCI registries support attaching signatures, attestations, and other metadata as associated artifacts (via the OCI Reference Types / Referrers API). The `.prov` file model predates OCI support and does not integrate with this ecosystem. + +### Who Is Affected + +- **Chart publishers** who want to sign their charts but are deterred by PGP complexity. +- **Chart consumers** who want to verify chart integrity and provenance before deploying to production clusters. +- **Platform and security teams** who need to enforce signing policies as part of supply chain security requirements. +- **CI/CD pipeline operators** who need automated, keyless signing integrated with workload identity. +- **Policy engine users** (OPA/Gatekeeper, Kyverno, Sigstore Policy Controller) who want to enforce chart signature verification using the same trust framework they use for container images. + +### Real-World Impact + +Supply chain security has become a critical concern across the cloud native ecosystem. Frameworks such as SLSA (Supply-chain Levels for Software Artifacts) require artifact signing as a baseline. Organizations that enforce container image signing via cosign today have no equivalent mechanism for Helm charts, creating a gap in their supply chain security posture. Native Sigstore support would close this gap and align Helm with the broader CNCF security ecosystem. + +## Rationale + +### Why Sigstore/Cosign + +Sigstore is the CNCF's graduated project for software artifact signing. It provides three core components relevant to this proposal: + +1. **Fulcio** - A free certificate authority that issues short-lived certificates tied to OIDC identities (GitHub Actions, Google, Microsoft, etc.). This enables "keyless" signing where the signer's identity is their existing OIDC identity rather than a long-lived PGP key. +2. **Rekor** - A transparency log that records signing events immutably. Anyone can verify that a signature was created at a specific time by a specific identity without needing to trust the signer's key distribution. +3. **Cosign** - The client tool (and Go library) for signing and verifying OCI artifacts. It already supports signing container images, SBOMs, attestations, and arbitrary blobs. + +Cosign's Go library (`sigstore/cosign/v2`) is well-maintained, has a stable API, and is already used by numerous CNCF projects. Integrating it as a library dependency (rather than shelling out to the `cosign` CLI) provides a clean, testable integration. + +### Why Not Notation (Notary v2) + +Notation (the CNCF's other signing project, evolved from Notary v2) was considered. While Notation is a valid signing framework, cosign has significantly broader adoption in the Kubernetes ecosystem, is already the de facto standard for container image signing, and has a more mature Go library. Choosing cosign maximizes interoperability with existing toolchains. If Notation support is desired in the future, the proposed architecture allows additional signature backends to be added. + +### Why OCI Artifact Signatures Instead of Files + +The current `.prov` file approach stores signatures as separate files alongside chart `.tgz` archives. This model has several drawbacks: signature files can become separated from charts, classic chart repositories (index.yaml-based) have no formal association between a chart and its provenance file, and the model does not extend to OCI registries. + +OCI registries support the Referrers API (OCI Distribution Spec 1.1), which allows artifacts (such as signatures) to be associated with a subject artifact (such as a chart). Cosign already uses this mechanism for container image signatures. Storing chart signatures as OCI reference artifacts keeps the signature co-located with the chart, discoverable via standard registry APIs, and consistent with how container image signatures work. + +For charts distributed through classic (index.yaml) repositories rather than OCI registries, this proposal supports signing the chart `.tgz` as a blob and storing the signature bundle (Sigstore bundle format) as a `.cosign.bundle` file alongside the chart archive. + +### Why Keyless by Default + +Keyless signing (via Fulcio and OIDC) is the recommended default because it eliminates the key management problem that killed adoption of the PGP-based system. Publishers sign with their identity (e.g., a GitHub Actions workflow identity, a Google account, etc.) and the signature is recorded in the Rekor transparency log. Verifiers check the signature against the transparency log and a specified identity/issuer, without needing to obtain any keys in advance. + +Key-based signing (using cosign-generated keypairs or KMS-backed keys) is also supported for environments that require it, such as air-gapped clusters or organizations with existing PKI infrastructure. + +## Specification + +### New Commands + +#### `helm sign` + +Signs a packaged chart (`.tgz`) or an OCI chart reference. + +```bash +# Keyless signing (interactive OIDC flow) +helm sign mychart-1.0.0.tgz + +# Keyless signing in CI (ambient OIDC credentials) +helm sign oci://registry.example.com/charts/mychart:1.0.0 + +# Key-based signing +helm sign mychart-1.0.0.tgz --key cosign.key + +# KMS-backed signing +helm sign oci://registry.example.com/charts/mychart:1.0.0 --key awskms:///arn:aws:kms:us-east-1:123456789:key/abcd + +# Sign and attach custom annotations +helm sign oci://registry.example.com/charts/mychart:1.0.0 \ + --annotations "org.example.build-url=https://ci.example.com/build/123" +``` + +**Behavior for OCI charts:** The signature is pushed to the same registry as a Referrer artifact associated with the chart manifest, using cosign's standard OCI media types. + +**Behavior for `.tgz` files:** A Sigstore bundle file (`.cosign.bundle`) is written alongside the `.tgz`. The bundle contains the signature, certificate chain, and Rekor transparency log entry. This file replaces the role of the `.prov` file for new signing operations. + +**Flags:** + +| Flag | Description | +|------|-------------| +| `--key` | Path to a cosign private key, or a KMS URI. If omitted, keyless (OIDC) signing is used. | +| `--key-password` | Password for an encrypted cosign private key. If the key is encrypted and this flag is not provided, the user is prompted interactively. | +| `--identity-token` | An explicit OIDC identity token for keyless signing. If omitted, ambient credentials are detected (e.g., GitHub Actions OIDC, GCP metadata). | +| `--rekor-url` | URL of the Rekor transparency log (default: `https://rekor.sigstore.dev`). | +| `--fulcio-url` | URL of the Fulcio CA (default: `https://fulcio.sigstore.dev`). | +| `--tsa-url` | URL of a trusted timestamp authority. | +| `--annotations` | Key=value pairs to include in the signature payload (repeatable). | +| `--output-bundle` | Explicitly set the output path for the `.cosign.bundle` file (`.tgz` signing only). | +| `--allow-insecure-registry` | Allow signing charts in HTTP (non-TLS) registries. | + +#### `helm verify` + +Verifies the signature of a packaged chart or OCI chart reference. + +```bash +# Keyless verification (requires specifying expected identity) +helm verify oci://registry.example.com/charts/mychart:1.0.0 \ + --certificate-identity "https://github.com/myorg/mychart/.github/workflows/release.yml@refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" + +# Keyless verification with identity regex +helm verify oci://registry.example.com/charts/mychart:1.0.0 \ + --certificate-identity-regexp ".*@myorg\\.com" \ + --certificate-oidc-issuer "https://accounts.google.com" + +# Key-based verification +helm verify mychart-1.0.0.tgz --key cosign.pub + +# Verify and display signature details +helm verify oci://registry.example.com/charts/mychart:1.0.0 \ + --certificate-identity "..." \ + --certificate-oidc-issuer "..." \ + --output json +``` + +**Behavior for OCI charts:** Signatures are discovered via the OCI Referrers API from the same registry. The chart digest is verified against the signature. + +**Behavior for `.tgz` files:** The corresponding `.cosign.bundle` file is read from the same directory (or a path specified by `--bundle`). If a `.cosign.bundle` is not found, Helm falls back to checking for a `.prov` file and uses legacy PGP verification (with a deprecation warning). + +**Flags:** + +| Flag | Description | +|------|-------------| +| `--key` | Path to a cosign public key for key-based verification. | +| `--certificate-identity` | Expected identity in the signing certificate (required for keyless). | +| `--certificate-identity-regexp` | Regex pattern for the expected identity. | +| `--certificate-oidc-issuer` | Expected OIDC issuer (required for keyless). | +| `--certificate-oidc-issuer-regexp` | Regex pattern for the expected OIDC issuer. | +| `--rekor-url` | URL of the Rekor transparency log (default: `https://rekor.sigstore.dev`). | +| `--bundle` | Explicit path to a `.cosign.bundle` file (`.tgz` verification only). | +| `--output` | Output format: `text` (default) or `json`. | +| `--allow-insecure-registry` | Allow verifying charts in HTTP (non-TLS) registries. | + +#### `helm install` / `helm upgrade` Integration + +The `--verify` flag on `helm install` and `helm upgrade` is extended to support cosign verification. + +```bash +# Verify before install using keyless verification +helm install myrelease oci://registry.example.com/charts/mychart:1.0.0 \ + --verify \ + --certificate-identity "https://github.com/myorg/mychart/.github/workflows/release.yml@refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" + +# Verify before install using key-based verification +helm install myrelease oci://registry.example.com/charts/mychart:1.0.0 \ + --verify \ + --key cosign.pub +``` + +When `--verify` is specified and the chart source is an OCI reference, Helm uses cosign verification. When the chart source is a `.tgz` file, Helm checks for a `.cosign.bundle` first and falls back to `.prov` if not found. When the chart source is a classic chart repository, existing PGP `.prov` verification behavior is preserved. + +If `--verify` is specified and no valid signature is found through any mechanism, the command fails with a non-zero exit code. + +### Signature Payload + +For OCI charts, the signature payload is the chart manifest digest, consistent with how cosign signs container images. + +For `.tgz` files, the signature payload is a JSON document containing: + +```json +{ + "critical": { + "type": "helm chart signature", + "chart": { + "name": "mychart", + "version": "1.0.0" + }, + "image": { + "digest": "sha256:abc123..." + } + }, + "optional": { + "annotations": {} + } +} +``` + +The `digest` field contains the SHA-256 digest of the `.tgz` file, ensuring integrity verification. + +### Configuration File + +Users can set default verification policies in `~/.config/helm/sigstore.yaml` or via `$HELM_SIGSTORE_CONFIG`: + +```yaml +# Default verification settings +defaults: + rekor-url: https://rekor.sigstore.dev + fulcio-url: https://fulcio.sigstore.dev + +# Per-registry or per-repository trust policies +policies: + - registry: "registry.example.com/charts/*" + certificate-identity-regexp: ".*@example\\.com" + certificate-oidc-issuer: "https://accounts.google.com" + - registry: "ghcr.io/myorg/*" + certificate-identity: "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" + certificate-oidc-issuer: "https://token.actions.githubusercontent.com" +``` + +When `--verify` is specified without explicit identity/issuer flags, Helm looks up the matching policy from this configuration. This allows organizations to configure trust policies once rather than specifying identity flags on every command invocation. + +### Library / SDK Changes + +The Helm SDK (`pkg/action`) is extended with: + +```go +// SignOption configures chart signing +type SignOption struct { + KeyRef string // Path to cosign key or KMS URI; empty for keyless + IdentityToken string // Explicit OIDC token for keyless signing + RekorURL string // Rekor transparency log URL + FulcioURL string // Fulcio CA URL + TSAUrl string // Timestamp authority URL + Annotations map[string]string +} + +// VerifyOption configures chart verification +type VerifyOption struct { + KeyRef string // Path to cosign public key + CertificateIdentity string // Expected signer identity + CertificateIdentityRegexp string // Regex for signer identity + CertificateOIDCIssuer string // Expected OIDC issuer + CertificateOIDCIssuerRegexp string // Regex for OIDC issuer + RekorURL string // Rekor transparency log URL + BundlePath string // Explicit bundle path for .tgz files +} + +// VerifyResult contains verification output +type VerifyResult struct { + Verified bool + SignerIdentity string + Issuer string + Timestamp time.Time + RekorLogID string + Annotations map[string]string +} +``` + +### Deprecation of PGP-Based Provenance + +The existing PGP `.prov` system is deprecated but not removed in the initial release: + +1. **Phase 1 (initial release):** `helm package --sign` and `helm verify` with PGP continue to work but emit a deprecation warning recommending migration to `helm sign` with cosign. The `--sign` flag on `helm package` is marked as deprecated in help text. +2. **Phase 2 (next major version, e.g., Helm 4):** PGP signing support is removed. `helm package --sign` is removed. `helm verify` only supports cosign. The `.prov` file format is no longer generated. Legacy `.prov` files are ignored with a warning. + +During Phase 1, `helm verify` checks for cosign signatures first (OCI referrers or `.cosign.bundle`) and falls back to `.prov` if no cosign signature is found. + +## Backwards Compatibility + +### No Breaking Changes in Initial Release + +- The existing `helm package --sign` and `helm verify` commands continue to function with PGP keys during the deprecation period. +- The existing `--verify` flag on `helm install`/`helm upgrade` continues to work with `.prov` files. +- Charts without signatures continue to install normally (signing is opt-in). +- The `--keyring` flag on existing commands continues to work. +- No changes to Chart.yaml, values.yaml, or any chart structure. + +### Migration Path + +Chart publishers can adopt cosign signing incrementally: + +1. Start signing with cosign in addition to PGP (both signatures can coexist). +2. Update documentation to point consumers to cosign verification. +3. Drop PGP signing when the deprecation period ends. + +Chart consumers can adopt cosign verification incrementally: + +1. Configure trust policies in `sigstore.yaml`. +2. Start using `--verify` with cosign identity flags. +3. Remove PGP public keys from keyrings when no longer needed. + +### Dependency Impact + +This proposal adds `sigstore/cosign/v2` and its transitive dependencies to Helm's dependency tree. The cosign library is well-maintained and widely used, but it does increase the binary size and dependency surface. The cosign library dependencies are already part of the broader CNCF ecosystem and are actively maintained. + +## Security Implications + +### Improvements Over Current System + +- **Elimination of long-lived keys.** Keyless signing uses short-lived certificates (typically 10-minute validity), reducing the window of exposure if credentials are compromised. +- **Transparency logging.** All signing events are recorded in Rekor, providing an auditable, tamper-evident log. If a signing key is compromised, the transparency log enables detection of unauthorized signatures. +- **Identity-based trust.** Verifiers specify *who* they trust (e.g., a GitHub Actions workflow in a specific repository) rather than managing opaque key material. This is more intuitive and harder to misconfigure. +- **Timestamp verification.** Signatures include trusted timestamps, enabling verification that a signature was created while the signing certificate was valid, even after the certificate expires. + +### Potential Risks + +- **Dependency on public infrastructure.** Keyless signing depends on Fulcio and Rekor being available. If these services experience downtime, keyless signing fails. Mitigation: key-based signing remains available as a fallback, and organizations can run private Sigstore infrastructure. +- **OIDC token exposure.** Keyless signing involves presenting an OIDC token to Fulcio. In CI environments, this token is typically scoped and short-lived. Users should ensure their OIDC tokens are appropriately scoped. +- **Trust in Sigstore root of trust.** Keyless verification trusts the Sigstore root CA (Fulcio) and transparency log (Rekor). Organizations with strict trust requirements can run private instances of these services using the `--rekor-url` and `--fulcio-url` flags. +- **Signature stripping.** An attacker with registry write access could delete signatures. Mitigation: Rekor provides an independent record that a signature existed. Registry access controls should be applied appropriately. +- **Malicious chart with valid signature.** A compromised publisher identity could sign a malicious chart. Mitigation: this is inherent to any signing system. The transparency log provides auditability, and consumers should scope their trust policies narrowly (e.g., specific workflow paths, not entire organizations). + +### Air-Gapped Environments + +For air-gapped environments without access to public Sigstore infrastructure: + +- Key-based signing with cosign-generated keypairs works fully offline. +- Organizations can deploy private Sigstore stacks (Fulcio, Rekor, TUF root) within their network. +- The `--rekor-url`, `--fulcio-url`, and related flags support pointing to internal infrastructure. + +## How to Teach This + +### For Chart Publishers + +**Getting started (keyless, CI):** + +```bash +# In a GitHub Actions workflow: +- name: Sign Helm chart + run: | + helm package mychart/ + helm sign mychart-1.0.0.tgz + helm push mychart-1.0.0.tgz oci://ghcr.io/myorg/charts + # or, sign the chart already in the registry: + helm sign oci://ghcr.io/myorg/charts/mychart:1.0.0 +``` + +No key generation, no key storage, no key rotation. The GitHub Actions OIDC token is used automatically. + +**Getting started (key-based):** + +```bash +# One-time setup +cosign generate-key-pair + +# Sign a chart +helm sign mychart-1.0.0.tgz --key cosign.key + +# Distribute cosign.pub to consumers +``` + +### For Chart Consumers + +**Verifying a chart (keyless):** + +```bash +# Verify a chart from an OCI registry +helm verify oci://ghcr.io/myorg/charts/mychart:1.0.0 \ + --certificate-identity "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" + +# Install with verification +helm install myrelease oci://ghcr.io/myorg/charts/mychart:1.0.0 \ + --verify \ + --certificate-identity "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" \ + --certificate-oidc-issuer "https://token.actions.githubusercontent.com" +``` + +**Setting up trust policies:** + +```bash +# Create a policy file so you don't need flags every time +cat > ~/.config/helm/sigstore.yaml <" ] +created: "2026-05-30" +type: "feature" +status: "draft" +--- + +## Abstract + +This HIP proposes a declarative mechanism for Helm charts to specify cluster capability prerequisites — such as the presence of specific API groups, Custom Resource Definitions (CRDs), or required controllers — that must be satisfied before installation proceeds. A new `prerequisites` field in `Chart.yaml` allows chart authors to declare what cluster capabilities their chart depends on. During `helm install` and `helm upgrade`, Helm validates these prerequisites against the target cluster's actual capabilities (via API discovery) and fails early with a clear, actionable error message when requirements are not met. + +This addresses the common pain point where charts silently deploy broken resources (e.g., Ingress objects without an ingress controller, or custom resources without their CRD installed), leading to confusing post-deployment debugging. By shifting validation left to install-time, users get immediate feedback about what their cluster is missing. + +## Motivation + +### Current Limitations + +Today, Helm charts have no native way to declare what cluster capabilities they depend on. When a chart creates an Ingress resource but the cluster has no ingress controller, or creates a ServiceMonitor but the Prometheus Operator CRD is absent, the result is: + +1. **Silent deployment of broken resources** — `helm install` succeeds, but the application does not function as expected +2. **Delayed failure signals** — users discover problems minutes or hours later when traffic fails to route or monitoring is missing +3. **Opaque error messages** — Kubernetes API errors about missing resources or unrecognized types are cryptic and do not point users toward a solution +4. **Documentation burden** — chart authors resort to lengthy README prerequisites sections that users skip or miss + +### Real-World Impact + +- **Chart consumers** waste significant time debugging failed deployments that could have been caught immediately. A chart depending on `cert-manager` CRDs will partially deploy and fail silently when those CRDs are absent. +- **Chart authors** receive support requests and issues that boil down to "you didn't have X installed." They cannot programmatically enforce their documented prerequisites. +- **Platform teams** managing multi-tenant clusters cannot easily validate that a chart is appropriate for their cluster's capabilities before deploying. +- **CI/CD pipelines** proceed through deployment stages only to discover at runtime that the target cluster lacks a required capability, wasting pipeline time and complicating rollback. + +### Existing Workarounds + +- **README documentation**: Chart authors list prerequisites in documentation, relying on users to read and follow them. This is frequently ignored. +- **Pre-install hooks with `lookup`**: Some charts use hooks that query the cluster, but this is complex, chart-specific, and provides poor UX (hook job logs are hard to surface to the user). +- **`helm template` + external validators**: Tools like `kubeval` or `kubeconform` validate rendered manifests against schemas but cannot verify that controllers or operators are actually running. +- **Wrapper scripts**: Organizations write custom scripts around `helm install` that perform prerequisite checks, fragmenting the deployment workflow. + +### Who Is Affected + +- **Chart consumers** (primary): anyone running `helm install` on a chart with undocumented or missed prerequisites +- **Chart authors** (secondary): those who want to provide a better install experience and reduce support burden +- **Platform operators** (tertiary): those validating chart compatibility with cluster offerings + +## Rationale + +### Why Declarative Prerequisites in Chart.yaml + +Placing prerequisite declarations in `Chart.yaml` makes them: + +- **Discoverable** — tools, registries, and `helm show chart` can surface them without rendering templates +- **Static** — they do not depend on values or template logic, making them predictable and cacheable +- **Enforceable** — Helm itself can validate them at a well-defined point in the install lifecycle (before template rendering) + +This approach mirrors how `kubeVersion` already constrains the Kubernetes version. The proposal extends this pattern to cluster capabilities. + +### Why Not Template-Time Checks with `lookup` + +While `lookup` can query the cluster during rendering, it has significant drawbacks: + +- It requires chart authors to write complex template logic for each prerequisite +- Error messages are custom per chart, inconsistent across the ecosystem +- It fails during `helm template` (no cluster context), preventing offline validation +- It mixes concerns: template logic should focus on generating manifests, not validating the environment + +### Why Focus on Capabilities, Not Resource Sizing + +An earlier formulation of this idea included resource sizing checks (e.g., "at least 3 nodes" or "minimum 16GB RAM available"). This was deliberately excluded because: + +- Resource availability is dynamic and changes between check-time and deploy-time +- Node count and available resources are scheduling concerns better handled by Kubernetes itself (resource requests, pod anti-affinity, topology constraints) +- Including sizing would make the feature scope unbounded and implementation far more complex +- Cluster capability (API availability, CRD presence) is a stable, binary property — either the API exists or it does not + +### How Other Projects Handle This + +- **Ansible**: uses `meta/requirements.yml` to declare collection and role dependencies +- **Terraform**: providers declare required provider versions and features +- **apt/yum**: packages declare dependencies that must be satisfied before installation +- **OLM (Operator Lifecycle Manager)**: operators declare `required` APIs in their ClusterServiceVersion + +The proposed approach aligns with these well-established dependency declaration patterns. + +## Specification + +### Chart.yaml Extension + +A new optional `prerequisites` field is added to `Chart.yaml`: + +```yaml +apiVersion: v2 +name: my-application +version: 1.0.0 +# ... other fields ... + +prerequisites: + capabilities: + - apiGroup: "networking.k8s.io" + version: "v1" + resource: "ingresses" + reason: "This chart creates Ingress resources for HTTP routing" + - apiGroup: "cert-manager.io" + version: "v1" + resource: "certificates" + reason: "TLS certificates are managed by cert-manager" + - apiGroup: "monitoring.coreos.com" + version: "v1" + resource: "servicemonitors" + reason: "Prometheus ServiceMonitor is used for metrics collection" + optional: true +``` + +### Schema + +```yaml +prerequisites: + capabilities: + - apiGroup: string # Required. The API group (e.g., "networking.k8s.io", "" for core) + version: string # Required. The API version (e.g., "v1", "v1beta1") + resource: string # Required. The plural resource name (e.g., "ingresses", "certificates") + reason: string # Optional. Human-readable explanation displayed on failure + optional: bool # Optional. Default: false. If true, a warning is issued instead of an error +``` + +### Validation Behavior + +During `helm install` and `helm upgrade`: + +1. Helm reads the `prerequisites.capabilities` list from the chart metadata +2. For each capability entry, Helm queries the cluster's API discovery endpoint (`/apis` or `/api/v1` for core resources) to check if the specified `apiGroup/version/resource` triple is registered +3. **If a required capability is missing**: Helm fails immediately with a clear error message and does not proceed to template rendering +4. **If an optional capability is missing**: Helm prints a warning and continues + +### Error Output + +``` +$ helm install my-release ./my-chart +Error: INSTALLATION FAILED: cluster prerequisites not met: + - missing required capability: cert-manager.io/v1/certificates + reason: TLS certificates are managed by cert-manager + hint: install cert-manager (https://cert-manager.io/docs/installation/) + - missing required capability: monitoring.coreos.com/v1/servicemonitors + (marked optional - continuing with warning) + +Required capabilities can be viewed with: helm show prerequisites ./my-chart +``` + +### CLI Additions + +**`helm show prerequisites CHART`**: Displays the prerequisite declarations from a chart without installing it. + +``` +$ helm show prerequisites ./my-chart +CAPABILITIES: + networking.k8s.io/v1/ingresses (required) + This chart creates Ingress resources for HTTP routing + cert-manager.io/v1/certificates (required) + TLS certificates are managed by cert-manager + monitoring.coreos.com/v1/servicemonitors (optional) + Prometheus ServiceMonitor is used for metrics collection +``` + +**`--skip-prerequisites`**: A flag on `helm install` and `helm upgrade` that bypasses prerequisite validation. This is an escape hatch for advanced users who know what they are doing (e.g., installing the chart and the prerequisite concurrently). + +``` +$ helm install my-release ./my-chart --skip-prerequisites +WARNING: Skipping prerequisite validation. The chart declares requirements that have not been verified. +``` + +### Behavior Matrix + +| Operation | Prerequisites Checked | Notes | +|-----------|----------------------|-------| +| `helm install` | Yes | Fails before rendering if requirements unmet | +| `helm upgrade` | Yes | Fails before rendering if requirements unmet | +| `helm install --skip-prerequisites` | No | Warning printed, proceeds | +| `helm template` | No | No cluster context available | +| `helm install --dry-run=client` | No | No cluster context available | +| `helm install --dry-run=server` | Yes | Validates against actual cluster | +| `helm show prerequisites` | N/A | Displays declared prerequisites | +| `helm lint` | No | Static check only; validates schema correctness | + +### Edge Cases + +- **CRD installed but controller not running**: The prerequisite check validates API registration, not controller health. This is a deliberate limitation — checking controller health would require chart-specific probes and is out of scope. The `reason` field can note this distinction. +- **Dependency charts providing the capability**: If a chart's `dependencies` include a sub-chart that installs the required CRD, the prerequisite should still be listed (CRDs from dependency charts may not be registered until after the parent chart is installed). Chart authors should use `optional: true` or omit the prerequisite in such cases. +- **Empty `prerequisites` field**: Treated as no prerequisites. Charts without the field behave identically to today. +- **Unknown fields in `prerequisites`**: Ignored with a warning, following Helm's existing forward-compatibility approach for Chart.yaml. + +## Backwards Compatibility + +This proposal is fully backwards compatible: + +- **Additive field**: The `prerequisites` field in `Chart.yaml` is optional. Existing charts without it behave identically to today. +- **Old Helm versions**: Helm versions that do not understand `prerequisites` will silently ignore the field (Helm already ignores unknown Chart.yaml fields). Charts using this feature will still install on older Helm versions — they just will not benefit from the prerequisite validation. +- **No behavior changes**: For charts that do not declare prerequisites, the install/upgrade flow is unchanged. There are no new required flags or configuration. +- **Safe for minor version**: This is purely additive behavior gated behind an opt-in declaration, suitable for a minor Helm version release. + +## Security Implications + +### API Discovery Information Leakage + +The prerequisite check queries the cluster's API discovery endpoints. These endpoints are already accessible to any authenticated user (they are required for `kubectl` to function). No new permissions or API access is introduced. + +### Malicious Charts + +A malicious chart could declare prerequisites to probe what capabilities a cluster has (by observing which prerequisites pass or fail in error messages). However: + +- This information is already available to anyone who can run `helm install` (they can use `kubectl api-resources`) +- The prerequisite check happens before any resources are created, so it does not enable any new attack vectors +- The `--skip-prerequisites` flag gives users full control + +### Denial of Service via Excessive Prerequisites + +A chart with an extremely large `prerequisites` list could cause many API discovery requests. Mitigation: Helm should cap the number of prerequisite entries (recommended limit: 50) and batch discovery requests where possible. + +### No Privilege Escalation + +Prerequisite validation uses only the API discovery endpoint, which requires no elevated permissions beyond what `helm install` already needs. It does not create, modify, or delete any cluster resources. + +## How to Teach This + +### Documentation Additions + +1. **Chart.yaml Reference**: Add `prerequisites` to the Chart.yaml specification page with full schema documentation +2. **Best Practices Guide**: "Declaring Chart Prerequisites" — when and how to use prerequisites effectively +3. **Migration Guide**: How to convert README-documented prerequisites into declarative `prerequisites` entries +4. **Helm Show**: Document `helm show prerequisites` alongside existing `helm show` subcommands + +### Key Example Pattern + +For a chart author adding prerequisites to an existing chart: + +```yaml +# Chart.yaml +apiVersion: v2 +name: my-web-app +version: 2.0.0 +description: A web application with TLS and monitoring + +prerequisites: + capabilities: + - apiGroup: "networking.k8s.io" + version: "v1" + resource: "ingresses" + reason: "Required for HTTP/HTTPS routing to the application" + - apiGroup: "cert-manager.io" + version: "v1" + resource: "certificates" + reason: "Automatic TLS certificate provisioning via cert-manager" + - apiGroup: "monitoring.coreos.com" + version: "v1" + resource: "servicemonitors" + reason: "Prometheus metrics collection (application still works without this)" + optional: true +``` + +### Teaching Approach + +For new Helm users: "Just like `kubeVersion` tells Helm what Kubernetes version your chart needs, `prerequisites` tells Helm what cluster capabilities your chart needs. If something is missing, Helm tells you right away instead of deploying broken resources." + +For experienced users: "If you have a README section listing prerequisites, you can now make those machine-readable. Add them to `prerequisites.capabilities` and Helm will validate them automatically." + +## Reference Implementation + +No implementation exists yet. The implementation will involve: + +1. **Chart.yaml schema extension**: Add `prerequisites` to the chart metadata schema with validation +2. **API discovery integration**: Add a prerequisites checker that queries the cluster's discovery API (`/apis` and `/api/v1`) to verify capability availability +3. **Install/upgrade lifecycle hook**: Insert prerequisite validation after chart loading but before template rendering +4. **CLI additions**: `helm show prerequisites` subcommand and `--skip-prerequisites` flag +5. **Error formatting**: Clear, actionable error messages listing all unmet prerequisites +6. **Lint integration**: Validate prerequisite schema correctness in `helm lint` + +## Rejected Ideas + +- **Resource sizing checks (node count, memory, CPU)**: Resource availability is dynamic and ephemeral. Checking "at least 3 nodes" at install time provides a false sense of safety because nodes can disappear between the check and pod scheduling. Kubernetes already handles resource constraints through requests/limits and scheduling. Including this would make the feature scope unbounded. +- **Controller health checks**: Verifying that a controller is not just registered but actively running and healthy would require chart-specific probe logic, timeouts, and health definitions. The API group being registered is a sufficient proxy for "this capability is intended to be available." Health monitoring is the domain of the platform operator. +- **Values-conditional prerequisites**: Allowing prerequisites to be conditional on values (e.g., "only require cert-manager if `tls.enabled=true`") would require evaluating prerequisites after values merging, complicating the lifecycle. Chart authors can use `optional: true` for capabilities that are only needed in some configurations, and document the relationship. +- **Inline remediation commands**: Including install commands for missing prerequisites (e.g., `install: "helm install cert-manager jetstack/cert-manager"`) was considered but rejected because: install procedures change over time, vary by environment, and could be a security risk if executed automatically. +- **Arbitrary Lua/CEL expressions**: A general-purpose expression language for prerequisites would be extremely powerful but introduces complexity, security concerns (arbitrary code execution), and a learning curve disproportionate to the problem being solved. +- **Namespace-scoped checks**: Checking for resources in specific namespaces (e.g., "cert-manager must be in namespace cert-manager") was rejected because API group registration is cluster-scoped and sufficient. Namespace-level checks would require additional permissions and are fragile. +- **Integration with chart dependencies**: Automatically inferring prerequisites from sub-chart resources was considered but rejected because: sub-charts may install CRDs themselves (making the prerequisite circular), and explicit declaration is clearer and more maintainable. + +## Open Issues + +1. **Exact validation timing**: Should prerequisites be checked before or after chart dependency resolution? If a dependency chart installs the CRD that the parent chart needs, checking before dependency installation would produce a false failure. The current proposal suggests checking after dependencies are installed, but this needs further discussion. +2. **Version constraints on capabilities**: Should chart authors be able to specify minimum versions of an API (e.g., "networking.k8s.io/v1 but not v1beta1 only")? The current schema uses exact version matching. Wildcard or range support could be added later. +3. **Registry integration**: Should chart registries (Artifact Hub, OCI registries) surface prerequisite information in search results and chart pages? This is desirable but out of scope for the initial implementation. +4. **Helm SDK consumers**: How should the prerequisites check be exposed in the Helm SDK for tools like Fleet, ArgoCD, or Flux that use Helm programmatically? They may want to handle prerequisite failures differently than the CLI. +5. **`reason` field localization**: Should the `reason` field support multiple languages or link to external documentation? For now, plain English text is sufficient. + +## References + +- [Helm Chart.yaml specification](https://helm.sh/docs/topics/charts/#the-chartyaml-file) +- [Kubernetes API Discovery](https://kubernetes.io/docs/reference/using-api/api-concepts/#discovery) +- [HIP-0019: Hook Output Display](https://github.com/helm/community/blob/main/hips/hip-0019.md) — related prior art for surfacing pre-install check results +- [Operator Lifecycle Manager (OLM) Dependencies](https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/) +- [Helm kubeVersion constraint](https://helm.sh/docs/topics/charts/#the-kubeversion-field) +- [Artifact Hub](https://artifacthub.io/) +- [Troubleshoot.sh Preflight Checks](https://troubleshoot.sh/docs/preflight/introduction/) diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json b/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json new file mode 100644 index 00000000..e92d1336 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json @@ -0,0 +1 @@ +{"total_tokens": 55117, "duration_ms": 262931, "total_duration_seconds": 262.9} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json new file mode 100644 index 00000000..3a26f9ca --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json @@ -0,0 +1,51 @@ +{ + "eval_name": "vague-idea", + "variant": "without_skill", + "expectations": [ + { + "text": "valid_yaml_preamble", + "passed": true, + "evidence": "Found valid YAML frontmatter" + }, + { + "text": "placeholder_hip_number", + "passed": true, + "evidence": "Found hip: 9999 placeholder" + }, + { + "text": "status_is_draft", + "passed": true, + "evidence": "status is draft" + }, + { + "text": "all_required_sections", + "passed": true, + "evidence": "All 11 required sections present" + }, + { + "text": "abstract_concise", + "passed": true, + "evidence": "Abstract is 129 words (target: 100-300)" + }, + { + "text": "scope_is_narrowed", + "passed": true, + "evidence": "'node' appears 5x, 'storage' appears 6x (lower = more focused)" + }, + { + "text": "title_is_specific", + "passed": true, + "evidence": "Title: 'Cluster Capability Prerequisites for Helm Charts'" + }, + { + "text": "motivation_addresses_real_pain", + "passed": true, + "evidence": "Motivation describes concrete pain points" + }, + { + "text": "specification_is_implementable", + "passed": true, + "evidence": "Specification is 1178 words" + } + ] +} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md new file mode 100644 index 00000000..2dd57a26 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md @@ -0,0 +1,455 @@ +--- +hip: 9999 +title: "Cluster Capability Prerequisites for Helm Charts" +authors: [ "George Jenkins" ] +created: "2026-05-30" +type: "feature" +status: "draft" +--- + +## Abstract + +This HIP proposes a declarative mechanism for Helm charts to specify cluster capability prerequisites -- requirements that the target Kubernetes cluster must satisfy before installation proceeds. Today, charts can declare a minimum Kubernetes version via `kubeVersion` in Chart.yaml, but there is no standard way to express richer requirements such as "an Ingress controller must be present," "the cluster must have a minimum number of nodes," or "a specific CRD must be installed." This proposal introduces a new `prerequisites` section in Chart.yaml that allows chart authors to declare capability, resource, and API requirements. When `helm install` or `helm upgrade` is invoked, Helm evaluates these prerequisites against the live cluster and either proceeds, emits warnings, or fails with actionable error messages, depending on the severity level declared by the chart author. + +## Motivation + +### Current Limitations + +Helm charts frequently assume the existence of cluster capabilities that are not guaranteed: + +**Ingress Controllers:** Many charts create Ingress resources, but Helm does not verify that an Ingress controller is running. The resources are created successfully (the Kubernetes API accepts them), but they have no effect. Users are left debugging why their application is unreachable. + +**Custom Resource Definitions (CRDs):** Charts that depend on CRDs from other operators (e.g., cert-manager `Certificate` resources, Prometheus `ServiceMonitor` resources) fail at install time with obscure errors like `no matches for kind "Certificate" in version "cert-manager.io/v1"`. The user must independently discover, install, and configure the dependency. + +**Node Capacity:** Stateful workloads like databases or distributed systems (e.g., Elasticsearch, Kafka) require minimum node counts or resource availability. Charts deploy successfully but pods remain Pending indefinitely, leaving users to diagnose scheduling failures. + +**Storage Classes:** Charts requesting PersistentVolumeClaims with a specific StorageClass fail silently when that class does not exist. The PVC is created but never bound, and the dependent pods never start. + +**API Versions:** The existing `kubeVersion` field checks the server version string, but does not verify whether specific API groups or versions are actually available (which depends on feature gates, API aggregation, and installed extensions). + +### Who Is Affected + +- **Chart consumers** waste time debugging deployment failures that could have been caught upfront. +- **Chart authors** write extensive documentation listing prerequisites, but users frequently skip or miss these sections. +- **Platform teams** managing multi-tenant clusters receive support requests for issues that are cluster-configuration problems, not chart problems. +- **CI/CD pipelines** that deploy charts fail late in the process, after potentially disruptive partial installations. + +### Existing Workarounds + +Chart authors currently work around these limitations using: + +1. **Documentation:** Listing prerequisites in README files. This is easily missed and not machine-readable. +2. **Pre-install hooks with `lookup()`:** Running Jobs that query the cluster, but this requires RBAC privileges, adds deployment time, and the error reporting is limited (see HIP-0019 for related hook output improvements). +3. **Template-time `lookup()` calls:** Using `{{ if not (lookup "networking.k8s.io/v1" "IngressClass" "" "") }} {{ fail "..." }} {{ end }}` in templates. This works for simple API checks but cannot verify operational capabilities (e.g., "is a controller actually processing these resources?"), does not work with `helm template` or `--dry-run=client`, and scatters prerequisite logic across templates instead of centralizing it. +4. **External tools:** Tools like Troubleshoot.sh preflight checks (referenced in HIP-0019) provide this capability but require separate installation and are not part of the chart itself. + +None of these approaches are standardized, composable, or provide a consistent user experience. + +## Rationale + +### Why Chart.yaml + +Prerequisites are metadata about what a chart requires from the environment. Like `kubeVersion`, `apiVersion`, `dependencies`, and `annotations`, they belong in Chart.yaml because: + +- They are declarative and can be evaluated before template rendering +- They are inspectable without installing the chart (`helm show chart`) +- They compose naturally with chart dependencies (a parent chart's prerequisites are the union of its own and its subcharts' prerequisites) +- They are machine-readable, enabling tooling beyond Helm (e.g., marketplace UIs, GitOps tools, policy engines) + +### Why Not Extend `kubeVersion` + +The `kubeVersion` field uses semver constraint syntax and is limited to matching the Kubernetes server version string. Extending it to cover arbitrary capabilities would be a semantic overload. Prerequisites are a different class of metadata: they describe cluster state, not just the server binary version. + +### Why Not Template-Only + +A template-only approach (using `lookup()` and `fail`) has been available since Helm 3 and adoption for prerequisite checking is minimal. The reasons are: + +- It does not work with `helm template` or `--dry-run=client`, preventing offline validation +- It intermingles prerequisite checks with resource generation logic +- There is no standard structure, so every chart invents its own approach +- It cannot be aggregated across chart dependencies +- It provides no way to distinguish hard failures from soft warnings + +### Severity Levels + +The proposal includes two severity levels: + +- **`required`** (default): Installation fails if the prerequisite is not met. Used for capabilities without which the chart fundamentally cannot function. +- **`recommended`**: Installation proceeds with a prominent warning. Used for capabilities that enhance the chart but are not strictly necessary (e.g., metrics collection via Prometheus). + +A `required`/`recommended` distinction is deliberately simple. More granular severity levels were considered and rejected (see Rejected Ideas) to keep the mental model accessible. + +### Prior Art + +- **Kubernetes itself** uses feature gates and API discovery to manage capability availability. +- **Operator Lifecycle Manager (OLM)** in OpenShift has a `required` section in ClusterServiceVersion manifests for specifying API and CRD dependencies. +- **Troubleshoot.sh** provides preflight check specifications with pass/warn/fail outcomes. +- **APT/RPM package managers** have `Depends`, `Recommends`, and `Suggests` for expressing dependency strength. +- **Terraform** has `required_providers` blocks for declaring infrastructure prerequisites. + +The design draws from OLM's API requirement declarations and Troubleshoot.sh's outcome model while keeping the specification chart-native and lightweight. + +## Specification + +### Chart.yaml Extension + +A new optional `prerequisites` field is added to Chart.yaml. It contains a list of prerequisite declarations, each specifying a type, parameters, and severity. + +```yaml +apiVersion: v2 +name: my-application +version: 1.0.0 +kubeVersion: ">=1.26.0" +prerequisites: + # Require that the networking.k8s.io/v1 IngressClass API exists + # (implies an Ingress controller is installed) + - type: apiVersion + apiVersion: "networking.k8s.io/v1" + kind: IngressClass + severity: required + reason: "This chart creates Ingress resources that require an Ingress controller." + + # Require cert-manager CRDs + - type: apiVersion + apiVersion: "cert-manager.io/v1" + kind: Certificate + severity: required + reason: "TLS certificates are managed via cert-manager. Install cert-manager before deploying this chart." + + # Recommend Prometheus Operator for monitoring + - type: apiVersion + apiVersion: "monitoring.coreos.com/v1" + kind: ServiceMonitor + severity: recommended + reason: "ServiceMonitor resources enable automatic Prometheus scraping. Monitoring will be limited without the Prometheus Operator." + + # Require a minimum number of schedulable nodes + - type: nodeCount + minimum: 3 + severity: required + reason: "This chart deploys a 3-node distributed database that requires at least 3 schedulable nodes." + + # Require a specific StorageClass + - type: storageClass + name: "fast-ssd" + severity: required + reason: "High-performance SSD storage is required for the database volumes." + + # Require minimum allocatable resources across the cluster + - type: clusterResources + cpu: "8" + memory: "32Gi" + severity: recommended + reason: "The full deployment with all replicas requires at least 8 CPU cores and 32Gi of memory across schedulable nodes." +``` + +### Prerequisite Types + +#### `apiVersion` + +Checks whether a specific API group/version (and optionally a specific resource kind) is available via the Kubernetes API discovery mechanism. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `apiVersion` | string | yes | The API group/version to check (e.g., `networking.k8s.io/v1`, `apps/v1`) | +| `kind` | string | no | A specific resource kind within the API group/version | +| `severity` | string | no | `required` (default) or `recommended` | +| `reason` | string | no | Human-readable explanation shown when the check fails | + +**Evaluation:** Uses the Kubernetes discovery API (`/apis` and `/api`) to check whether the specified group/version is registered. If `kind` is specified, further checks that the resource type exists in that group/version. This mirrors the mechanism Helm already uses internally for resource mapping. + +#### `nodeCount` + +Checks the number of schedulable (non-cordoned, Ready) nodes in the cluster. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `minimum` | integer | yes | Minimum number of schedulable nodes | +| `severity` | string | no | `required` (default) or `recommended` | +| `reason` | string | no | Human-readable explanation | + +**Evaluation:** Lists nodes, filters to those with `Ready` condition `True` and `spec.unschedulable != true`, and compares count against `minimum`. + +#### `storageClass` + +Checks whether a specific StorageClass exists in the cluster. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `name` | string | yes | Name of the StorageClass to check | +| `severity` | string | no | `required` (default) or `recommended` | +| `reason` | string | no | Human-readable explanation | + +**Evaluation:** Attempts to get the named StorageClass from the `storage.k8s.io/v1` API. + +#### `clusterResources` + +Checks aggregate allocatable resources across schedulable nodes. + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `cpu` | string | no | Minimum allocatable CPU (Kubernetes quantity format) | +| `memory` | string | no | Minimum allocatable memory (Kubernetes quantity format) | +| `severity` | string | no | `required` (default) or `recommended` | +| `reason` | string | no | Human-readable explanation | + +**Evaluation:** Sums `status.allocatable` across schedulable nodes and compares against declared minimums. At least one of `cpu` or `memory` must be specified. + +**Important caveat:** This check reports total allocatable resources, not available (unallocated) resources. Determining truly available resources would require inspecting all existing pod resource requests across the cluster, which is expensive and requires broad RBAC permissions. The allocatable check establishes whether the cluster is sized appropriately, not whether it currently has spare capacity. + +### Evaluation Behavior + +#### During `helm install` and `helm upgrade` + +1. After chart loading and dependency resolution but before template rendering, Helm evaluates all prerequisites from the chart and its transitive dependencies. +2. Prerequisites are deduplicated: if the same check (identical type and parameters) appears multiple times, the strictest severity wins. +3. Each prerequisite is evaluated against the cluster. +4. Results are categorized: + - **Failed required prerequisites:** Installation is aborted. All failures are reported together (not just the first) so the user can address them in one pass. + - **Failed recommended prerequisites:** Warnings are printed to stderr. Installation proceeds. + - **Passed prerequisites:** Reported at `--debug` verbosity. +5. Error output includes the `reason` text from the chart author, providing actionable guidance. + +Example failure output: + +``` +Error: INSTALLATION FAILED: cluster prerequisites not met + +REQUIRED (installation cannot proceed): + [FAIL] apiVersion networking.k8s.io/v1 IngressClass: API not found + Reason: This chart creates Ingress resources that require an Ingress controller. + [FAIL] storageClass fast-ssd: StorageClass not found + Reason: High-performance SSD storage is required for the database volumes. + +RECOMMENDED (warnings): + [WARN] apiVersion monitoring.coreos.com/v1 ServiceMonitor: API not found + Reason: ServiceMonitor resources enable automatic Prometheus scraping. Monitoring will be limited without the Prometheus Operator. + +2 required prerequisite(s) failed. Use --skip-prerequisites to override. +``` + +#### During `helm template` and `--dry-run=client` + +Prerequisites are not evaluated (no cluster access). A note is printed indicating that prerequisite validation was skipped. The `prerequisites` section can still be inspected via `helm show chart`. + +#### During `--dry-run=server` + +Prerequisites are evaluated against the cluster, matching live install/upgrade behavior. + +### Command-Line Flags + +| Flag | Description | +|------|-------------| +| `--skip-prerequisites` | Skip all prerequisite checks. Installation proceeds regardless of prerequisite failures. | +| `--skip-prerequisites=recommended` | Skip only recommended prerequisite checks. Required prerequisites are still enforced. | + +The `--skip-prerequisites` flag provides an escape hatch for scenarios where the user knows better than the chart (e.g., a custom Ingress controller that does not register IngressClass resources, or a cluster autoscaler that will add nodes on demand). + +### New Command: `helm prerequisites` + +A new subcommand allows evaluating prerequisites without installing: + +```bash +# Check prerequisites for a chart against the current cluster +helm prerequisites show ./my-chart + +# Check prerequisites against a specific cluster context +helm prerequisites show ./my-chart --kube-context production + +# Output in JSON for tooling consumption +helm prerequisites show ./my-chart --output json +``` + +This enables CI/CD pipelines and platform tools to validate prerequisites independently of installation. + +### Subchart and Dependency Handling + +Prerequisites from subcharts and dependencies are aggregated into the parent chart's prerequisite evaluation: + +1. Each dependency's prerequisites are loaded recursively. +2. Prerequisites are evaluated as a flat list after deduplication. +3. If a dependency is conditional (e.g., `condition: redis.enabled`), its prerequisites are only evaluated when the condition is true. Condition evaluation uses the merged values, consistent with how Helm resolves dependency conditions today. +4. Conflicting prerequisites (e.g., parent requires `storageClass: fast-ssd` and subchart requires `storageClass: standard`) are both evaluated independently -- both must pass. + +### Schema Validation + +The `prerequisites` field is validated during `helm lint` and `helm package`: + +- Each entry must have a valid `type` +- Required fields for each type must be present +- `severity` must be `required` or `recommended` (defaults to `required` if omitted) +- Unknown fields generate a warning (for forward compatibility with future prerequisite types) + +## Backwards Compatibility + +This proposal is fully backwards compatible: + +- The `prerequisites` field in Chart.yaml is optional. Existing charts work unchanged. +- Older versions of Helm that do not understand `prerequisites` will ignore the field, as Chart.yaml allows arbitrary additional fields. Charts using prerequisites will still install on older Helm versions, just without the safety checks. +- No existing Chart.yaml fields are modified or removed. +- No changes to template rendering, release storage, or any other existing behavior. +- The `--skip-prerequisites` flag ensures users are never blocked by prerequisites if they choose to override them. + +The `apiVersion: v2` chart format already permits additional top-level keys in Chart.yaml without schema errors, so the addition of `prerequisites` does not require a new chart API version. + +## Security Implications + +### RBAC Requirements + +Prerequisite evaluation requires the Helm client (or its service account) to have read access to cluster-level resources: + +- **API discovery:** Already required by Helm for resource mapping. No additional permissions needed for `apiVersion` checks. +- **Node listing:** Requires `get`/`list` on `nodes` (cluster-scoped). This may not be available in restricted environments where Helm is limited to namespace-scoped operations. +- **StorageClass listing:** Requires `get` on `storageclasses.storage.k8s.io` (cluster-scoped). +- **Resource aggregation:** Requires `list` on `nodes` with access to `status.allocatable`. + +If Helm lacks the permissions to evaluate a prerequisite, the check is treated as a warning (not a failure) with a message indicating that the check could not be performed due to insufficient permissions. This ensures that prerequisite checks do not break existing deployments in restricted RBAC environments. + +### Information Disclosure + +Prerequisite checks only read cluster state; they do not expose any information that is not already available to the Helm user via `kubectl`. The `reason` field is authored by the chart maintainer and does not contain cluster-derived data. + +### Malicious Charts + +A malicious chart author could declare prerequisites designed to: + +- **Fingerprint cluster capabilities:** By observing which prerequisites pass or fail. Mitigation: This information is already available to chart templates via `lookup()` and `.Capabilities`. Prerequisites do not expand the information surface. +- **Cause denial of service:** By declaring an expensive prerequisite check (e.g., `clusterResources` on a very large cluster). Mitigation: All prerequisite types defined in this proposal have bounded evaluation cost. Future prerequisite types should be evaluated for cost before acceptance. + +## How to Teach This + +### Documentation Additions + +1. **Chart.yaml Reference:** Add `prerequisites` to the Chart.yaml specification with field descriptions and type reference. +2. **Chart Developer Guide:** A new "Declaring Prerequisites" section explaining when and how to use each prerequisite type, with guidance on choosing between `required` and `recommended`. +3. **Best Practices Guide:** Add recommendations such as: + - Always include a `reason` with actionable remediation steps + - Prefer `apiVersion` checks over `nodeCount` or `clusterResources` when possible (API checks are cheap and deterministic) + - Use `recommended` for capabilities that enhance but are not essential to the chart + - Do not use prerequisites for conditions that can be handled gracefully by conditional templates + +### User-Facing Messages + +All prerequisite failure messages should follow a consistent format: + +``` +[FAIL|WARN] : + Reason: +``` + +### Example: Adding Prerequisites to an Existing Chart + +A chart author who maintains a web application chart with Ingress support would add: + +```yaml +# Chart.yaml +prerequisites: + - type: apiVersion + apiVersion: "networking.k8s.io/v1" + kind: IngressClass + severity: recommended + reason: >- + An Ingress controller is needed to expose the application externally. + Install an Ingress controller such as ingress-nginx + (https://kubernetes.github.io/ingress-nginx/) or set + ingress.enabled=false to use a different exposure method. +``` + +This is marked `recommended` rather than `required` because the chart can function without Ingress (the user might use a LoadBalancer Service or port-forward instead). + +## Reference Implementation + +A future pull request will: + +1. Extend the Chart.yaml schema to include the `prerequisites` field +2. Implement prerequisite evaluation logic for each type (`apiVersion`, `nodeCount`, `storageClass`, `clusterResources`) +3. Integrate prerequisite evaluation into the `install` and `upgrade` action pipelines +4. Add `--skip-prerequisites` flag to `helm install` and `helm upgrade` +5. Implement the `helm prerequisites show` subcommand +6. Add prerequisite validation to `helm lint` +7. Implement subchart prerequisite aggregation and deduplication +8. Add comprehensive unit and integration tests +9. Update helm.sh documentation + +## Rejected Ideas + +### Arbitrary Scripting / Custom Checks + +Allowing chart authors to define custom prerequisite checks via embedded scripts (bash, Lua, Wasm, etc.) was considered. This was rejected because: + +- It introduces a security risk (executing arbitrary code from a chart before the user has reviewed the rendered manifests) +- It makes prerequisites non-portable and hard to reason about +- It conflicts with Helm's declarative philosophy +- Custom checks can still be implemented via pre-install hooks (see HIP-0019 for improved hook output) + +### Fine-Grained Severity Levels + +A five-level severity scale (critical, required, recommended, optional, informational) was considered. This was rejected in favor of the simpler required/recommended binary because: + +- Two levels cover the dominant use cases (must-have vs. nice-to-have) +- More levels require users to understand subtle distinctions that rarely affect behavior +- Additional levels can be added in a future HIP if demand materializes + +### Resource-Level Prerequisites (Per-Template) + +Attaching prerequisites to individual templates (e.g., "only render this Ingress if IngressClass exists") was considered. This was rejected because: + +- It conflates prerequisite checking with conditional rendering, which templates already handle via `{{ if }}` and `lookup()` +- Chart-level prerequisites are simpler to reason about and aggregate across dependencies +- Template-level conditions are better expressed as values (e.g., `ingress.enabled`) + +### Namespace-Scoped Checks + +Checking for specific resources within a namespace (e.g., "a Secret named `tls-cert` must exist") was considered. This was rejected because: + +- It overlaps with Helm's existing dependency mechanism and `lookup()` in templates +- Namespace-scoped resources are often created by the chart itself or its hooks +- It would significantly expand the prerequisite specification surface + +### Operational Checks (Liveness/Health) + +Checking not just that an API exists but that a controller is operational (e.g., "the Ingress controller is healthy and processing resources") was considered. This was rejected because: + +- There is no standard mechanism to determine whether a controller is "operational" across all implementations +- It would require executing probes or health checks, which is slow and unreliable +- API availability (via discovery) is a good proxy for controller presence in practice + +### Using Annotations Instead of a Top-Level Field + +Placing prerequisites in Chart.yaml `annotations` (similar to HIP-0015 for images) was considered. This was rejected because: + +- Prerequisites have structured, typed data that maps poorly to annotation string values +- Annotations are intended for metadata consumed by external tools, not by Helm itself +- A top-level field enables schema validation and clearer documentation + +### Embedding in values.yaml + +Placing prerequisites in values.yaml was rejected because: + +- Prerequisites are chart metadata, not user-configurable values +- Users should not be able to accidentally disable safety checks by overriding values +- values.yaml is for parameterizing the chart, not declaring its environmental requirements + +## Open Issues + +1. **Extensibility mechanism for custom prerequisite types:** Should this proposal include a plugin or extension point for registering custom prerequisite types, or should new types only be added through future HIPs? A plugin system would be more flexible but adds complexity to the initial implementation. + +2. **Interaction with `helm diff` plugins:** Popular plugins like `helm-diff` run template rendering without installing. Should they also evaluate prerequisites? This may require plugin API changes. + +3. **Dependency ordering of prerequisites:** If chart A lists chart B as a dependency, and chart B has prerequisites, should chart A be able to declare that it satisfies chart B's prerequisites (e.g., chart A installs the CRDs that chart B needs)? This relates to the broader question of install-time ordering (see HIP-0025). + +4. **OCI chart metadata:** When charts are stored as OCI artifacts, should prerequisites be extractable from the OCI manifest without pulling the full chart? This would enable registries and marketplace UIs to display prerequisite information. + +5. **Cluster capability reporting:** Should Helm provide a `helm cluster capabilities` command that reports what prerequisites the current cluster would satisfy? This would be useful for platform teams but expands Helm's scope. + +## References + +- [Helm Chart.yaml Specification](https://helm.sh/docs/topics/charts/#the-chartyaml-file) +- [Kubernetes API Discovery](https://kubernetes.io/docs/reference/using-api/api-concepts/#api-discovery) +- [HIP-0015: Annotation for Images used by Helm Charts](https://github.com/helm/community/blob/main/hips/hip-0015.md) +- [HIP-0019: New annotations for displaying hook output](https://github.com/helm/community/blob/main/hips/hip-0019.md) +- [HIP-0025: Better Support for Resource Creation Sequencing](https://github.com/helm/community/blob/main/hips/hip-0025.md) +- [OLM ClusterServiceVersion Dependencies](https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/) +- [Troubleshoot.sh Preflight Checks](https://troubleshoot.sh/docs/preflight/introduction/) +- [Helm lookup Function](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#using-the-lookup-function) +- [Kubernetes Node Status](https://kubernetes.io/docs/concepts/architecture/nodes/#condition) diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json new file mode 100644 index 00000000..bf227389 --- /dev/null +++ b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json @@ -0,0 +1 @@ +{"total_tokens": 59853, "duration_ms": 169596, "total_duration_seconds": 169.6} \ No newline at end of file diff --git a/skills/hip-author/SKILL.md b/skills/hip-author/SKILL.md new file mode 100644 index 00000000..8ee5c768 --- /dev/null +++ b/skills/hip-author/SKILL.md @@ -0,0 +1,174 @@ +--- +name: hip-author +description: "Guided authoring of Helm Improvement Proposals (HIPs). Use this skill when the user wants to write a HIP, create a proposal, draft a HIP, start a new HIP, or mentions writing a Helm Improvement Proposal. Also trigger when the user says things like 'I have an idea for Helm' or 'I want to propose a change to Helm' or 'new proposal' in the context of this repository." +--- + +# HIP Authoring Guide + +This skill walks users through creating a Helm Improvement Proposal from an initial idea to a complete, submission-ready document. + +The process has two phases: **idea refinement** (getting the concept sharp before writing) and **section-by-section drafting** (producing each section, pausing for the user to edit, then asking clarifying questions before moving on). + +Read `references/hip-template.md` for the canonical template, preamble format, required sections, length recommendations, and approval requirements. Use it as the structural backbone for every HIP you help draft. + +## Phase 1: Idea Refinement + +Before writing anything, help the user sharpen their idea. A focused proposal is far more likely to succeed — the Helm maintainers will reject proposals that are too broad or unfocused. + +### Step 1: Understand the idea + +Ask the user to describe their idea in plain language. Listen for: + +- What problem does this solve? +- Who experiences this problem? (chart authors, cluster operators, end users, maintainers) +- Is this a change to Helm's code (feature), a process/governance change (process), or documentation/guidance (informational)? +- Has this been discussed in [#helm-dev](https://kubernetes.slack.com/messages/C51E88VDG) on Kubernetes Slack or at the [weekly developer call](https://calendar.google.com/calendar/embed?src=s5anaqbm9kda435dnh5r8lj1l8%40group.calendar.google.com&ctz=America%2FLos_Angeles) (Thursdays 9:30am US Pacific)? If not, strongly recommend they vet the idea there first. The `#helm-dev` channel is where active development discussion happens and is the fastest way to get initial feedback on whether an idea is worth writing up as a HIP. Ideas that have been previously rejected or are out of scope for the project will be caught early, saving significant effort. + +### Step 2: Scope gate + +This step is critical. The single most common reason HIPs get rejected or stall is being too broad. Apply these tests: + +1. **Single-concept test**: Can you explain the core of this proposal in one sentence without using "and" to join independent ideas? If not, it needs splitting. +2. **Independence test**: Does the proposal contain sub-features that could ship independently? If removing part of the proposal still leaves something valuable, the removed part should be its own HIP. +3. **MVP test**: What is the absolute simplest version of this that delivers value? Start there. Enhancements can be follow-up HIPs. + +If the idea fails these tests, do NOT proceed. Instead: +- Name the independent pieces explicitly +- Help the user pick which single piece to write up first +- Explain that focused HIPs move faster through review and are more likely to be accepted + +Only proceed when the user has committed to a single, focused proposal. + +### Step 3: Feasibility check + +Ask targeted questions about impact: + +- Are there backwards compatibility concerns? If this changes existing behavior, the bar is significantly higher. +- Does this require changes across multiple Helm projects (helm, helm-www, chartmuseum, etc.), or is it scoped to one? +- Is there prior art in other package managers or CNCF projects? +- What's the rough implementation complexity? (This informs how much detail the Specification needs.) + +### Step 4: Identify the type + +Based on the discussion, confirm the HIP type: + +- **feature** — most common; proposes a new capability or interoperability standard +- **process** — changes to how the project operates (governance, release process, tooling). Requires org maintainer approval rather than project maintainer approval. +- **informational** — guidance or conventions; non-binding + +### Step 5: Summarize and confirm + +Present a crisp 2-3 sentence summary of the proposal back to the user. This summary will become the seed for the Abstract. Ask: "Does this capture your idea? What would you change?" + +Do not proceed to Phase 2 until the user explicitly confirms the idea is well-scoped and accurately summarized. + +## Phase 2: Section-by-Section Drafting + +Work through each section one at a time. For every section: + +1. **Draft** the section content based on everything discussed so far. Use the length guidance from `references/hip-template.md` — aim for the "typical" range, not the maximum. +2. **Present** the draft to the user with the section header, and ask them to edit directly or suggest changes. +3. **Wait** for the user to confirm or revise. If they revise, incorporate their changes. +4. **Clarify** — before moving to the next section, ask 1-2 targeted questions that will inform the upcoming sections. These questions should arise naturally from what was just written. + +### Section order + +#### 1. Preamble + +Generate the YAML frontmatter. Use `hip: 9999` as the placeholder number, today's date for `created`, `status: "draft"`, and the type determined in Phase 1. Ask the user for their preferred author format (with or without email). + +#### 2. Abstract + +Target ~50 words (existing HIPs average 67, median 46). Draw from the summary confirmed in Phase 1. The abstract should be self-contained — a reader should understand what the proposal does without reading further. Avoid implementation details. + +Before moving on, ask: "What existing workarounds do people use today? Understanding the current pain points will strengthen the Motivation section." + +#### 3. Motivation + +Target ~150 words. This section is critical — proposals without sufficient motivation get rejected outright. Use subheadings to organize: + +- **Current Limitations** — what can't users do today? +- **Real-World Impact** — concrete examples, not hypotheticals +- **Who Is Affected** — name specific roles +- **Existing Workarounds** (optional) — what do people do today, and why is it inadequate? + +Before moving on, ask: "What alternative approaches did you consider? Why did you land on this design rather than those alternatives?" + +#### 4. Rationale + +Target ~100 words. Explain the "why" behind key design decisions. Use subheadings for distinct decisions (e.g., "### Why X over Y"). Cover: + +- Why this approach over the alternatives discussed +- How similar problems are handled in other projects if relevant +- Key tradeoffs made and why they're acceptable + +Before moving on, ask: "Can you describe the technical details? What would the API, CLI interface, data structures, or behavior look like?" + +#### 5. Specification + +Target ~350 words (the largest section). For feature HIPs, this needs to be detailed enough for someone else to implement. Include: + +- Data structures, CLI flags, API shapes as appropriate +- Usage examples showing realistic scenarios (use code blocks) +- Behavior matrix if there are multiple modes or contexts +- Edge cases and how they're handled + +For process HIPs, define concrete steps, timelines, roles, and decision criteria rather than code. + +Before moving on, ask: "Does this change break anything for existing users? Could someone on an older version of Helm be affected?" + +#### 6. Backwards Compatibility + +Target ~30 words. Often short — for purely additive changes, a sentence confirming no breakage is sufficient. For breaking changes, be explicit about severity, migration path, and whether a major version is required. + +Before moving on, ask: "Could someone misuse this feature? What's the worst case from a security perspective?" + +#### 7. Security Implications + +Target ~20 words. Can be very brief ("No security implications") for benign features. For features touching data exposure or trust boundaries, cover attack surface, risks, and mitigations. + +Before moving on, ask: "If you were writing docs for this, what's the one example you'd lead with? How would you explain this to a new Helm user?" + +#### 8. How to Teach This + +Target ~50 words. Document: + +- Documentation additions or changes needed +- The key example pattern users should follow +- How this fits into concepts users already know + +#### 9. Reference Implementation + +Target ~15 words. Link to a PR or describe what the implementation will involve. If nothing exists yet, a brief description of what the implementation entails is fine. + +#### 10. Rejected Ideas + +Target ~50 words. Capture alternatives discussed (in Phase 1 and during drafting) with brief explanations of why they were rejected. Use a bulleted list — each entry should be 1-2 sentences. + +#### 11. Open Issues + +Target ~15 words. Any unresolved questions. Fine to submit a draft HIP with open issues — they're resolved during review. + +#### 12. References + +Collect all URLs, specs, and materials referenced throughout the HIP. + +### Optional sections + +Offer these when appropriate: + +- **Scope** — when the proposal is large, explicitly stating what is NOT in scope helps focus review. Offer this after Phase 1 if the user's idea required significant narrowing. +- **Implementation Plan** — for complex multi-phase features, a phased delivery plan with milestones. Offer this if the Specification describes something that would naturally ship incrementally. + +## Phase 3: Assembly and Review + +After all sections are drafted and the user has reviewed each one: + +1. Assemble the complete HIP document in the correct order +2. Write it to `hips/hip-9999.md` (placeholder number) +3. Remind the user to: + - Add the HIP to the listing in `hips/README.md` once a real number is assigned + - Submit as a PR to `helm/community` + - Each commit must be signed off (DCO requirement) + - The HIP needs at least 2 approvals (from project maintainers for feature/informational, from org maintainers for process) +4. Strongly recommend: if the user hasn't already vetted this idea in `#helm-dev` on Kubernetes Slack or at the weekly Thursday developer call, suggest they do so before or alongside submitting the PR. Getting early maintainer feedback prevents lengthy review cycles and reduces the chance of outright rejection. diff --git a/skills/hip-author/references/hip-template.md b/skills/hip-author/references/hip-template.md new file mode 100644 index 00000000..b0a908a7 --- /dev/null +++ b/skills/hip-author/references/hip-template.md @@ -0,0 +1,156 @@ +# HIP Template and Reference + +This file contains the canonical HIP template extracted from hip-0001.md, enriched with guidance and length recommendations derived from analyzing all existing HIPs in the repository. + +## Preamble format + +Every HIP starts with YAML frontmatter. Headers marked with `*` are optional. + +```yaml +--- +hip: 9999 +title: "" +authors: [ "Full Name " ] +created: "YYYY-MM-DD" +type: "feature" +status: "draft" +--- +``` + +### Preamble fields + +| Field | Required | Notes | +|-------|----------|-------| +| `hip` | yes | Use `9999` as placeholder on initial submission (real number assigned at merge) | +| `title` | yes | Short descriptive title | +| `authors` | yes | Format: `"Name "` or `"Name"` (email optional) | +| `created` | yes | RFC 3339 date (YYYY-MM-DD) | +| `type` | yes | `feature`, `informational`, or `process` | +| `status` | yes | Always `draft` on initial submission | +| `helm-version`* | no | Helm version this ships with (add after implementation ships) | +| `requires`* | no | List of HIP numbers this depends on | +| `replaces`* | no | HIP number this obsoletes | +| `superseded-by`* | no | HIP number that supersedes this one | + +### Type definitions + +- **feature**: proposes a new feature or implementation for a Helm project, or an interoperability standard +- **informational**: design guidance or information for the community; non-binding +- **process**: changes to project processes, governance, or tooling; requires org maintainer approval + +## Required sections with length guidance + +Length recommendations are based on analysis of all 26 existing HIPs. The "typical" range covers the 25th-75th percentile. These are guidelines, not rules — a complex feature HIP will naturally be longer than a simple process HIP. + +### Abstract +**Typical: 25-100 words. Target: ~50 words. Max observed: 185 words.** + +A concise, self-contained description of what the proposal does and what problem it solves. A reader should understand the proposal's purpose without reading further. Avoid implementation details — save those for the Specification. + +Most accepted HIPs have abstracts well under 200 words. The hip-0001 guidance says "~200 words" but in practice shorter is better. + +### Motivation +**Typical: 100-200 words. Target: ~150 words. Max observed: 488 words.** + +This is the most critical section for acceptance. Proposals without sufficient motivation are rejected outright. Structure around: + +- **Current limitations** — what can't users do today, or what is painful? +- **Real-world impact** — concrete examples, not hypotheticals. Name the roles affected (chart authors, cluster operators, platform teams, CI/CD pipelines). +- **Existing workarounds** — what do people do today, and why is it inadequate? + +Subheadings work well here (e.g., "### Current Limitations", "### Who Is Affected", "### Real-World Impact"). Most strong HIPs use them. + +### Rationale +**Typical: 50-150 words. Target: ~100 words. Max observed: 4632 words (outlier).** + +Why this design, not just what. Cover: + +- Why this approach over alternatives +- How similar problems are handled in other projects (if relevant) +- Key tradeoffs and why they're acceptable +- Naming decisions (if the proposal introduces new concepts or API surface) + +Use subheadings to separate distinct design decisions (e.g., "### Why X over Y", "### Key Tradeoffs"). + +### Specification +**Typical: 230-680 words. Target: ~350 words. Max observed: 1563 words.** + +The largest section in most HIPs. For feature HIPs, this must be detailed enough for someone else to implement. Include: + +- Data structures, Go types, CLI flags, API shapes +- Usage examples (CLI invocations, YAML snippets, template examples) +- Behavior matrix if there are multiple modes or contexts (see hip-0029 for a good example) +- Edge cases and how they're handled + +For process HIPs, define concrete steps, timelines, roles, and decision criteria rather than code. + +### Backwards compatibility +**Typical: 15-90 words. Target: ~30 words. Max observed: 177 words.** + +Often short. For purely additive changes, a sentence confirming no breakage is sufficient. For breaking changes, be explicit about: + +- What breaks and severity +- Migration path +- Whether this requires a major version bump (Helm follows SemVer) + +### Security implications +**Typical: 1-40 words. Target: ~20 words. Max observed: 532 words.** + +Often very short for benign features ("No security implications"). For features that touch data exposure, authentication, or trust boundaries, cover: + +- Attack surface added +- Data exposure risks +- How a malicious chart or user could abuse the feature +- Mitigations built into the design + +### How to teach this +**Typical: 25-70 words. Target: ~50 words. Max observed: 569 words.** + +What documentation needs to change and what key patterns users should learn: + +- Documentation additions or modifications needed +- The one example you'd lead with when explaining the feature +- How it fits into concepts users already know + +### Reference implementation +**Typical: 5-20 words. Target: ~15 words. Max observed: 133 words.** + +Usually very short. Link to a PR or describe what the implementation will involve. The implementation must be complete before the HIP can reach "final" status, but it does not need to exist when the HIP is submitted as a draft. + +### Rejected ideas +**Typical: 10-100 words. Target: ~50 words. Max observed: 1171 words.** + +Ideas discussed and discarded, with brief explanations of why. Prevents reviewers from re-proposing the same alternatives. Use a bulleted list for multiple rejected ideas — each entry should be 1-2 sentences. + +### Open issues +**Typical: 1-50 words. Target: ~15 words. Max observed: 177 words.** + +Unresolved questions. Fine to submit a draft HIP with open issues — they're resolved during review. Can also be empty if all questions are settled. + +### References +**Typical: 10-40 words. Target: ~20 words. Max observed: 420 words.** + +URLs, specs, and materials referenced throughout the HIP. Use markdown link format. + +## Optional sections + +These sections appear in some existing HIPs and may be useful depending on the proposal: + +- **Scope** (hip-0026) — when a feature HIP is large, explicitly defining what is and isn't in scope helps focus review +- **Implementation Plan** (hip-0026) — for complex features, a phased delivery plan with milestones +- **Prior raised issues** (hip-0025) — links to related GitHub issues or mailing list threads that preceded the HIP + +## Auxiliary files + +Diagrams or supporting files use the naming convention: `proposal-XXX-YY.ext` (e.g., `proposal-029-01.png`), where XXX is the HIP number and YY is a serial number starting at 01. + +## Approval requirements + +- Feature and informational HIPs: at least 2 approvals from project maintainers +- Process HIPs: at least 2 approvals from Helm org maintainers + +## Status lifecycle + +`draft` -> `accepted` -> `final` (after reference implementation is complete) + +Other statuses: `provisional` (accepted but needs more feedback), `deferred` (paused), `rejected`, `superseded` From 5545c862c7d62da038513e44b17b269ac769fd53 Mon Sep 17 00:00:00 2001 From: George Jenkins Date: Sat, 30 May 2026 16:20:34 -0700 Subject: [PATCH 2/2] retest Signed-off-by: George Jenkins --- .../skills}/hip-author/SKILL.md | 0 .../hip-author/references/hip-template.md | 0 skills/hip-author-workspace/evals/evals.json | 26 - .../feature-hip/eval_metadata.json | 47 -- .../feature-hip/with_skill/grading.json | 46 -- .../with_skill/outputs/hip-9999.md | 344 ------------- .../feature-hip/with_skill/timing.json | 1 - .../feature-hip/without_skill/grading.json | 46 -- .../without_skill/outputs/hip-9999.md | 470 ------------------ .../feature-hip/without_skill/timing.json | 1 - .../process-hip/eval_metadata.json | 47 -- .../process-hip/with_skill/grading.json | 51 -- .../with_skill/outputs/hip-9999.md | 242 --------- .../process-hip/with_skill/timing.json | 1 - .../process-hip/without_skill/grading.json | 51 -- .../without_skill/outputs/hip-9999.md | 351 ------------- .../process-hip/without_skill/timing.json | 1 - .../iteration-1/vague-idea/eval_metadata.json | 47 -- .../vague-idea/with_skill/grading.json | 51 -- .../vague-idea/with_skill/outputs/hip-9999.md | 303 ----------- .../vague-idea/with_skill/timing.json | 1 - .../vague-idea/without_skill/grading.json | 51 -- .../without_skill/outputs/hip-9999.md | 455 ----------------- .../vague-idea/without_skill/timing.json | 1 - 24 files changed, 2634 deletions(-) rename {skills => .agents/skills}/hip-author/SKILL.md (100%) rename {skills => .agents/skills}/hip-author/references/hip-template.md (100%) delete mode 100644 skills/hip-author-workspace/evals/evals.json delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/feature-hip/without_skill/timing.json delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/eval_metadata.json delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/with_skill/timing.json delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/process-hip/without_skill/timing.json delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/eval_metadata.json delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md delete mode 100644 skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json diff --git a/skills/hip-author/SKILL.md b/.agents/skills/hip-author/SKILL.md similarity index 100% rename from skills/hip-author/SKILL.md rename to .agents/skills/hip-author/SKILL.md diff --git a/skills/hip-author/references/hip-template.md b/.agents/skills/hip-author/references/hip-template.md similarity index 100% rename from skills/hip-author/references/hip-template.md rename to .agents/skills/hip-author/references/hip-template.md diff --git a/skills/hip-author-workspace/evals/evals.json b/skills/hip-author-workspace/evals/evals.json deleted file mode 100644 index f579a439..00000000 --- a/skills/hip-author-workspace/evals/evals.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "skill_name": "hip-author", - "evals": [ - { - "id": 0, - "name": "feature-hip", - "prompt": "I want to write a HIP for adding native support for chart signing using Sigstore/cosign instead of the current PGP-based provenance system. The current .prov file approach is clunky and almost nobody uses it because PGP key management is painful. Cosign is already the standard in the container ecosystem and it would make chart verification way more accessible.", - "expected_output": "A well-structured HIP document with all required sections, proper YAML preamble with hip: 9999, type: feature, status: draft. Should address backwards compatibility with existing .prov files.", - "files": [] - }, - { - "id": 1, - "name": "process-hip", - "prompt": "I think we should create a formal process for how Helm handles security embargoes and coordinated disclosure with downstream distributors. Right now the SECURITY.md covers reporting but there's no documented process for how we coordinate with distro maintainers who package Helm before a CVE goes public.", - "expected_output": "A well-structured HIP document with type: process, addressing the coordination gap in security disclosure. Should reference existing SECURITY.md and governance docs.", - "files": [] - }, - { - "id": 2, - "name": "vague-idea", - "prompt": "I have a half-baked idea - what if Helm charts could somehow declare their resource requirements or dependencies on cluster capabilities? Like, a chart could say 'I need an ingress controller' or 'I need at least 3 nodes' and helm install would check that before deploying. I'm not sure if this is even feasible or if it's too broad.", - "expected_output": "Should help refine the vague idea into something concrete before producing any HIP text. Should probe scope, suggest narrowing, and only proceed to drafting after the idea is focused.", - "files": [] - } - ] -} diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json b/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json deleted file mode 100644 index 587ff20e..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/eval_metadata.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "eval_id": 0, - "eval_name": "feature-hip", - "prompt": "I want to write a HIP for adding native support for chart signing using Sigstore/cosign instead of the current PGP-based provenance system. The current .prov file approach is clunky and almost nobody uses it because PGP key management is painful. Cosign is already the standard in the container ecosystem and it would make chart verification way more accessible.", - "assertions": [ - { - "name": "valid_yaml_preamble", - "description": "HIP starts with valid YAML frontmatter containing all required fields (hip, title, authors, created, type, status)", - "type": "structural" - }, - { - "name": "placeholder_hip_number", - "description": "Uses hip: 9999 (or quoted '9999') as placeholder, not an invented number", - "type": "structural" - }, - { - "name": "type_is_feature", - "description": "type field is set to 'feature'", - "type": "structural" - }, - { - "name": "status_is_draft", - "description": "status field is set to 'draft'", - "type": "structural" - }, - { - "name": "all_required_sections", - "description": "Contains all required sections: Abstract, Motivation, Rationale, Specification, Backwards compatibility, Security implications, How to teach this, Reference implementation, Rejected ideas, Open issues, References", - "type": "structural" - }, - { - "name": "abstract_concise", - "description": "Abstract is roughly 100-300 words (not a full page, not a single sentence)", - "type": "quality" - }, - { - "name": "backwards_compat_addresses_prov", - "description": "Backwards compatibility section explicitly addresses migration from existing .prov/PGP system", - "type": "content" - }, - { - "name": "specification_has_details", - "description": "Specification section contains concrete technical details (CLI flags, file formats, or workflow descriptions), not just hand-waving", - "type": "content" - } - ] -} diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json deleted file mode 100644 index 263c24ea..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/grading.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "eval_name": "feature-hip", - "variant": "with_skill", - "expectations": [ - { - "text": "valid_yaml_preamble", - "passed": true, - "evidence": "Found valid YAML frontmatter" - }, - { - "text": "placeholder_hip_number", - "passed": true, - "evidence": "Found hip: 9999 placeholder" - }, - { - "text": "status_is_draft", - "passed": true, - "evidence": "status is draft" - }, - { - "text": "all_required_sections", - "passed": true, - "evidence": "All 11 required sections present" - }, - { - "text": "abstract_concise", - "passed": true, - "evidence": "Abstract is 145 words (target: 100-300)" - }, - { - "text": "type_is_feature", - "passed": true, - "evidence": "type is feature" - }, - { - "text": "backwards_compat_addresses_prov", - "passed": true, - "evidence": "Backwards compat section references .prov/PGP" - }, - { - "text": "specification_has_details", - "passed": true, - "evidence": "Specification is 733 words, has code examples" - } - ] -} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md deleted file mode 100644 index b296ab72..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/outputs/hip-9999.md +++ /dev/null @@ -1,344 +0,0 @@ ---- -hip: 9999 -title: "Native Chart Signing with Sigstore/Cosign" -authors: ["User "] -created: "2026-05-30" -type: "feature" -status: "draft" ---- - -## Abstract - -This HIP proposes replacing Helm's current PGP-based chart provenance system (`.prov` files) with native support for Sigstore/cosign signing and verification. The existing provenance mechanism, introduced in Helm 2, requires chart publishers to manage PGP keys and consumers to obtain and trust those keys manually. This friction has led to near-zero adoption in practice, leaving the vast majority of Helm charts deployed without any signature verification. - -Sigstore's cosign has become the de facto signing standard in the container ecosystem, offering keyless signing via OIDC identity, transparency log integration through Rekor, and a dramatically simpler user experience. This proposal adds `helm sign` and `helm verify` subcommands backed by cosign, stores signatures as OCI artifacts alongside charts in OCI registries, and introduces a `cosign` verification mode for `helm install` and `helm upgrade`. The existing PGP-based `.prov` system remains available but is deprecated in favor of the new approach. - -## Motivation - -### The PGP Provenance Problem - -Helm has supported chart provenance since Helm 2 through `.prov` files containing PGP signatures. Despite existing for years, this system sees almost no real-world usage. The reasons are well-documented: - -**Key management burden:** Chart publishers must generate, secure, rotate, and distribute PGP keys. Consumers must discover, import, and decide to trust those keys. There is no standard keyserver or trust model for the Helm ecosystem, so every publisher invents their own distribution mechanism (README instructions, website downloads, out-of-band communication). - -**Tooling friction:** The `helm package --sign` workflow requires a local PGP keyring. CI/CD pipelines must be configured with PGP secret keys, which creates secret management overhead. The `helm verify` command requires the public key to be pre-imported, which means consumers must perform manual setup before verification can occur. - -**Ecosystem disconnect:** The container ecosystem has broadly adopted Sigstore/cosign for image signing. Organizations that sign their container images with cosign must use an entirely separate signing infrastructure for their Helm charts. This duplication is wasteful and confusing. - -**No transparency or auditability:** PGP signatures provide no public transparency log. There is no way to audit when a chart was signed, by whom, or whether a key has been compromised without the publisher explicitly communicating revocation. - -### Who Is Affected - -- **Chart publishers** (e.g., Bitnami, major open-source projects, enterprise platform teams) who want to provide verifiable charts but find PGP too burdensome to set up and maintain. -- **Cluster operators and security teams** who want to enforce chart verification policies but cannot because the charts they consume are unsigned. -- **Enterprise compliance teams** who need audit trails for software supply chain integrity and cannot get them from the current system. -- **CI/CD pipeline authors** who must integrate signing into automated workflows and find PGP key management in pipelines painful. - -### The Sigstore Opportunity - -Sigstore has achieved broad adoption in the cloud-native ecosystem. Cosign is used to sign container images across major registries, and tools like Kyverno and OPA Gatekeeper can enforce cosign signature policies. By aligning Helm chart signing with the same infrastructure, chart verification becomes a natural extension of existing supply chain security practices rather than a separate, parallel system. - -## Rationale - -### Why Sigstore/Cosign Over Other Approaches - -**Keyless signing via OIDC:** Cosign's keyless mode lets publishers sign charts using their existing identity (GitHub Actions OIDC, Google Cloud identity, etc.) without managing long-lived signing keys. This eliminates the single biggest barrier to adoption. A chart published from a GitHub Actions workflow can be signed automatically with zero key management. - -**Transparency log (Rekor):** Every signature is recorded in an immutable, publicly auditable transparency log. This provides the auditability that PGP signatures lack and enables detection of compromised signing identities. - -**OCI-native storage:** Cosign stores signatures as OCI artifacts alongside the signed content. Since Helm 3.8+ supports OCI registries as a first-class chart storage mechanism, cosign signatures fit naturally into the same registry infrastructure. No separate `.prov` file hosting is needed. - -**Ecosystem alignment:** kubectl, Kyverno, OPA Gatekeeper, Tekton, and other CNCF projects already integrate with Sigstore. Using the same signing infrastructure for Helm charts means organizations can enforce unified supply chain policies across container images and Helm charts. - -### How Other Projects Handle This - -- **Container images:** Cosign is the standard. Registries like Docker Hub, GitHub Container Registry, and Amazon ECR support cosign signatures as OCI artifacts. -- **Kubernetes manifests:** The Kubernetes project signs release artifacts with cosign. -- **Linux packages:** Sigstore is being adopted for npm (via npmjs provenance), Python (via PEP 740), and other package ecosystems. - -Helm is an outlier in the CNCF ecosystem by still relying exclusively on PGP for provenance. - -### Key Tradeoffs - -- **Dependency on Sigstore infrastructure:** Keyless signing requires access to Sigstore's Fulcio CA and Rekor transparency log (or self-hosted equivalents). This is acceptable because Sigstore infrastructure is operated by the Linux Foundation and has strong availability commitments, and organizations can run private instances. -- **Two signing systems during transition:** Maintaining both PGP and cosign signing adds complexity, but a clean break would strand the small number of existing PGP provenance users. Deprecation with a clear timeline is the pragmatic path. -- **OCI registry requirement for signatures:** Cosign signatures stored as OCI artifacts require an OCI-compatible registry. Charts distributed via HTTP repositories cannot use this signature storage mechanism, though they can use cosign with key-based signing and detached signatures. - -## Specification - -### New CLI Commands - -#### `helm sign` - -Signs a packaged chart (`.tgz`) using cosign. - -```bash -# Keyless signing (uses OIDC identity, records in Rekor) -helm sign mychart-1.0.0.tgz - -# Key-based signing -helm sign mychart-1.0.0.tgz --key cosign.key - -# Sign and push signature to OCI registry -helm sign mychart-1.0.0.tgz --push oci://registry.example.com/charts - -# Sign with custom Rekor and Fulcio endpoints (private Sigstore) -helm sign mychart-1.0.0.tgz \ - --rekor-url https://rekor.internal.example.com \ - --fulcio-url https://fulcio.internal.example.com -``` - -**Flags:** - -| Flag | Default | Description | -|------|---------|-------------| -| `--key` | (none) | Path to cosign private key. If omitted, keyless signing is used. | -| `--push` | (none) | OCI registry reference to push signature to. | -| `--rekor-url` | `https://rekor.sigstore.dev` | Rekor transparency log URL. | -| `--fulcio-url` | `https://fulcio.sigstore.dev` | Fulcio CA URL for keyless signing. | -| `--output` | (none) | Write detached signature to file instead of pushing to registry. | -| `--tlog-upload` | `true` | Upload signature to transparency log. Set to `false` for air-gapped environments using key-based signing. | - -#### `helm verify` - -Verifies a chart's cosign signature. - -```bash -# Verify using keyless identity (checks Rekor + Fulcio certificate) -helm verify mychart-1.0.0.tgz \ - --certificate-identity user@example.com \ - --certificate-oidc-issuer https://accounts.google.com - -# Verify using a public key -helm verify mychart-1.0.0.tgz --key cosign.pub - -# Verify a chart in an OCI registry (fetches signature from registry) -helm verify oci://registry.example.com/charts/mychart --version 1.0.0 \ - --certificate-identity-regexp '.*@example\.com' \ - --certificate-oidc-issuer https://accounts.google.com - -# Verify with a detached signature file -helm verify mychart-1.0.0.tgz --signature mychart-1.0.0.tgz.sig --key cosign.pub -``` - -**Flags:** - -| Flag | Default | Description | -|------|---------|-------------| -| `--key` | (none) | Path to cosign public key for key-based verification. | -| `--certificate-identity` | (none) | Expected signer identity for keyless verification (exact match). | -| `--certificate-identity-regexp` | (none) | Regex pattern for signer identity. | -| `--certificate-oidc-issuer` | (none) | Expected OIDC issuer for keyless verification. | -| `--certificate-oidc-issuer-regexp` | (none) | Regex pattern for OIDC issuer. | -| `--signature` | (none) | Path to detached signature file. | -| `--rekor-url` | `https://rekor.sigstore.dev` | Rekor URL for transparency log verification. | - -### Verification on Install/Upgrade - -The `helm install` and `helm upgrade` commands gain a `--verify-cosign` flag: - -```bash -# Verify cosign signature before installing -helm install myrelease oci://registry.example.com/charts/mychart \ - --version 1.0.0 \ - --verify-cosign \ - --certificate-identity-regexp '.*@bitnami\.com' \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com - -# Verify with public key -helm install myrelease oci://registry.example.com/charts/mychart \ - --version 1.0.0 \ - --verify-cosign \ - --key cosign.pub -``` - -When `--verify-cosign` is specified, the chart is not installed unless signature verification succeeds. This is distinct from the existing `--verify` flag, which uses PGP provenance. - -### Signature Storage - -For charts in OCI registries, cosign signatures are stored as OCI artifacts using cosign's standard tagging convention (`sha256-.sig`). This is the same mechanism used for container image signatures and requires no custom infrastructure. - -For charts distributed outside of OCI registries (e.g., HTTP chart repositories), signatures can be stored as detached `.cosign.sig` files alongside the chart `.tgz` in the repository index, or verified against the Rekor transparency log by digest. - -### Data Structures - -The chart repository `index.yaml` gains an optional `cosignSignature` field: - -```yaml -entries: - mychart: - - version: 1.0.0 - digest: sha256:abc123... - urls: - - https://example.com/charts/mychart-1.0.0.tgz - cosignSignature: - type: "detached" - url: "https://example.com/charts/mychart-1.0.0.tgz.cosign.sig" -``` - -For OCI registries, no index changes are needed since cosign's standard OCI artifact discovery mechanism is used. - -### Integration with `helm package` - -A convenience flag is added to `helm package`: - -```bash -# Package and sign in one step -helm package mychart/ --cosign-sign -helm package mychart/ --cosign-sign --cosign-key cosign.key -``` - -### Deprecation of PGP Provenance - -The existing PGP-based `--sign`, `--verify`, and `--keyring` flags on `helm package`, `helm verify`, and `helm install` are deprecated but not removed. They will emit deprecation warnings directing users to the cosign-based equivalents. A future major version of Helm may remove PGP provenance support entirely. - -### Edge Cases - -- **Air-gapped environments:** Key-based signing with `--tlog-upload=false` supports environments without internet access to Sigstore infrastructure. Verification uses the public key directly without Rekor. -- **Multiple signatures:** A chart can have multiple cosign signatures (e.g., signed by both the chart author and an enterprise security review). `helm verify` succeeds if any provided identity/key matches. -- **Chart dependencies:** `helm dependency update` does not verify dependency signatures. Signature verification applies to the final packaged chart. A future HIP could address recursive dependency verification. -- **Helm plugins:** The signing and verification logic is implemented in Helm core, not as a plugin, to ensure consistent behavior and avoid the bootstrapping problem of needing to verify a plugin before using it. - -## Backwards Compatibility - -This proposal is fully backwards compatible. All changes are additive: - -- **New commands:** `helm sign` and `helm verify` (with cosign) are new. The existing `helm verify` command for PGP provenance is preserved under `helm verify --legacy-pgp` (or simply continues to work when a `--keyring` is specified, since the flag combination is unambiguous). -- **New flags:** `--verify-cosign` on `helm install` / `helm upgrade` is new and opt-in. The existing `--verify` flag for PGP is unchanged. -- **Index format:** The `cosignSignature` field in `index.yaml` is optional. Older Helm clients ignore unknown fields. -- **OCI registries:** Cosign signatures as OCI artifacts do not interfere with chart storage or retrieval. Older Helm clients that do not understand cosign simply skip verification. - -No existing workflow breaks. Users who currently use PGP provenance (a very small number) can continue to do so. The deprecation warning is informational and does not change behavior. - -This feature is additive and appropriate for a minor version release. - -## Security Implications - -### Improvements Over Current System - -- **Transparency log:** Rekor provides a public, append-only record of every signing event. If a signing key or identity is compromised, the transparency log enables detection and forensic analysis. -- **Short-lived certificates:** Keyless signing uses short-lived certificates (typically 10-minute validity) rather than long-lived PGP keys, reducing the window of exposure if credentials are compromised. -- **Identity-based trust:** Instead of trusting opaque PGP key IDs, consumers trust identifiable entities (email addresses, CI/CD pipeline identities) bound to OIDC issuers, making trust decisions more intuitive. - -### Attack Surface Considerations - -- **Sigstore infrastructure dependency:** Keyless signing depends on Fulcio and Rekor availability. If these services are unavailable, keyless signing fails. Mitigation: support key-based signing as a fallback, and support private Sigstore deployments. -- **OIDC identity compromise:** If an attacker compromises the OIDC identity used for signing (e.g., a GitHub Actions workflow token), they could sign malicious charts. Mitigation: the Rekor transparency log records all signing events, enabling detection. Organizations should monitor Rekor for unexpected signing events on their identities. -- **Signature stripping:** An attacker with registry write access could remove cosign signatures. Mitigation: `--verify-cosign` on install causes a hard failure if no valid signature is found, preventing installation of unsigned charts. Registry access controls remain the primary defense. -- **Cosign library vulnerabilities:** Embedding cosign's verification logic in Helm adds cosign's dependency tree to Helm's attack surface. Mitigation: use cosign as a well-maintained Go library with active security response, and track upstream releases. - -### Misuse Scenarios - -- A malicious chart author could sign a chart with a legitimate-looking but unrelated identity. Users must verify the `--certificate-identity` matches the expected publisher, not just that "a signature exists." -- Policy enforcement tools (Kyverno, OPA) should be used in production to codify trusted identities rather than relying on manual `--verify-cosign` invocations. - -## How to Teach This - -### Documentation Additions - -1. **Chart Signing Guide:** A new top-level documentation page covering both keyless and key-based signing workflows, replacing the current provenance documentation as the recommended approach. -2. **Supply Chain Security Guide:** A conceptual guide explaining how cosign chart signing fits into a broader supply chain security strategy alongside image signing, SBOM generation, and policy enforcement. -3. **Migration Guide:** Step-by-step instructions for chart publishers currently using PGP provenance to switch to cosign signing. -4. **CI/CD Examples:** Ready-to-use workflow examples for GitHub Actions, GitLab CI, and other popular CI systems showing how to sign charts in automated pipelines. - -### Key Example Pattern - -The simplest and most common pattern for a chart publisher using GitHub Actions: - -```yaml -# .github/workflows/release.yml -- name: Package and sign chart - run: | - helm package mychart/ - helm sign mychart-*.tgz --push oci://ghcr.io/${{ github.repository }} -``` - -For a consumer: - -```bash -helm install myrelease oci://ghcr.io/org/charts/mychart \ - --version 1.0.0 \ - --verify-cosign \ - --certificate-identity-regexp '.*@myorg\.com' \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com -``` - -### How This Fits into Existing Helm Concepts - -Signing and verification are presented as an optional but recommended step in the chart lifecycle: author, package, **sign**, push, **verify**, install. This mirrors the existing provenance concept but with dramatically lower friction. The `helm sign` / `helm verify` commands are direct analogs of the existing PGP provenance workflow, so users familiar with the old system can map concepts directly. - -## Reference Implementation - -No reference implementation exists yet. The implementation will involve: - -1. Adding the `cosign` Go library (`github.com/sigstore/cosign/v2`) as a dependency to the Helm project. -2. Implementing `helm sign` and `helm verify` subcommands in `cmd/helm/`. -3. Adding `--verify-cosign` and related flags to `helm install` and `helm upgrade`. -4. Adding the `--cosign-sign` convenience flag to `helm package`. -5. Extending the OCI registry client to discover and store cosign signatures as OCI artifacts. -6. Adding the optional `cosignSignature` field to the repository index parser. -7. Adding deprecation warnings to the existing PGP provenance flags. -8. Comprehensive tests covering keyless signing, key-based signing, verification modes, air-gapped scenarios, and error handling. - -A proof-of-concept branch will be linked here once development begins. - -## Rejected Ideas - -### Cosign as a Helm Plugin - -Implementing signing as an external plugin (e.g., `helm-cosign`) was considered. This was rejected because: -- Plugins must themselves be trusted, creating a bootstrapping problem. -- Plugin installation is an extra step that reduces adoption. -- Core integration ensures consistent behavior across all Helm installations. -- The Helm project should own its supply chain security story. - -### Notation (Microsoft) Instead of Cosign - -Notation is another Sigstore-adjacent signing tool focused on the OCI ecosystem. It was rejected in favor of cosign because: -- Cosign has significantly broader adoption in the Kubernetes/CNCF ecosystem. -- Cosign's keyless signing mode is more mature. -- Most organizations already use cosign for container image signing. -- Supporting both would add complexity without proportional benefit. Notation support could be added in a future HIP if demand warrants it. - -### Requiring Cosign for All Charts - -Making chart signing mandatory was rejected because: -- It would break the existing ecosystem where nearly all charts are unsigned. -- Chart repositories and registries would need universal signing support. -- Development and testing workflows should not require signing infrastructure. -- Signing should be encouraged through tooling and documentation, not mandated. - -### Removing PGP Provenance Immediately - -A clean break from PGP was considered. This was rejected because: -- Some users may have invested in PGP provenance workflows. -- A deprecation period gives the community time to migrate. -- Both systems can coexist without technical conflict. - -### Using In-Toto Attestations Instead of Raw Signatures - -In-toto attestations provide richer metadata than raw signatures (e.g., build provenance, SBOM linkage). While valuable, this was rejected as the initial scope because: -- Raw signatures solve the immediate adoption problem with minimal complexity. -- In-toto attestation support can be layered on top in a future HIP. -- Cosign supports both raw signatures and attestations, so the foundation supports future extension. - -## Open Issues - -1. **Flag naming for legacy PGP:** Should the existing `--verify` flag be renamed to `--verify-pgp` or should it remain as-is with `--verify-cosign` being the new addition? The current proposal keeps `--verify` unchanged for backwards compatibility. -2. **Default verification in future major version:** Should a future Helm 4.x make `--verify-cosign` the default behavior for OCI registry installs? This is out of scope for this HIP but worth discussing. -3. **Recursive dependency verification:** Should `helm dependency update` verify cosign signatures on dependencies? This adds complexity and is deferred to a future proposal. -4. **Private Sigstore configuration:** How should private Fulcio/Rekor endpoints be configured persistently (environment variables, Helm configuration file, or both)? -5. **Cosign library versioning:** How will Helm track cosign library updates, and what is the compatibility commitment? - -## References - -- [Sigstore](https://www.sigstore.dev/) -- [Cosign Documentation](https://docs.sigstore.dev/cosign/signing/overview/) -- [Helm Provenance and Integrity](https://helm.sh/docs/topics/provenance/) -- [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) -- [Cosign OCI Signature Storage](https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md) -- [Rekor Transparency Log](https://docs.sigstore.dev/logging/overview/) -- [Fulcio Certificate Authority](https://docs.sigstore.dev/certificate_authority/overview/) -- [Kyverno Sigstore Verification](https://kyverno.io/docs/writing-policies/verify-images/sigstore/) -- [SLSA Supply Chain Framework](https://slsa.dev/) -- [HIP-0001: HIP Purpose and Guidelines](https://github.com/helm/community/blob/main/hips/hip-0001.md) diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json b/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json deleted file mode 100644 index 10d51517..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/with_skill/timing.json +++ /dev/null @@ -1 +0,0 @@ -{"total_tokens": 48451, "duration_ms": 150057, "total_duration_seconds": 150.1} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json deleted file mode 100644 index 3364bcba..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/grading.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "eval_name": "feature-hip", - "variant": "without_skill", - "expectations": [ - { - "text": "valid_yaml_preamble", - "passed": true, - "evidence": "Found valid YAML frontmatter" - }, - { - "text": "placeholder_hip_number", - "passed": true, - "evidence": "Found hip: 9999 placeholder" - }, - { - "text": "status_is_draft", - "passed": true, - "evidence": "status is draft" - }, - { - "text": "all_required_sections", - "passed": true, - "evidence": "All 11 required sections present" - }, - { - "text": "abstract_concise", - "passed": true, - "evidence": "Abstract is 110 words (target: 100-300)" - }, - { - "text": "type_is_feature", - "passed": true, - "evidence": "type is feature" - }, - { - "text": "backwards_compat_addresses_prov", - "passed": true, - "evidence": "Backwards compat section references .prov/PGP" - }, - { - "text": "specification_has_details", - "passed": true, - "evidence": "Specification is 1097 words, has code examples" - } - ] -} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md deleted file mode 100644 index 152386f4..00000000 --- a/skills/hip-author-workspace/iteration-1/feature-hip/without_skill/outputs/hip-9999.md +++ /dev/null @@ -1,470 +0,0 @@ ---- -hip: 9999 -title: "Native Chart Signing and Verification with Sigstore/Cosign" -authors: [""] -created: "2026-05-30" -type: "feature" -status: "draft" ---- - -## Abstract - -This HIP proposes replacing Helm's current PGP-based chart provenance system (`.prov` files) with native support for Sigstore/cosign signing and verification. The current provenance mechanism suffers from extremely low adoption due to the complexity of PGP key management, lack of integration with modern identity providers, and an opaque verification workflow. Sigstore provides keyless signing via OIDC identity, transparency logging via Rekor, and a verification model already established as the standard in the container image ecosystem. This proposal introduces `helm sign` and `helm verify` commands backed by cosign, stores signatures as OCI artifacts alongside chart packages in OCI registries, and maintains backward compatibility with the existing `.prov` system during a deprecation period. - -## Motivation - -### The Current State of Chart Provenance - -Helm has supported chart provenance since Helm 2 through PGP-based `.prov` files. The system requires chart publishers to maintain PGP keypairs, distribute public keys out-of-band, and package `.prov` files alongside `.tgz` chart archives. Despite being available for years, adoption is negligibly low across the ecosystem. Several factors contribute to this: - -**PGP key management is burdensome.** Publishers must generate keypairs, protect private keys, establish key rotation policies, and distribute public keys through a side channel. There is no standardized discovery mechanism for Helm chart signing keys. Users must manually locate, download, and import the correct public key before verification can occur. - -**The verification workflow is disconnected.** Running `helm verify` requires the user to have already obtained and trusted the publisher's public key. There is no integration with any identity provider, certificate authority, or transparency log. Users have no easy way to determine whether a chart was signed by a legitimate publisher without prior out-of-band key exchange. - -**The ecosystem has moved on.** The container ecosystem has converged on Sigstore (cosign, Rekor, Fulcio) as the standard for artifact signing and verification. Kubernetes itself, along with major container registries, CI/CD platforms, and policy engines, support Sigstore natively. Helm charts distributed as OCI artifacts sit in the same registries as container images but lack the same signing primitives. - -**OCI registries are now first-class.** Helm 3.8+ supports OCI registries as a native chart storage backend. OCI registries support attaching signatures, attestations, and other metadata as associated artifacts (via the OCI Reference Types / Referrers API). The `.prov` file model predates OCI support and does not integrate with this ecosystem. - -### Who Is Affected - -- **Chart publishers** who want to sign their charts but are deterred by PGP complexity. -- **Chart consumers** who want to verify chart integrity and provenance before deploying to production clusters. -- **Platform and security teams** who need to enforce signing policies as part of supply chain security requirements. -- **CI/CD pipeline operators** who need automated, keyless signing integrated with workload identity. -- **Policy engine users** (OPA/Gatekeeper, Kyverno, Sigstore Policy Controller) who want to enforce chart signature verification using the same trust framework they use for container images. - -### Real-World Impact - -Supply chain security has become a critical concern across the cloud native ecosystem. Frameworks such as SLSA (Supply-chain Levels for Software Artifacts) require artifact signing as a baseline. Organizations that enforce container image signing via cosign today have no equivalent mechanism for Helm charts, creating a gap in their supply chain security posture. Native Sigstore support would close this gap and align Helm with the broader CNCF security ecosystem. - -## Rationale - -### Why Sigstore/Cosign - -Sigstore is the CNCF's graduated project for software artifact signing. It provides three core components relevant to this proposal: - -1. **Fulcio** - A free certificate authority that issues short-lived certificates tied to OIDC identities (GitHub Actions, Google, Microsoft, etc.). This enables "keyless" signing where the signer's identity is their existing OIDC identity rather than a long-lived PGP key. -2. **Rekor** - A transparency log that records signing events immutably. Anyone can verify that a signature was created at a specific time by a specific identity without needing to trust the signer's key distribution. -3. **Cosign** - The client tool (and Go library) for signing and verifying OCI artifacts. It already supports signing container images, SBOMs, attestations, and arbitrary blobs. - -Cosign's Go library (`sigstore/cosign/v2`) is well-maintained, has a stable API, and is already used by numerous CNCF projects. Integrating it as a library dependency (rather than shelling out to the `cosign` CLI) provides a clean, testable integration. - -### Why Not Notation (Notary v2) - -Notation (the CNCF's other signing project, evolved from Notary v2) was considered. While Notation is a valid signing framework, cosign has significantly broader adoption in the Kubernetes ecosystem, is already the de facto standard for container image signing, and has a more mature Go library. Choosing cosign maximizes interoperability with existing toolchains. If Notation support is desired in the future, the proposed architecture allows additional signature backends to be added. - -### Why OCI Artifact Signatures Instead of Files - -The current `.prov` file approach stores signatures as separate files alongside chart `.tgz` archives. This model has several drawbacks: signature files can become separated from charts, classic chart repositories (index.yaml-based) have no formal association between a chart and its provenance file, and the model does not extend to OCI registries. - -OCI registries support the Referrers API (OCI Distribution Spec 1.1), which allows artifacts (such as signatures) to be associated with a subject artifact (such as a chart). Cosign already uses this mechanism for container image signatures. Storing chart signatures as OCI reference artifacts keeps the signature co-located with the chart, discoverable via standard registry APIs, and consistent with how container image signatures work. - -For charts distributed through classic (index.yaml) repositories rather than OCI registries, this proposal supports signing the chart `.tgz` as a blob and storing the signature bundle (Sigstore bundle format) as a `.cosign.bundle` file alongside the chart archive. - -### Why Keyless by Default - -Keyless signing (via Fulcio and OIDC) is the recommended default because it eliminates the key management problem that killed adoption of the PGP-based system. Publishers sign with their identity (e.g., a GitHub Actions workflow identity, a Google account, etc.) and the signature is recorded in the Rekor transparency log. Verifiers check the signature against the transparency log and a specified identity/issuer, without needing to obtain any keys in advance. - -Key-based signing (using cosign-generated keypairs or KMS-backed keys) is also supported for environments that require it, such as air-gapped clusters or organizations with existing PKI infrastructure. - -## Specification - -### New Commands - -#### `helm sign` - -Signs a packaged chart (`.tgz`) or an OCI chart reference. - -```bash -# Keyless signing (interactive OIDC flow) -helm sign mychart-1.0.0.tgz - -# Keyless signing in CI (ambient OIDC credentials) -helm sign oci://registry.example.com/charts/mychart:1.0.0 - -# Key-based signing -helm sign mychart-1.0.0.tgz --key cosign.key - -# KMS-backed signing -helm sign oci://registry.example.com/charts/mychart:1.0.0 --key awskms:///arn:aws:kms:us-east-1:123456789:key/abcd - -# Sign and attach custom annotations -helm sign oci://registry.example.com/charts/mychart:1.0.0 \ - --annotations "org.example.build-url=https://ci.example.com/build/123" -``` - -**Behavior for OCI charts:** The signature is pushed to the same registry as a Referrer artifact associated with the chart manifest, using cosign's standard OCI media types. - -**Behavior for `.tgz` files:** A Sigstore bundle file (`.cosign.bundle`) is written alongside the `.tgz`. The bundle contains the signature, certificate chain, and Rekor transparency log entry. This file replaces the role of the `.prov` file for new signing operations. - -**Flags:** - -| Flag | Description | -|------|-------------| -| `--key` | Path to a cosign private key, or a KMS URI. If omitted, keyless (OIDC) signing is used. | -| `--key-password` | Password for an encrypted cosign private key. If the key is encrypted and this flag is not provided, the user is prompted interactively. | -| `--identity-token` | An explicit OIDC identity token for keyless signing. If omitted, ambient credentials are detected (e.g., GitHub Actions OIDC, GCP metadata). | -| `--rekor-url` | URL of the Rekor transparency log (default: `https://rekor.sigstore.dev`). | -| `--fulcio-url` | URL of the Fulcio CA (default: `https://fulcio.sigstore.dev`). | -| `--tsa-url` | URL of a trusted timestamp authority. | -| `--annotations` | Key=value pairs to include in the signature payload (repeatable). | -| `--output-bundle` | Explicitly set the output path for the `.cosign.bundle` file (`.tgz` signing only). | -| `--allow-insecure-registry` | Allow signing charts in HTTP (non-TLS) registries. | - -#### `helm verify` - -Verifies the signature of a packaged chart or OCI chart reference. - -```bash -# Keyless verification (requires specifying expected identity) -helm verify oci://registry.example.com/charts/mychart:1.0.0 \ - --certificate-identity "https://github.com/myorg/mychart/.github/workflows/release.yml@refs/heads/main" \ - --certificate-oidc-issuer "https://token.actions.githubusercontent.com" - -# Keyless verification with identity regex -helm verify oci://registry.example.com/charts/mychart:1.0.0 \ - --certificate-identity-regexp ".*@myorg\\.com" \ - --certificate-oidc-issuer "https://accounts.google.com" - -# Key-based verification -helm verify mychart-1.0.0.tgz --key cosign.pub - -# Verify and display signature details -helm verify oci://registry.example.com/charts/mychart:1.0.0 \ - --certificate-identity "..." \ - --certificate-oidc-issuer "..." \ - --output json -``` - -**Behavior for OCI charts:** Signatures are discovered via the OCI Referrers API from the same registry. The chart digest is verified against the signature. - -**Behavior for `.tgz` files:** The corresponding `.cosign.bundle` file is read from the same directory (or a path specified by `--bundle`). If a `.cosign.bundle` is not found, Helm falls back to checking for a `.prov` file and uses legacy PGP verification (with a deprecation warning). - -**Flags:** - -| Flag | Description | -|------|-------------| -| `--key` | Path to a cosign public key for key-based verification. | -| `--certificate-identity` | Expected identity in the signing certificate (required for keyless). | -| `--certificate-identity-regexp` | Regex pattern for the expected identity. | -| `--certificate-oidc-issuer` | Expected OIDC issuer (required for keyless). | -| `--certificate-oidc-issuer-regexp` | Regex pattern for the expected OIDC issuer. | -| `--rekor-url` | URL of the Rekor transparency log (default: `https://rekor.sigstore.dev`). | -| `--bundle` | Explicit path to a `.cosign.bundle` file (`.tgz` verification only). | -| `--output` | Output format: `text` (default) or `json`. | -| `--allow-insecure-registry` | Allow verifying charts in HTTP (non-TLS) registries. | - -#### `helm install` / `helm upgrade` Integration - -The `--verify` flag on `helm install` and `helm upgrade` is extended to support cosign verification. - -```bash -# Verify before install using keyless verification -helm install myrelease oci://registry.example.com/charts/mychart:1.0.0 \ - --verify \ - --certificate-identity "https://github.com/myorg/mychart/.github/workflows/release.yml@refs/heads/main" \ - --certificate-oidc-issuer "https://token.actions.githubusercontent.com" - -# Verify before install using key-based verification -helm install myrelease oci://registry.example.com/charts/mychart:1.0.0 \ - --verify \ - --key cosign.pub -``` - -When `--verify` is specified and the chart source is an OCI reference, Helm uses cosign verification. When the chart source is a `.tgz` file, Helm checks for a `.cosign.bundle` first and falls back to `.prov` if not found. When the chart source is a classic chart repository, existing PGP `.prov` verification behavior is preserved. - -If `--verify` is specified and no valid signature is found through any mechanism, the command fails with a non-zero exit code. - -### Signature Payload - -For OCI charts, the signature payload is the chart manifest digest, consistent with how cosign signs container images. - -For `.tgz` files, the signature payload is a JSON document containing: - -```json -{ - "critical": { - "type": "helm chart signature", - "chart": { - "name": "mychart", - "version": "1.0.0" - }, - "image": { - "digest": "sha256:abc123..." - } - }, - "optional": { - "annotations": {} - } -} -``` - -The `digest` field contains the SHA-256 digest of the `.tgz` file, ensuring integrity verification. - -### Configuration File - -Users can set default verification policies in `~/.config/helm/sigstore.yaml` or via `$HELM_SIGSTORE_CONFIG`: - -```yaml -# Default verification settings -defaults: - rekor-url: https://rekor.sigstore.dev - fulcio-url: https://fulcio.sigstore.dev - -# Per-registry or per-repository trust policies -policies: - - registry: "registry.example.com/charts/*" - certificate-identity-regexp: ".*@example\\.com" - certificate-oidc-issuer: "https://accounts.google.com" - - registry: "ghcr.io/myorg/*" - certificate-identity: "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" - certificate-oidc-issuer: "https://token.actions.githubusercontent.com" -``` - -When `--verify` is specified without explicit identity/issuer flags, Helm looks up the matching policy from this configuration. This allows organizations to configure trust policies once rather than specifying identity flags on every command invocation. - -### Library / SDK Changes - -The Helm SDK (`pkg/action`) is extended with: - -```go -// SignOption configures chart signing -type SignOption struct { - KeyRef string // Path to cosign key or KMS URI; empty for keyless - IdentityToken string // Explicit OIDC token for keyless signing - RekorURL string // Rekor transparency log URL - FulcioURL string // Fulcio CA URL - TSAUrl string // Timestamp authority URL - Annotations map[string]string -} - -// VerifyOption configures chart verification -type VerifyOption struct { - KeyRef string // Path to cosign public key - CertificateIdentity string // Expected signer identity - CertificateIdentityRegexp string // Regex for signer identity - CertificateOIDCIssuer string // Expected OIDC issuer - CertificateOIDCIssuerRegexp string // Regex for OIDC issuer - RekorURL string // Rekor transparency log URL - BundlePath string // Explicit bundle path for .tgz files -} - -// VerifyResult contains verification output -type VerifyResult struct { - Verified bool - SignerIdentity string - Issuer string - Timestamp time.Time - RekorLogID string - Annotations map[string]string -} -``` - -### Deprecation of PGP-Based Provenance - -The existing PGP `.prov` system is deprecated but not removed in the initial release: - -1. **Phase 1 (initial release):** `helm package --sign` and `helm verify` with PGP continue to work but emit a deprecation warning recommending migration to `helm sign` with cosign. The `--sign` flag on `helm package` is marked as deprecated in help text. -2. **Phase 2 (next major version, e.g., Helm 4):** PGP signing support is removed. `helm package --sign` is removed. `helm verify` only supports cosign. The `.prov` file format is no longer generated. Legacy `.prov` files are ignored with a warning. - -During Phase 1, `helm verify` checks for cosign signatures first (OCI referrers or `.cosign.bundle`) and falls back to `.prov` if no cosign signature is found. - -## Backwards Compatibility - -### No Breaking Changes in Initial Release - -- The existing `helm package --sign` and `helm verify` commands continue to function with PGP keys during the deprecation period. -- The existing `--verify` flag on `helm install`/`helm upgrade` continues to work with `.prov` files. -- Charts without signatures continue to install normally (signing is opt-in). -- The `--keyring` flag on existing commands continues to work. -- No changes to Chart.yaml, values.yaml, or any chart structure. - -### Migration Path - -Chart publishers can adopt cosign signing incrementally: - -1. Start signing with cosign in addition to PGP (both signatures can coexist). -2. Update documentation to point consumers to cosign verification. -3. Drop PGP signing when the deprecation period ends. - -Chart consumers can adopt cosign verification incrementally: - -1. Configure trust policies in `sigstore.yaml`. -2. Start using `--verify` with cosign identity flags. -3. Remove PGP public keys from keyrings when no longer needed. - -### Dependency Impact - -This proposal adds `sigstore/cosign/v2` and its transitive dependencies to Helm's dependency tree. The cosign library is well-maintained and widely used, but it does increase the binary size and dependency surface. The cosign library dependencies are already part of the broader CNCF ecosystem and are actively maintained. - -## Security Implications - -### Improvements Over Current System - -- **Elimination of long-lived keys.** Keyless signing uses short-lived certificates (typically 10-minute validity), reducing the window of exposure if credentials are compromised. -- **Transparency logging.** All signing events are recorded in Rekor, providing an auditable, tamper-evident log. If a signing key is compromised, the transparency log enables detection of unauthorized signatures. -- **Identity-based trust.** Verifiers specify *who* they trust (e.g., a GitHub Actions workflow in a specific repository) rather than managing opaque key material. This is more intuitive and harder to misconfigure. -- **Timestamp verification.** Signatures include trusted timestamps, enabling verification that a signature was created while the signing certificate was valid, even after the certificate expires. - -### Potential Risks - -- **Dependency on public infrastructure.** Keyless signing depends on Fulcio and Rekor being available. If these services experience downtime, keyless signing fails. Mitigation: key-based signing remains available as a fallback, and organizations can run private Sigstore infrastructure. -- **OIDC token exposure.** Keyless signing involves presenting an OIDC token to Fulcio. In CI environments, this token is typically scoped and short-lived. Users should ensure their OIDC tokens are appropriately scoped. -- **Trust in Sigstore root of trust.** Keyless verification trusts the Sigstore root CA (Fulcio) and transparency log (Rekor). Organizations with strict trust requirements can run private instances of these services using the `--rekor-url` and `--fulcio-url` flags. -- **Signature stripping.** An attacker with registry write access could delete signatures. Mitigation: Rekor provides an independent record that a signature existed. Registry access controls should be applied appropriately. -- **Malicious chart with valid signature.** A compromised publisher identity could sign a malicious chart. Mitigation: this is inherent to any signing system. The transparency log provides auditability, and consumers should scope their trust policies narrowly (e.g., specific workflow paths, not entire organizations). - -### Air-Gapped Environments - -For air-gapped environments without access to public Sigstore infrastructure: - -- Key-based signing with cosign-generated keypairs works fully offline. -- Organizations can deploy private Sigstore stacks (Fulcio, Rekor, TUF root) within their network. -- The `--rekor-url`, `--fulcio-url`, and related flags support pointing to internal infrastructure. - -## How to Teach This - -### For Chart Publishers - -**Getting started (keyless, CI):** - -```bash -# In a GitHub Actions workflow: -- name: Sign Helm chart - run: | - helm package mychart/ - helm sign mychart-1.0.0.tgz - helm push mychart-1.0.0.tgz oci://ghcr.io/myorg/charts - # or, sign the chart already in the registry: - helm sign oci://ghcr.io/myorg/charts/mychart:1.0.0 -``` - -No key generation, no key storage, no key rotation. The GitHub Actions OIDC token is used automatically. - -**Getting started (key-based):** - -```bash -# One-time setup -cosign generate-key-pair - -# Sign a chart -helm sign mychart-1.0.0.tgz --key cosign.key - -# Distribute cosign.pub to consumers -``` - -### For Chart Consumers - -**Verifying a chart (keyless):** - -```bash -# Verify a chart from an OCI registry -helm verify oci://ghcr.io/myorg/charts/mychart:1.0.0 \ - --certificate-identity "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" \ - --certificate-oidc-issuer "https://token.actions.githubusercontent.com" - -# Install with verification -helm install myrelease oci://ghcr.io/myorg/charts/mychart:1.0.0 \ - --verify \ - --certificate-identity "https://github.com/myorg/charts/.github/workflows/release.yml@refs/heads/main" \ - --certificate-oidc-issuer "https://token.actions.githubusercontent.com" -``` - -**Setting up trust policies:** - -```bash -# Create a policy file so you don't need flags every time -cat > ~/.config/helm/sigstore.yaml <" ] -created: "2026-05-30" -type: "feature" -status: "draft" ---- - -## Abstract - -This HIP proposes a declarative mechanism for Helm charts to specify cluster capability prerequisites — such as the presence of specific API groups, Custom Resource Definitions (CRDs), or required controllers — that must be satisfied before installation proceeds. A new `prerequisites` field in `Chart.yaml` allows chart authors to declare what cluster capabilities their chart depends on. During `helm install` and `helm upgrade`, Helm validates these prerequisites against the target cluster's actual capabilities (via API discovery) and fails early with a clear, actionable error message when requirements are not met. - -This addresses the common pain point where charts silently deploy broken resources (e.g., Ingress objects without an ingress controller, or custom resources without their CRD installed), leading to confusing post-deployment debugging. By shifting validation left to install-time, users get immediate feedback about what their cluster is missing. - -## Motivation - -### Current Limitations - -Today, Helm charts have no native way to declare what cluster capabilities they depend on. When a chart creates an Ingress resource but the cluster has no ingress controller, or creates a ServiceMonitor but the Prometheus Operator CRD is absent, the result is: - -1. **Silent deployment of broken resources** — `helm install` succeeds, but the application does not function as expected -2. **Delayed failure signals** — users discover problems minutes or hours later when traffic fails to route or monitoring is missing -3. **Opaque error messages** — Kubernetes API errors about missing resources or unrecognized types are cryptic and do not point users toward a solution -4. **Documentation burden** — chart authors resort to lengthy README prerequisites sections that users skip or miss - -### Real-World Impact - -- **Chart consumers** waste significant time debugging failed deployments that could have been caught immediately. A chart depending on `cert-manager` CRDs will partially deploy and fail silently when those CRDs are absent. -- **Chart authors** receive support requests and issues that boil down to "you didn't have X installed." They cannot programmatically enforce their documented prerequisites. -- **Platform teams** managing multi-tenant clusters cannot easily validate that a chart is appropriate for their cluster's capabilities before deploying. -- **CI/CD pipelines** proceed through deployment stages only to discover at runtime that the target cluster lacks a required capability, wasting pipeline time and complicating rollback. - -### Existing Workarounds - -- **README documentation**: Chart authors list prerequisites in documentation, relying on users to read and follow them. This is frequently ignored. -- **Pre-install hooks with `lookup`**: Some charts use hooks that query the cluster, but this is complex, chart-specific, and provides poor UX (hook job logs are hard to surface to the user). -- **`helm template` + external validators**: Tools like `kubeval` or `kubeconform` validate rendered manifests against schemas but cannot verify that controllers or operators are actually running. -- **Wrapper scripts**: Organizations write custom scripts around `helm install` that perform prerequisite checks, fragmenting the deployment workflow. - -### Who Is Affected - -- **Chart consumers** (primary): anyone running `helm install` on a chart with undocumented or missed prerequisites -- **Chart authors** (secondary): those who want to provide a better install experience and reduce support burden -- **Platform operators** (tertiary): those validating chart compatibility with cluster offerings - -## Rationale - -### Why Declarative Prerequisites in Chart.yaml - -Placing prerequisite declarations in `Chart.yaml` makes them: - -- **Discoverable** — tools, registries, and `helm show chart` can surface them without rendering templates -- **Static** — they do not depend on values or template logic, making them predictable and cacheable -- **Enforceable** — Helm itself can validate them at a well-defined point in the install lifecycle (before template rendering) - -This approach mirrors how `kubeVersion` already constrains the Kubernetes version. The proposal extends this pattern to cluster capabilities. - -### Why Not Template-Time Checks with `lookup` - -While `lookup` can query the cluster during rendering, it has significant drawbacks: - -- It requires chart authors to write complex template logic for each prerequisite -- Error messages are custom per chart, inconsistent across the ecosystem -- It fails during `helm template` (no cluster context), preventing offline validation -- It mixes concerns: template logic should focus on generating manifests, not validating the environment - -### Why Focus on Capabilities, Not Resource Sizing - -An earlier formulation of this idea included resource sizing checks (e.g., "at least 3 nodes" or "minimum 16GB RAM available"). This was deliberately excluded because: - -- Resource availability is dynamic and changes between check-time and deploy-time -- Node count and available resources are scheduling concerns better handled by Kubernetes itself (resource requests, pod anti-affinity, topology constraints) -- Including sizing would make the feature scope unbounded and implementation far more complex -- Cluster capability (API availability, CRD presence) is a stable, binary property — either the API exists or it does not - -### How Other Projects Handle This - -- **Ansible**: uses `meta/requirements.yml` to declare collection and role dependencies -- **Terraform**: providers declare required provider versions and features -- **apt/yum**: packages declare dependencies that must be satisfied before installation -- **OLM (Operator Lifecycle Manager)**: operators declare `required` APIs in their ClusterServiceVersion - -The proposed approach aligns with these well-established dependency declaration patterns. - -## Specification - -### Chart.yaml Extension - -A new optional `prerequisites` field is added to `Chart.yaml`: - -```yaml -apiVersion: v2 -name: my-application -version: 1.0.0 -# ... other fields ... - -prerequisites: - capabilities: - - apiGroup: "networking.k8s.io" - version: "v1" - resource: "ingresses" - reason: "This chart creates Ingress resources for HTTP routing" - - apiGroup: "cert-manager.io" - version: "v1" - resource: "certificates" - reason: "TLS certificates are managed by cert-manager" - - apiGroup: "monitoring.coreos.com" - version: "v1" - resource: "servicemonitors" - reason: "Prometheus ServiceMonitor is used for metrics collection" - optional: true -``` - -### Schema - -```yaml -prerequisites: - capabilities: - - apiGroup: string # Required. The API group (e.g., "networking.k8s.io", "" for core) - version: string # Required. The API version (e.g., "v1", "v1beta1") - resource: string # Required. The plural resource name (e.g., "ingresses", "certificates") - reason: string # Optional. Human-readable explanation displayed on failure - optional: bool # Optional. Default: false. If true, a warning is issued instead of an error -``` - -### Validation Behavior - -During `helm install` and `helm upgrade`: - -1. Helm reads the `prerequisites.capabilities` list from the chart metadata -2. For each capability entry, Helm queries the cluster's API discovery endpoint (`/apis` or `/api/v1` for core resources) to check if the specified `apiGroup/version/resource` triple is registered -3. **If a required capability is missing**: Helm fails immediately with a clear error message and does not proceed to template rendering -4. **If an optional capability is missing**: Helm prints a warning and continues - -### Error Output - -``` -$ helm install my-release ./my-chart -Error: INSTALLATION FAILED: cluster prerequisites not met: - - missing required capability: cert-manager.io/v1/certificates - reason: TLS certificates are managed by cert-manager - hint: install cert-manager (https://cert-manager.io/docs/installation/) - - missing required capability: monitoring.coreos.com/v1/servicemonitors - (marked optional - continuing with warning) - -Required capabilities can be viewed with: helm show prerequisites ./my-chart -``` - -### CLI Additions - -**`helm show prerequisites CHART`**: Displays the prerequisite declarations from a chart without installing it. - -``` -$ helm show prerequisites ./my-chart -CAPABILITIES: - networking.k8s.io/v1/ingresses (required) - This chart creates Ingress resources for HTTP routing - cert-manager.io/v1/certificates (required) - TLS certificates are managed by cert-manager - monitoring.coreos.com/v1/servicemonitors (optional) - Prometheus ServiceMonitor is used for metrics collection -``` - -**`--skip-prerequisites`**: A flag on `helm install` and `helm upgrade` that bypasses prerequisite validation. This is an escape hatch for advanced users who know what they are doing (e.g., installing the chart and the prerequisite concurrently). - -``` -$ helm install my-release ./my-chart --skip-prerequisites -WARNING: Skipping prerequisite validation. The chart declares requirements that have not been verified. -``` - -### Behavior Matrix - -| Operation | Prerequisites Checked | Notes | -|-----------|----------------------|-------| -| `helm install` | Yes | Fails before rendering if requirements unmet | -| `helm upgrade` | Yes | Fails before rendering if requirements unmet | -| `helm install --skip-prerequisites` | No | Warning printed, proceeds | -| `helm template` | No | No cluster context available | -| `helm install --dry-run=client` | No | No cluster context available | -| `helm install --dry-run=server` | Yes | Validates against actual cluster | -| `helm show prerequisites` | N/A | Displays declared prerequisites | -| `helm lint` | No | Static check only; validates schema correctness | - -### Edge Cases - -- **CRD installed but controller not running**: The prerequisite check validates API registration, not controller health. This is a deliberate limitation — checking controller health would require chart-specific probes and is out of scope. The `reason` field can note this distinction. -- **Dependency charts providing the capability**: If a chart's `dependencies` include a sub-chart that installs the required CRD, the prerequisite should still be listed (CRDs from dependency charts may not be registered until after the parent chart is installed). Chart authors should use `optional: true` or omit the prerequisite in such cases. -- **Empty `prerequisites` field**: Treated as no prerequisites. Charts without the field behave identically to today. -- **Unknown fields in `prerequisites`**: Ignored with a warning, following Helm's existing forward-compatibility approach for Chart.yaml. - -## Backwards Compatibility - -This proposal is fully backwards compatible: - -- **Additive field**: The `prerequisites` field in `Chart.yaml` is optional. Existing charts without it behave identically to today. -- **Old Helm versions**: Helm versions that do not understand `prerequisites` will silently ignore the field (Helm already ignores unknown Chart.yaml fields). Charts using this feature will still install on older Helm versions — they just will not benefit from the prerequisite validation. -- **No behavior changes**: For charts that do not declare prerequisites, the install/upgrade flow is unchanged. There are no new required flags or configuration. -- **Safe for minor version**: This is purely additive behavior gated behind an opt-in declaration, suitable for a minor Helm version release. - -## Security Implications - -### API Discovery Information Leakage - -The prerequisite check queries the cluster's API discovery endpoints. These endpoints are already accessible to any authenticated user (they are required for `kubectl` to function). No new permissions or API access is introduced. - -### Malicious Charts - -A malicious chart could declare prerequisites to probe what capabilities a cluster has (by observing which prerequisites pass or fail in error messages). However: - -- This information is already available to anyone who can run `helm install` (they can use `kubectl api-resources`) -- The prerequisite check happens before any resources are created, so it does not enable any new attack vectors -- The `--skip-prerequisites` flag gives users full control - -### Denial of Service via Excessive Prerequisites - -A chart with an extremely large `prerequisites` list could cause many API discovery requests. Mitigation: Helm should cap the number of prerequisite entries (recommended limit: 50) and batch discovery requests where possible. - -### No Privilege Escalation - -Prerequisite validation uses only the API discovery endpoint, which requires no elevated permissions beyond what `helm install` already needs. It does not create, modify, or delete any cluster resources. - -## How to Teach This - -### Documentation Additions - -1. **Chart.yaml Reference**: Add `prerequisites` to the Chart.yaml specification page with full schema documentation -2. **Best Practices Guide**: "Declaring Chart Prerequisites" — when and how to use prerequisites effectively -3. **Migration Guide**: How to convert README-documented prerequisites into declarative `prerequisites` entries -4. **Helm Show**: Document `helm show prerequisites` alongside existing `helm show` subcommands - -### Key Example Pattern - -For a chart author adding prerequisites to an existing chart: - -```yaml -# Chart.yaml -apiVersion: v2 -name: my-web-app -version: 2.0.0 -description: A web application with TLS and monitoring - -prerequisites: - capabilities: - - apiGroup: "networking.k8s.io" - version: "v1" - resource: "ingresses" - reason: "Required for HTTP/HTTPS routing to the application" - - apiGroup: "cert-manager.io" - version: "v1" - resource: "certificates" - reason: "Automatic TLS certificate provisioning via cert-manager" - - apiGroup: "monitoring.coreos.com" - version: "v1" - resource: "servicemonitors" - reason: "Prometheus metrics collection (application still works without this)" - optional: true -``` - -### Teaching Approach - -For new Helm users: "Just like `kubeVersion` tells Helm what Kubernetes version your chart needs, `prerequisites` tells Helm what cluster capabilities your chart needs. If something is missing, Helm tells you right away instead of deploying broken resources." - -For experienced users: "If you have a README section listing prerequisites, you can now make those machine-readable. Add them to `prerequisites.capabilities` and Helm will validate them automatically." - -## Reference Implementation - -No implementation exists yet. The implementation will involve: - -1. **Chart.yaml schema extension**: Add `prerequisites` to the chart metadata schema with validation -2. **API discovery integration**: Add a prerequisites checker that queries the cluster's discovery API (`/apis` and `/api/v1`) to verify capability availability -3. **Install/upgrade lifecycle hook**: Insert prerequisite validation after chart loading but before template rendering -4. **CLI additions**: `helm show prerequisites` subcommand and `--skip-prerequisites` flag -5. **Error formatting**: Clear, actionable error messages listing all unmet prerequisites -6. **Lint integration**: Validate prerequisite schema correctness in `helm lint` - -## Rejected Ideas - -- **Resource sizing checks (node count, memory, CPU)**: Resource availability is dynamic and ephemeral. Checking "at least 3 nodes" at install time provides a false sense of safety because nodes can disappear between the check and pod scheduling. Kubernetes already handles resource constraints through requests/limits and scheduling. Including this would make the feature scope unbounded. -- **Controller health checks**: Verifying that a controller is not just registered but actively running and healthy would require chart-specific probe logic, timeouts, and health definitions. The API group being registered is a sufficient proxy for "this capability is intended to be available." Health monitoring is the domain of the platform operator. -- **Values-conditional prerequisites**: Allowing prerequisites to be conditional on values (e.g., "only require cert-manager if `tls.enabled=true`") would require evaluating prerequisites after values merging, complicating the lifecycle. Chart authors can use `optional: true` for capabilities that are only needed in some configurations, and document the relationship. -- **Inline remediation commands**: Including install commands for missing prerequisites (e.g., `install: "helm install cert-manager jetstack/cert-manager"`) was considered but rejected because: install procedures change over time, vary by environment, and could be a security risk if executed automatically. -- **Arbitrary Lua/CEL expressions**: A general-purpose expression language for prerequisites would be extremely powerful but introduces complexity, security concerns (arbitrary code execution), and a learning curve disproportionate to the problem being solved. -- **Namespace-scoped checks**: Checking for resources in specific namespaces (e.g., "cert-manager must be in namespace cert-manager") was rejected because API group registration is cluster-scoped and sufficient. Namespace-level checks would require additional permissions and are fragile. -- **Integration with chart dependencies**: Automatically inferring prerequisites from sub-chart resources was considered but rejected because: sub-charts may install CRDs themselves (making the prerequisite circular), and explicit declaration is clearer and more maintainable. - -## Open Issues - -1. **Exact validation timing**: Should prerequisites be checked before or after chart dependency resolution? If a dependency chart installs the CRD that the parent chart needs, checking before dependency installation would produce a false failure. The current proposal suggests checking after dependencies are installed, but this needs further discussion. -2. **Version constraints on capabilities**: Should chart authors be able to specify minimum versions of an API (e.g., "networking.k8s.io/v1 but not v1beta1 only")? The current schema uses exact version matching. Wildcard or range support could be added later. -3. **Registry integration**: Should chart registries (Artifact Hub, OCI registries) surface prerequisite information in search results and chart pages? This is desirable but out of scope for the initial implementation. -4. **Helm SDK consumers**: How should the prerequisites check be exposed in the Helm SDK for tools like Fleet, ArgoCD, or Flux that use Helm programmatically? They may want to handle prerequisite failures differently than the CLI. -5. **`reason` field localization**: Should the `reason` field support multiple languages or link to external documentation? For now, plain English text is sufficient. - -## References - -- [Helm Chart.yaml specification](https://helm.sh/docs/topics/charts/#the-chartyaml-file) -- [Kubernetes API Discovery](https://kubernetes.io/docs/reference/using-api/api-concepts/#discovery) -- [HIP-0019: Hook Output Display](https://github.com/helm/community/blob/main/hips/hip-0019.md) — related prior art for surfacing pre-install check results -- [Operator Lifecycle Manager (OLM) Dependencies](https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/) -- [Helm kubeVersion constraint](https://helm.sh/docs/topics/charts/#the-kubeversion-field) -- [Artifact Hub](https://artifacthub.io/) -- [Troubleshoot.sh Preflight Checks](https://troubleshoot.sh/docs/preflight/introduction/) diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json b/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json deleted file mode 100644 index e92d1336..00000000 --- a/skills/hip-author-workspace/iteration-1/vague-idea/with_skill/timing.json +++ /dev/null @@ -1 +0,0 @@ -{"total_tokens": 55117, "duration_ms": 262931, "total_duration_seconds": 262.9} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json deleted file mode 100644 index 3a26f9ca..00000000 --- a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/grading.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "eval_name": "vague-idea", - "variant": "without_skill", - "expectations": [ - { - "text": "valid_yaml_preamble", - "passed": true, - "evidence": "Found valid YAML frontmatter" - }, - { - "text": "placeholder_hip_number", - "passed": true, - "evidence": "Found hip: 9999 placeholder" - }, - { - "text": "status_is_draft", - "passed": true, - "evidence": "status is draft" - }, - { - "text": "all_required_sections", - "passed": true, - "evidence": "All 11 required sections present" - }, - { - "text": "abstract_concise", - "passed": true, - "evidence": "Abstract is 129 words (target: 100-300)" - }, - { - "text": "scope_is_narrowed", - "passed": true, - "evidence": "'node' appears 5x, 'storage' appears 6x (lower = more focused)" - }, - { - "text": "title_is_specific", - "passed": true, - "evidence": "Title: 'Cluster Capability Prerequisites for Helm Charts'" - }, - { - "text": "motivation_addresses_real_pain", - "passed": true, - "evidence": "Motivation describes concrete pain points" - }, - { - "text": "specification_is_implementable", - "passed": true, - "evidence": "Specification is 1178 words" - } - ] -} \ No newline at end of file diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md deleted file mode 100644 index 2dd57a26..00000000 --- a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/outputs/hip-9999.md +++ /dev/null @@ -1,455 +0,0 @@ ---- -hip: 9999 -title: "Cluster Capability Prerequisites for Helm Charts" -authors: [ "George Jenkins" ] -created: "2026-05-30" -type: "feature" -status: "draft" ---- - -## Abstract - -This HIP proposes a declarative mechanism for Helm charts to specify cluster capability prerequisites -- requirements that the target Kubernetes cluster must satisfy before installation proceeds. Today, charts can declare a minimum Kubernetes version via `kubeVersion` in Chart.yaml, but there is no standard way to express richer requirements such as "an Ingress controller must be present," "the cluster must have a minimum number of nodes," or "a specific CRD must be installed." This proposal introduces a new `prerequisites` section in Chart.yaml that allows chart authors to declare capability, resource, and API requirements. When `helm install` or `helm upgrade` is invoked, Helm evaluates these prerequisites against the live cluster and either proceeds, emits warnings, or fails with actionable error messages, depending on the severity level declared by the chart author. - -## Motivation - -### Current Limitations - -Helm charts frequently assume the existence of cluster capabilities that are not guaranteed: - -**Ingress Controllers:** Many charts create Ingress resources, but Helm does not verify that an Ingress controller is running. The resources are created successfully (the Kubernetes API accepts them), but they have no effect. Users are left debugging why their application is unreachable. - -**Custom Resource Definitions (CRDs):** Charts that depend on CRDs from other operators (e.g., cert-manager `Certificate` resources, Prometheus `ServiceMonitor` resources) fail at install time with obscure errors like `no matches for kind "Certificate" in version "cert-manager.io/v1"`. The user must independently discover, install, and configure the dependency. - -**Node Capacity:** Stateful workloads like databases or distributed systems (e.g., Elasticsearch, Kafka) require minimum node counts or resource availability. Charts deploy successfully but pods remain Pending indefinitely, leaving users to diagnose scheduling failures. - -**Storage Classes:** Charts requesting PersistentVolumeClaims with a specific StorageClass fail silently when that class does not exist. The PVC is created but never bound, and the dependent pods never start. - -**API Versions:** The existing `kubeVersion` field checks the server version string, but does not verify whether specific API groups or versions are actually available (which depends on feature gates, API aggregation, and installed extensions). - -### Who Is Affected - -- **Chart consumers** waste time debugging deployment failures that could have been caught upfront. -- **Chart authors** write extensive documentation listing prerequisites, but users frequently skip or miss these sections. -- **Platform teams** managing multi-tenant clusters receive support requests for issues that are cluster-configuration problems, not chart problems. -- **CI/CD pipelines** that deploy charts fail late in the process, after potentially disruptive partial installations. - -### Existing Workarounds - -Chart authors currently work around these limitations using: - -1. **Documentation:** Listing prerequisites in README files. This is easily missed and not machine-readable. -2. **Pre-install hooks with `lookup()`:** Running Jobs that query the cluster, but this requires RBAC privileges, adds deployment time, and the error reporting is limited (see HIP-0019 for related hook output improvements). -3. **Template-time `lookup()` calls:** Using `{{ if not (lookup "networking.k8s.io/v1" "IngressClass" "" "") }} {{ fail "..." }} {{ end }}` in templates. This works for simple API checks but cannot verify operational capabilities (e.g., "is a controller actually processing these resources?"), does not work with `helm template` or `--dry-run=client`, and scatters prerequisite logic across templates instead of centralizing it. -4. **External tools:** Tools like Troubleshoot.sh preflight checks (referenced in HIP-0019) provide this capability but require separate installation and are not part of the chart itself. - -None of these approaches are standardized, composable, or provide a consistent user experience. - -## Rationale - -### Why Chart.yaml - -Prerequisites are metadata about what a chart requires from the environment. Like `kubeVersion`, `apiVersion`, `dependencies`, and `annotations`, they belong in Chart.yaml because: - -- They are declarative and can be evaluated before template rendering -- They are inspectable without installing the chart (`helm show chart`) -- They compose naturally with chart dependencies (a parent chart's prerequisites are the union of its own and its subcharts' prerequisites) -- They are machine-readable, enabling tooling beyond Helm (e.g., marketplace UIs, GitOps tools, policy engines) - -### Why Not Extend `kubeVersion` - -The `kubeVersion` field uses semver constraint syntax and is limited to matching the Kubernetes server version string. Extending it to cover arbitrary capabilities would be a semantic overload. Prerequisites are a different class of metadata: they describe cluster state, not just the server binary version. - -### Why Not Template-Only - -A template-only approach (using `lookup()` and `fail`) has been available since Helm 3 and adoption for prerequisite checking is minimal. The reasons are: - -- It does not work with `helm template` or `--dry-run=client`, preventing offline validation -- It intermingles prerequisite checks with resource generation logic -- There is no standard structure, so every chart invents its own approach -- It cannot be aggregated across chart dependencies -- It provides no way to distinguish hard failures from soft warnings - -### Severity Levels - -The proposal includes two severity levels: - -- **`required`** (default): Installation fails if the prerequisite is not met. Used for capabilities without which the chart fundamentally cannot function. -- **`recommended`**: Installation proceeds with a prominent warning. Used for capabilities that enhance the chart but are not strictly necessary (e.g., metrics collection via Prometheus). - -A `required`/`recommended` distinction is deliberately simple. More granular severity levels were considered and rejected (see Rejected Ideas) to keep the mental model accessible. - -### Prior Art - -- **Kubernetes itself** uses feature gates and API discovery to manage capability availability. -- **Operator Lifecycle Manager (OLM)** in OpenShift has a `required` section in ClusterServiceVersion manifests for specifying API and CRD dependencies. -- **Troubleshoot.sh** provides preflight check specifications with pass/warn/fail outcomes. -- **APT/RPM package managers** have `Depends`, `Recommends`, and `Suggests` for expressing dependency strength. -- **Terraform** has `required_providers` blocks for declaring infrastructure prerequisites. - -The design draws from OLM's API requirement declarations and Troubleshoot.sh's outcome model while keeping the specification chart-native and lightweight. - -## Specification - -### Chart.yaml Extension - -A new optional `prerequisites` field is added to Chart.yaml. It contains a list of prerequisite declarations, each specifying a type, parameters, and severity. - -```yaml -apiVersion: v2 -name: my-application -version: 1.0.0 -kubeVersion: ">=1.26.0" -prerequisites: - # Require that the networking.k8s.io/v1 IngressClass API exists - # (implies an Ingress controller is installed) - - type: apiVersion - apiVersion: "networking.k8s.io/v1" - kind: IngressClass - severity: required - reason: "This chart creates Ingress resources that require an Ingress controller." - - # Require cert-manager CRDs - - type: apiVersion - apiVersion: "cert-manager.io/v1" - kind: Certificate - severity: required - reason: "TLS certificates are managed via cert-manager. Install cert-manager before deploying this chart." - - # Recommend Prometheus Operator for monitoring - - type: apiVersion - apiVersion: "monitoring.coreos.com/v1" - kind: ServiceMonitor - severity: recommended - reason: "ServiceMonitor resources enable automatic Prometheus scraping. Monitoring will be limited without the Prometheus Operator." - - # Require a minimum number of schedulable nodes - - type: nodeCount - minimum: 3 - severity: required - reason: "This chart deploys a 3-node distributed database that requires at least 3 schedulable nodes." - - # Require a specific StorageClass - - type: storageClass - name: "fast-ssd" - severity: required - reason: "High-performance SSD storage is required for the database volumes." - - # Require minimum allocatable resources across the cluster - - type: clusterResources - cpu: "8" - memory: "32Gi" - severity: recommended - reason: "The full deployment with all replicas requires at least 8 CPU cores and 32Gi of memory across schedulable nodes." -``` - -### Prerequisite Types - -#### `apiVersion` - -Checks whether a specific API group/version (and optionally a specific resource kind) is available via the Kubernetes API discovery mechanism. - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `apiVersion` | string | yes | The API group/version to check (e.g., `networking.k8s.io/v1`, `apps/v1`) | -| `kind` | string | no | A specific resource kind within the API group/version | -| `severity` | string | no | `required` (default) or `recommended` | -| `reason` | string | no | Human-readable explanation shown when the check fails | - -**Evaluation:** Uses the Kubernetes discovery API (`/apis` and `/api`) to check whether the specified group/version is registered. If `kind` is specified, further checks that the resource type exists in that group/version. This mirrors the mechanism Helm already uses internally for resource mapping. - -#### `nodeCount` - -Checks the number of schedulable (non-cordoned, Ready) nodes in the cluster. - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `minimum` | integer | yes | Minimum number of schedulable nodes | -| `severity` | string | no | `required` (default) or `recommended` | -| `reason` | string | no | Human-readable explanation | - -**Evaluation:** Lists nodes, filters to those with `Ready` condition `True` and `spec.unschedulable != true`, and compares count against `minimum`. - -#### `storageClass` - -Checks whether a specific StorageClass exists in the cluster. - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `name` | string | yes | Name of the StorageClass to check | -| `severity` | string | no | `required` (default) or `recommended` | -| `reason` | string | no | Human-readable explanation | - -**Evaluation:** Attempts to get the named StorageClass from the `storage.k8s.io/v1` API. - -#### `clusterResources` - -Checks aggregate allocatable resources across schedulable nodes. - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `cpu` | string | no | Minimum allocatable CPU (Kubernetes quantity format) | -| `memory` | string | no | Minimum allocatable memory (Kubernetes quantity format) | -| `severity` | string | no | `required` (default) or `recommended` | -| `reason` | string | no | Human-readable explanation | - -**Evaluation:** Sums `status.allocatable` across schedulable nodes and compares against declared minimums. At least one of `cpu` or `memory` must be specified. - -**Important caveat:** This check reports total allocatable resources, not available (unallocated) resources. Determining truly available resources would require inspecting all existing pod resource requests across the cluster, which is expensive and requires broad RBAC permissions. The allocatable check establishes whether the cluster is sized appropriately, not whether it currently has spare capacity. - -### Evaluation Behavior - -#### During `helm install` and `helm upgrade` - -1. After chart loading and dependency resolution but before template rendering, Helm evaluates all prerequisites from the chart and its transitive dependencies. -2. Prerequisites are deduplicated: if the same check (identical type and parameters) appears multiple times, the strictest severity wins. -3. Each prerequisite is evaluated against the cluster. -4. Results are categorized: - - **Failed required prerequisites:** Installation is aborted. All failures are reported together (not just the first) so the user can address them in one pass. - - **Failed recommended prerequisites:** Warnings are printed to stderr. Installation proceeds. - - **Passed prerequisites:** Reported at `--debug` verbosity. -5. Error output includes the `reason` text from the chart author, providing actionable guidance. - -Example failure output: - -``` -Error: INSTALLATION FAILED: cluster prerequisites not met - -REQUIRED (installation cannot proceed): - [FAIL] apiVersion networking.k8s.io/v1 IngressClass: API not found - Reason: This chart creates Ingress resources that require an Ingress controller. - [FAIL] storageClass fast-ssd: StorageClass not found - Reason: High-performance SSD storage is required for the database volumes. - -RECOMMENDED (warnings): - [WARN] apiVersion monitoring.coreos.com/v1 ServiceMonitor: API not found - Reason: ServiceMonitor resources enable automatic Prometheus scraping. Monitoring will be limited without the Prometheus Operator. - -2 required prerequisite(s) failed. Use --skip-prerequisites to override. -``` - -#### During `helm template` and `--dry-run=client` - -Prerequisites are not evaluated (no cluster access). A note is printed indicating that prerequisite validation was skipped. The `prerequisites` section can still be inspected via `helm show chart`. - -#### During `--dry-run=server` - -Prerequisites are evaluated against the cluster, matching live install/upgrade behavior. - -### Command-Line Flags - -| Flag | Description | -|------|-------------| -| `--skip-prerequisites` | Skip all prerequisite checks. Installation proceeds regardless of prerequisite failures. | -| `--skip-prerequisites=recommended` | Skip only recommended prerequisite checks. Required prerequisites are still enforced. | - -The `--skip-prerequisites` flag provides an escape hatch for scenarios where the user knows better than the chart (e.g., a custom Ingress controller that does not register IngressClass resources, or a cluster autoscaler that will add nodes on demand). - -### New Command: `helm prerequisites` - -A new subcommand allows evaluating prerequisites without installing: - -```bash -# Check prerequisites for a chart against the current cluster -helm prerequisites show ./my-chart - -# Check prerequisites against a specific cluster context -helm prerequisites show ./my-chart --kube-context production - -# Output in JSON for tooling consumption -helm prerequisites show ./my-chart --output json -``` - -This enables CI/CD pipelines and platform tools to validate prerequisites independently of installation. - -### Subchart and Dependency Handling - -Prerequisites from subcharts and dependencies are aggregated into the parent chart's prerequisite evaluation: - -1. Each dependency's prerequisites are loaded recursively. -2. Prerequisites are evaluated as a flat list after deduplication. -3. If a dependency is conditional (e.g., `condition: redis.enabled`), its prerequisites are only evaluated when the condition is true. Condition evaluation uses the merged values, consistent with how Helm resolves dependency conditions today. -4. Conflicting prerequisites (e.g., parent requires `storageClass: fast-ssd` and subchart requires `storageClass: standard`) are both evaluated independently -- both must pass. - -### Schema Validation - -The `prerequisites` field is validated during `helm lint` and `helm package`: - -- Each entry must have a valid `type` -- Required fields for each type must be present -- `severity` must be `required` or `recommended` (defaults to `required` if omitted) -- Unknown fields generate a warning (for forward compatibility with future prerequisite types) - -## Backwards Compatibility - -This proposal is fully backwards compatible: - -- The `prerequisites` field in Chart.yaml is optional. Existing charts work unchanged. -- Older versions of Helm that do not understand `prerequisites` will ignore the field, as Chart.yaml allows arbitrary additional fields. Charts using prerequisites will still install on older Helm versions, just without the safety checks. -- No existing Chart.yaml fields are modified or removed. -- No changes to template rendering, release storage, or any other existing behavior. -- The `--skip-prerequisites` flag ensures users are never blocked by prerequisites if they choose to override them. - -The `apiVersion: v2` chart format already permits additional top-level keys in Chart.yaml without schema errors, so the addition of `prerequisites` does not require a new chart API version. - -## Security Implications - -### RBAC Requirements - -Prerequisite evaluation requires the Helm client (or its service account) to have read access to cluster-level resources: - -- **API discovery:** Already required by Helm for resource mapping. No additional permissions needed for `apiVersion` checks. -- **Node listing:** Requires `get`/`list` on `nodes` (cluster-scoped). This may not be available in restricted environments where Helm is limited to namespace-scoped operations. -- **StorageClass listing:** Requires `get` on `storageclasses.storage.k8s.io` (cluster-scoped). -- **Resource aggregation:** Requires `list` on `nodes` with access to `status.allocatable`. - -If Helm lacks the permissions to evaluate a prerequisite, the check is treated as a warning (not a failure) with a message indicating that the check could not be performed due to insufficient permissions. This ensures that prerequisite checks do not break existing deployments in restricted RBAC environments. - -### Information Disclosure - -Prerequisite checks only read cluster state; they do not expose any information that is not already available to the Helm user via `kubectl`. The `reason` field is authored by the chart maintainer and does not contain cluster-derived data. - -### Malicious Charts - -A malicious chart author could declare prerequisites designed to: - -- **Fingerprint cluster capabilities:** By observing which prerequisites pass or fail. Mitigation: This information is already available to chart templates via `lookup()` and `.Capabilities`. Prerequisites do not expand the information surface. -- **Cause denial of service:** By declaring an expensive prerequisite check (e.g., `clusterResources` on a very large cluster). Mitigation: All prerequisite types defined in this proposal have bounded evaluation cost. Future prerequisite types should be evaluated for cost before acceptance. - -## How to Teach This - -### Documentation Additions - -1. **Chart.yaml Reference:** Add `prerequisites` to the Chart.yaml specification with field descriptions and type reference. -2. **Chart Developer Guide:** A new "Declaring Prerequisites" section explaining when and how to use each prerequisite type, with guidance on choosing between `required` and `recommended`. -3. **Best Practices Guide:** Add recommendations such as: - - Always include a `reason` with actionable remediation steps - - Prefer `apiVersion` checks over `nodeCount` or `clusterResources` when possible (API checks are cheap and deterministic) - - Use `recommended` for capabilities that enhance but are not essential to the chart - - Do not use prerequisites for conditions that can be handled gracefully by conditional templates - -### User-Facing Messages - -All prerequisite failure messages should follow a consistent format: - -``` -[FAIL|WARN] : - Reason: -``` - -### Example: Adding Prerequisites to an Existing Chart - -A chart author who maintains a web application chart with Ingress support would add: - -```yaml -# Chart.yaml -prerequisites: - - type: apiVersion - apiVersion: "networking.k8s.io/v1" - kind: IngressClass - severity: recommended - reason: >- - An Ingress controller is needed to expose the application externally. - Install an Ingress controller such as ingress-nginx - (https://kubernetes.github.io/ingress-nginx/) or set - ingress.enabled=false to use a different exposure method. -``` - -This is marked `recommended` rather than `required` because the chart can function without Ingress (the user might use a LoadBalancer Service or port-forward instead). - -## Reference Implementation - -A future pull request will: - -1. Extend the Chart.yaml schema to include the `prerequisites` field -2. Implement prerequisite evaluation logic for each type (`apiVersion`, `nodeCount`, `storageClass`, `clusterResources`) -3. Integrate prerequisite evaluation into the `install` and `upgrade` action pipelines -4. Add `--skip-prerequisites` flag to `helm install` and `helm upgrade` -5. Implement the `helm prerequisites show` subcommand -6. Add prerequisite validation to `helm lint` -7. Implement subchart prerequisite aggregation and deduplication -8. Add comprehensive unit and integration tests -9. Update helm.sh documentation - -## Rejected Ideas - -### Arbitrary Scripting / Custom Checks - -Allowing chart authors to define custom prerequisite checks via embedded scripts (bash, Lua, Wasm, etc.) was considered. This was rejected because: - -- It introduces a security risk (executing arbitrary code from a chart before the user has reviewed the rendered manifests) -- It makes prerequisites non-portable and hard to reason about -- It conflicts with Helm's declarative philosophy -- Custom checks can still be implemented via pre-install hooks (see HIP-0019 for improved hook output) - -### Fine-Grained Severity Levels - -A five-level severity scale (critical, required, recommended, optional, informational) was considered. This was rejected in favor of the simpler required/recommended binary because: - -- Two levels cover the dominant use cases (must-have vs. nice-to-have) -- More levels require users to understand subtle distinctions that rarely affect behavior -- Additional levels can be added in a future HIP if demand materializes - -### Resource-Level Prerequisites (Per-Template) - -Attaching prerequisites to individual templates (e.g., "only render this Ingress if IngressClass exists") was considered. This was rejected because: - -- It conflates prerequisite checking with conditional rendering, which templates already handle via `{{ if }}` and `lookup()` -- Chart-level prerequisites are simpler to reason about and aggregate across dependencies -- Template-level conditions are better expressed as values (e.g., `ingress.enabled`) - -### Namespace-Scoped Checks - -Checking for specific resources within a namespace (e.g., "a Secret named `tls-cert` must exist") was considered. This was rejected because: - -- It overlaps with Helm's existing dependency mechanism and `lookup()` in templates -- Namespace-scoped resources are often created by the chart itself or its hooks -- It would significantly expand the prerequisite specification surface - -### Operational Checks (Liveness/Health) - -Checking not just that an API exists but that a controller is operational (e.g., "the Ingress controller is healthy and processing resources") was considered. This was rejected because: - -- There is no standard mechanism to determine whether a controller is "operational" across all implementations -- It would require executing probes or health checks, which is slow and unreliable -- API availability (via discovery) is a good proxy for controller presence in practice - -### Using Annotations Instead of a Top-Level Field - -Placing prerequisites in Chart.yaml `annotations` (similar to HIP-0015 for images) was considered. This was rejected because: - -- Prerequisites have structured, typed data that maps poorly to annotation string values -- Annotations are intended for metadata consumed by external tools, not by Helm itself -- A top-level field enables schema validation and clearer documentation - -### Embedding in values.yaml - -Placing prerequisites in values.yaml was rejected because: - -- Prerequisites are chart metadata, not user-configurable values -- Users should not be able to accidentally disable safety checks by overriding values -- values.yaml is for parameterizing the chart, not declaring its environmental requirements - -## Open Issues - -1. **Extensibility mechanism for custom prerequisite types:** Should this proposal include a plugin or extension point for registering custom prerequisite types, or should new types only be added through future HIPs? A plugin system would be more flexible but adds complexity to the initial implementation. - -2. **Interaction with `helm diff` plugins:** Popular plugins like `helm-diff` run template rendering without installing. Should they also evaluate prerequisites? This may require plugin API changes. - -3. **Dependency ordering of prerequisites:** If chart A lists chart B as a dependency, and chart B has prerequisites, should chart A be able to declare that it satisfies chart B's prerequisites (e.g., chart A installs the CRDs that chart B needs)? This relates to the broader question of install-time ordering (see HIP-0025). - -4. **OCI chart metadata:** When charts are stored as OCI artifacts, should prerequisites be extractable from the OCI manifest without pulling the full chart? This would enable registries and marketplace UIs to display prerequisite information. - -5. **Cluster capability reporting:** Should Helm provide a `helm cluster capabilities` command that reports what prerequisites the current cluster would satisfy? This would be useful for platform teams but expands Helm's scope. - -## References - -- [Helm Chart.yaml Specification](https://helm.sh/docs/topics/charts/#the-chartyaml-file) -- [Kubernetes API Discovery](https://kubernetes.io/docs/reference/using-api/api-concepts/#api-discovery) -- [HIP-0015: Annotation for Images used by Helm Charts](https://github.com/helm/community/blob/main/hips/hip-0015.md) -- [HIP-0019: New annotations for displaying hook output](https://github.com/helm/community/blob/main/hips/hip-0019.md) -- [HIP-0025: Better Support for Resource Creation Sequencing](https://github.com/helm/community/blob/main/hips/hip-0025.md) -- [OLM ClusterServiceVersion Dependencies](https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/) -- [Troubleshoot.sh Preflight Checks](https://troubleshoot.sh/docs/preflight/introduction/) -- [Helm lookup Function](https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#using-the-lookup-function) -- [Kubernetes Node Status](https://kubernetes.io/docs/concepts/architecture/nodes/#condition) diff --git a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json b/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json deleted file mode 100644 index bf227389..00000000 --- a/skills/hip-author-workspace/iteration-1/vague-idea/without_skill/timing.json +++ /dev/null @@ -1 +0,0 @@ -{"total_tokens": 59853, "duration_ms": 169596, "total_duration_seconds": 169.6} \ No newline at end of file