diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..98253a4 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,24 @@ +# Code owners for this repository. +# +# GitHub requests review from an owner automatically, and the branch protection +# rule requires an approving review from one. Replace the handles below before +# using this template for a real pack: a CODEOWNERS file naming someone who does +# not maintain the repository is worse than none, because it routes review to a +# person who will not do it. +# +# Entries are last-match-wins, so put the general rule first and narrow after. + +# Everything, by default. +* @your-handle + +# Uncomment and adjust as the pack grows. +# /chart/ @your-handle +# /docs/ @your-handle +# /.github/workflows/ @your-handle + +# Files the repository standards require. Losing one silently breaks +# conformance, so review them deliberately. +/pack-metadata.yaml @your-handle +/GOVERNANCE.md @your-handle +/MAINTAINERS.md @your-handle +/SECURITY.md @your-handle diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..c62ca05 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,15 @@ +# Code of Conduct + +This project follows the Nebari Code of Conduct. + +The full text, including what is expected, what is unacceptable, and how enforcement works, is in the governance repository: + +**[Nebari Code of Conduct](https://github.com/nebari-dev/governance/blob/main/CODE_OF_CONDUCT.md)** + +## Reporting + +To report an incident, use [this form](https://forms.gle/PFHmsMUiu12qJwWV7_), which reaches the [Code of Conduct committee](https://github.com/nebari-dev/governance/blob/main/code-of-conduct/coc_enforcement.md#the-code-of-conduct-committee). + +If you would rather not use the form, or the incident involves a member of the committee, you can contact any committee member directly using the addresses in the [enforcement manual](https://github.com/nebari-dev/governance/blob/main/code-of-conduct/coc_enforcement.md). + +Reports are kept confidential. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ac3fc1d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,29 @@ +# Contributing + +Contributions are welcome, including code, documentation, issues, and review. + +## Before you start + +- The [Nebari governance](https://github.com/nebari-dev/governance/blob/main/GOVERNANCE.md) explains who decides what. Most decisions about this repository are made by its maintainers, listed in [MAINTAINERS.md](MAINTAINERS.md). +- The [community guidelines](https://www.nebari.dev/community) cover the contribution process in detail. +- The [Code of Conduct](CODE_OF_CONDUCT.md) applies to every space this project uses. + +## Making a change + +1. Open an issue first for anything substantial, so the approach can be discussed before you build it. +2. Work on a branch and open a pull request. Do not commit to the default branch. +3. A pull request needs one approving review before merge, and CI has to pass. + +Commit and triage access on this repository is granted by its maintainers as trust is established. Ask if you have been contributing and want it. + +## Changes that need an RFD + +Some changes are not this repository's to make on its own. A change to the platform contract, the shared conventions, the security baseline, or the repository standards affects every pack, and goes through a [platform RFD](https://github.com/nebari-dev/governance/blob/main/GOVERNANCE.md#platform-rfds) in the governance repository. + +If a maintainer tells you your change needs an RFD, that is what they mean. + +## For packs specifically + +- The [Nebari Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md) is the contract a pack has to satisfy. +- The [release readiness checklist](docs/release-readiness-checklist.md) governs promotion between maturity levels. +- `pack-metadata.yaml` declares this pack's level, owner, and target specification version. Keep it accurate; the [pack dashboard](https://github.com/nebari-dev/software-pack-dashboard) reads it. diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..1f92bb4 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,27 @@ +# Governance + +This repository is governed by the Nebari project governance, which lives in one place: + +**[nebari-dev/governance](https://github.com/nebari-dev/governance/blob/main/GOVERNANCE.md)** + +That document covers stewardship, the teams and what each one decides, the two decision lanes, and how the governance itself is amended. This file exists so you do not have to know that before you can find it. + +## This repository + +| | | +| --- | --- | +| **Tier** | Official. It lives in the `nebari-dev` organization, so it carries the Nebari name and must satisfy the [Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md) and the [repository standards](https://github.com/nebari-dev/governance/blob/main/repository-standards.md) | +| **Target Pack Specification version** | `0.1.0`, also declared in `pack-metadata.yaml` as `target_pack_spec_version` | +| **Maintainers** | [MAINTAINERS.md](MAINTAINERS.md) | + +Update the table when either changes. A stub that lies is worse than no stub. + +## Who decides what + +Day-to-day decisions about this repository, its features, releases, dependencies, and maturity level, are made by its maintainers. + +A change that crosses repository boundaries or alters a shared contract is not this repository's to make. That includes the Pack Specification, the authentication, routing, and TLS conventions, the security baseline, and the repository standards themselves. Those go through a [platform RFD](https://github.com/nebari-dev/governance/blob/main/GOVERNANCE.md#platform-rfds), decided by the Core team. + +## Community packs + +A pack outside the `nebari-dev` organization is not governed by this. It needs to satisfy the Pack Specification to work, and to follow the [naming rules](https://github.com/nebari-dev/governance/blob/main/trademark-and-naming.md) so it does not imply official endorsement. Beyond that it is yours. diff --git a/LICENSE b/LICENSE index 261eeb9..c3badd1 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2026 OpenTeams Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..6ed840f --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,19 @@ +# Maintainers + +This file is the authoritative list of maintainers for this repository. Nothing else is: not the governance repository, not the website, not the GitHub team list. + +Maintainers hold write access here, decide this repository's features, releases, dependencies, and, for a pack, its maturity level. See the [Nebari governance](https://github.com/nebari-dev/governance/blob/main/GOVERNANCE.md#teams-and-roles) for what that authority covers and what it does not. + +| Name | GitHub | Role | +| ---- | ------ | ---- | +| _Your name_ | [@your-handle](https://github.com/your-handle) | Maintainer | + +The `owner` field in `pack-metadata.yaml` names the single most accountable maintainer. Keep the two consistent. + +## Becoming a maintainer + +Existing maintainers add new ones, on the basis of a record of regular, valuable contributions to this repository. Nominate someone, including yourself, by opening an issue here. + +## Stepping back + +Say so, in an issue or privately to the other maintainers. Update this file and `pack-metadata.yaml` in the same change so the accountable person is never ambiguous. diff --git a/README.md b/README.md index 25ce005..aeb3a49 100644 --- a/README.md +++ b/README.md @@ -116,12 +116,14 @@ For local development (optional): ``` software-pack-template/ - .github/workflows/ - build-images.yaml # Build + publish images via reusable pack-build-image - lint.yaml # Manifest validation (all examples) - test.yaml # Integration tests on kind cluster - test-integration.yaml # NebariApp integration tests (full stack) - release.yaml # Release chart via reusable pack-release workflow + .github/ + CODEOWNERS # Review routing; replace the handles + workflows/ + build-images.yaml # Build + publish images via reusable pack-build-image + lint.yaml # Manifest validation (all examples) + test.yaml # Integration tests on kind cluster + test-integration.yaml # NebariApp integration tests (full stack) + release.yaml # Release chart via reusable pack-release workflow examples/ vanilla-yaml/ # Example 1: Plain Kubernetes manifests deployment.yaml # nginx Deployment @@ -177,10 +179,18 @@ software-pack-template/ docs/ nebariapp-crd-reference.md # Full NebariApp field reference auth-flow.md # Authentication flow details + release-readiness-checklist.md # Maturity levels and promotion gates + adr/ # Architecture decision records + pack-metadata.yaml # Declared maturity, owner, target spec version .gitignore .editorconfig + CODE_OF_CONDUCT.md # Links to the org Code of Conduct + CONTRIBUTING.md # How to contribute, and what needs an RFD + GOVERNANCE.md # Tier, target spec version, who decides what LICENSE # Apache 2.0 + MAINTAINERS.md # Authoritative maintainer list for this repo README.md # This file + SECURITY.md # How to report a vulnerability ``` ## The NebariApp CRD diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2b4a83e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,29 @@ +# Security policy + +## Reporting a vulnerability + +Report it privately, through GitHub's security advisories for this repository: + +**Security → Advisories → Report a vulnerability** + +Please do not open a public issue for a vulnerability. Disclosing one publicly before maintainers can ship a fix puts every deployment at risk. + +If advisories are not enabled here, or the issue affects the platform rather than this pack, report it against [nebari](https://github.com/nebari-dev/nebari/security/advisories/new) instead. + +## What to include + +Whatever you have. A rough report today is worth more than a polished one next month: + +- what an attacker can do, and what access they need to start +- the versions or configurations affected +- steps to reproduce, if you have them + +## What happens next + +A maintainer will acknowledge the report and tell you whether it is accepted. If it is, you will hear when a fix is planned and released, and you will be credited unless you ask not to be. + +## Supported versions + +Only the latest release, unless this repository's README says otherwise. + +Security requirements that every Nebari pack has to meet, such as not running containers as root and pinning image tags, are in the [security baseline](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md#6-security-baseline). diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..199ebd7 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,43 @@ +# Architecture decision records + +An ADR records a decision that was made, the alternatives that were considered, and why the choice went the way it did. It is not a design doc and not a plan: it is written once the decision is real, and then left alone. + +The point is that six months later nobody has to reconstruct the reasoning from a pull request thread, and nobody re-litigates a settled question by accident. + +## When to write one + +When a choice will outlive the person who made it and would be expensive to reverse. Picking a dependency you will build on, deciding how the pack handles authentication, choosing not to support a deployment mode. + +Not for reversible or local choices. A function name is not an ADR. + +## Naming + +`YYYY-MM-DD-short-slug.md`, dated when the decision was accepted. The Nebari Operator's [`docs/decisions/`](https://github.com/nebari-dev/nebari-operator/tree/main/docs/decisions) is the reference for how these read in practice. + +## Shape + +Keep it short. A page is usually enough. + +```markdown +# Short title of the decision + +**Status:** accepted | superseded by +**Date:** YYYY-MM-DD + +## Context +What forced a decision. Constraints that were real at the time. + +## Decision +What was decided, stated plainly. + +## Alternatives considered +What else was on the table, and why it lost. This is the part future +readers actually need. + +## Consequences +What this makes easy, what it makes hard, and what it commits us to. +``` + +## Superseding + +Do not edit a decision to change its outcome. Write a new record and mark the old one superseded, pointing at the new one. The history of what was believed and when is the reason these are worth keeping. diff --git a/docs/release-readiness-checklist.md b/docs/release-readiness-checklist.md index 9bcd67d..5c4a553 100644 --- a/docs/release-readiness-checklist.md +++ b/docs/release-readiness-checklist.md @@ -23,8 +23,9 @@ A pack moves through four sequential active levels. **Deprecated** is an orthogo - **Promise:** Stable enough for a customer to deploy in their own environment with engineering support. APIs and values may still change between releases. - **Pre-sales behavior:** Can demo without caveat. Customer pilots may be offered with engineering involvement. -### GA (v1.0+) +### GA (`1.0.0` and above) - **Audience:** Production customers. +- **Versioning:** Experimental, Alpha, and Beta sit on the `0.x` line. GA means `1.0.0` or above, per the [version tagging convention](#version-tagging-convention). - **Promise:** Fully supported. Documented upgrade path between releases. We own the bug-fix and security-fix story. - **Pre-sales behavior:** Pitch freely. @@ -54,7 +55,8 @@ Key fields the checklist depends on: - `owner` — accountable engineer's GitHub username - `product_owner` — required when `level: ga` - `deprecated` + `sunset_date` — see Deprecated status above -- `nebariapp_integration` — `none` | `partial` | `full` | `na` +- `nebariapp_integration` — `none` | `partial` | `full` | `na`, measured against the [Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md) +- `target_pack_spec_version` — the specification version the pack was built against - `scope.standalone-supported` — `yes` | `no` - `last_promoted_at` / `last_promoted_pr` — updated on every promotion - `demo_notes` — current known gotchas, surfaced in the dashboard Notes column (first ~100 chars) @@ -157,6 +159,8 @@ If "product owner" has not been named for a pack, the tech lead acts as product - `[A]` `NebariApp` reaches Ready condition with all applicable sub-conditions healthy (RoutingReady, TLSReady, AuthReady) - `[A]` All configurable NebariApp fields used by the pack are documented in the pack's values reference - `[A]` `nebariapp_integration` field in `pack-metadata.yaml` accurately reflects the integration depth (`none` | `partial` | `full` | `na`) +- `[A]` Pack satisfies every MUST in the [Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md), which is the contract these checks are measured against +- `[B]` `target_pack_spec_version` in `pack-metadata.yaml` names the specification version the pack was verified against - `[B]` Auth-protected routes reject unauthenticated requests (if auth enabled) - `[B]` Auth-protected routes allow authenticated users with correct group membership (if auth enabled) - `[B]` Health/readiness probes configured and verified @@ -184,6 +188,9 @@ If "product owner" has not been named for a pack, the tech lead acts as product - `[GA]` Example dashboard or Grafana panel definition for the LGTM stack (if applicable) ### Security + +These are the [security baseline](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md#6-security-baseline), which the Pack Specification owns. It is repeated here because this checklist is what a promotion PR is reviewed against; the specification is authoritative if the two ever disagree. + - `[B]` Containers do not run as root (or have documented justification if they must) - `[B]` No secrets hardcoded in templates or default values - `[B]` OIDC scopes minimally scoped to what the app needs @@ -207,8 +214,10 @@ If "product owner" has not been named for a pack, the tech lead acts as product - `[GA]` Pre-sales engineer has verified the demo flow on the GA release commit after release ### Sign-off + +These roles are operational, not governance roles. The project governance does not define or appoint them; this checklist is the authority on who signs off on what, so the two cannot drift. Pre-sales is not a sign-off role: it is a commercial function, and demo readiness is tracked separately under Pre-sales Verification. + - `[A]` Pack owner approves the promotion PR -- `[A]` Pre-sales rep approves the promotion PR - `[B]` Tech lead approves the promotion PR - `[GA]` Product owner has documented and verified acceptance criteria - `[GA]` Product owner approves the promotion PR diff --git a/docs/site/src/content/docs/release-readiness.md b/docs/site/src/content/docs/release-readiness.md index a31eba8..e8bf7dd 100644 --- a/docs/site/src/content/docs/release-readiness.md +++ b/docs/site/src/content/docs/release-readiness.md @@ -31,8 +31,9 @@ status that can apply to a pack at any level. - **Promise:** Stable enough for a customer to deploy in their own environment with engineering support. APIs and values may still change between releases. - **Pre-sales behavior:** Can demo without caveat. Customer pilots may be offered with engineering involvement. -### GA (v1.0+) +### GA (`1.0.0` and above) - **Audience:** Production customers. +- **Versioning:** Experimental, Alpha, and Beta sit on the `0.x` line. GA means `1.0.0` or above, per the version tagging convention. - **Promise:** Fully supported. Documented upgrade path between releases. We own the bug-fix and security-fix story. - **Pre-sales behavior:** Pitch freely. @@ -67,7 +68,8 @@ Key fields the checklist depends on: - `owner` - accountable engineer's GitHub username - `product_owner` - required when `level: ga` - `deprecated` + `sunset_date` - see Deprecated status above -- `nebariapp_integration` - `none` | `partial` | `full` | `na` +- `nebariapp_integration` - `none` | `partial` | `full` | `na`, measured against the [Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md) +- `target_pack_spec_version` - the specification version the pack was built against - `scope.standalone-supported` - `yes` | `no` - `last_promoted_at` / `last_promoted_pr` - updated on every promotion - `demo_notes` - current known gotchas, surfaced in the dashboard Notes column (first ~100 chars) @@ -181,6 +183,8 @@ promotion purposes, but this should be resolved before the next promotion attemp - `[A]` `NebariApp` reaches Ready condition with all applicable sub-conditions healthy (RoutingReady, TLSReady, AuthReady) - `[A]` All configurable NebariApp fields used by the pack are documented in the pack's values reference - `[A]` `nebariapp_integration` field in `pack-metadata.yaml` accurately reflects the integration depth (`none` | `partial` | `full` | `na`) +- `[A]` Pack satisfies every MUST in the [Pack Specification](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md), which is the contract these checks are measured against +- `[B]` `target_pack_spec_version` in `pack-metadata.yaml` names the specification version the pack was verified against - `[B]` Auth-protected routes reject unauthenticated requests (if auth enabled) - `[B]` Auth-protected routes allow authenticated users with correct group membership (if auth enabled) - `[B]` Health/readiness probes configured and verified @@ -207,6 +211,9 @@ promotion purposes, but this should be resolved before the next promotion attemp - `[GA]` Example dashboard or Grafana panel definition for the LGTM stack (if applicable) ### Security + +These are the [security baseline](https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md#6-security-baseline), which the Pack Specification owns. It is repeated here because this checklist is what a promotion PR is reviewed against; the specification is authoritative if the two ever disagree. + - `[B]` Containers do not run as root (or have documented justification if they must) - `[B]` No secrets hardcoded in templates or default values - `[B]` OIDC scopes minimally scoped to what the app needs @@ -230,8 +237,10 @@ promotion purposes, but this should be resolved before the next promotion attemp - `[GA]` Pre-sales engineer has verified the demo flow on the GA release commit after release ### Sign-off + +These roles are operational, not governance roles. The project governance does not define or appoint them; this checklist is the authority on who signs off on what, so the two cannot drift. Pre-sales is not a sign-off role: it is a commercial function, and demo readiness is tracked separately under Pre-sales Verification. + - `[A]` Pack owner approves the promotion PR -- `[A]` Pre-sales rep approves the promotion PR - `[B]` Tech lead approves the promotion PR - `[GA]` Product owner has documented and verified acceptance criteria - `[GA]` Product owner approves the promotion PR diff --git a/pack-metadata.yaml b/pack-metadata.yaml new file mode 100644 index 0000000..a4286e4 --- /dev/null +++ b/pack-metadata.yaml @@ -0,0 +1,48 @@ +# pack-metadata.yaml +# +# Declares this pack's maturity, ownership, and which version of the platform +# contract it targets. The pack dashboard reads it hourly: +# https://github.com/nebari-dev/software-pack-dashboard +# +# Replace every placeholder below before using this template for a real pack. +# The schema and a fully commented example are at: +# https://github.com/nebari-dev/software-pack-dashboard/tree/main/schema +# +# Validate before committing: +# pip install check-jsonschema +# check-jsonschema \ +# --schemafile https://raw.githubusercontent.com/nebari-dev/software-pack-dashboard/main/schema/pack-metadata.schema.json \ +# pack-metadata.yaml + +# Must equal the GitHub repository name exactly. +name: your-pack-name + +# Human-readable name, shown on the dashboard. +display_name: Your Pack + +# experimental | alpha | beta | ga +# Start at experimental. Promotion is gated by docs/release-readiness-checklist.md +# and is a deliberate PR, not something that drifts upward on its own. +level: experimental + +# GitHub username of the single most accountable engineer, no "@". +# Keep this consistent with MAINTAINERS.md. +owner: your-handle + +deprecated: false + +# Required once level is ga. Null is fine before that. +product_owner: null + +# full | partial | none | na +nebariapp_integration: full + +# Which version of the Nebari Pack Specification this pack was built against: +# https://github.com/nebari-dev/nebari-operator/blob/main/docs/pack-specification.md +# Recording it means a Macro release of the specification shows up as work this +# pack owes, instead of as a surprise during a platform upgrade. +target_pack_spec_version: "0.1.0" + +# Whether the pack installs without the Nebari Operator, as a plain Helm chart. +scope: + standalone-supported: no