diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b5730d98 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,14 @@ +# Code owners for goceleris/celeris. +# +# Every pull request needs an approving review from a code owner of the +# files it touches before it can merge (see GOVERNANCE.md, "How changes +# get merged"). The last matching pattern wins, so keep the catch-all +# first and add narrower delegations below it. +# +# Syntax: https://docs.github.com/articles/about-code-owners + +* @FumingPower3925 + +# Area delegation example — uncomment and adjust when a contributor +# takes ownership of a subtree: +# /middleware/ @FumingPower3925 @WdnLiu diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 34ac65dc..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -name: Bug Report -about: Report a bug in celeris -title: '' -labels: bug -assignees: '' ---- - -**Describe the bug** -A clear description of the bug. - -**To Reproduce** -Steps or minimal code to reproduce: - -```go -// your code here -``` - -**Expected behavior** -What you expected to happen. - -**Environment** -- OS: [e.g., Ubuntu 24.04, macOS 15] -- Go version: [e.g., 1.26] -- Celeris version: [e.g., v1.0.0] -- Engine: [e.g., IOUring, Epoll, Std] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..474cc4ee --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,65 @@ +name: Bug report +description: Report a bug in celeris +title: "[bug]: " +labels: ["bug", "needs-triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug. Please fill in the + environment fields — engine and architecture matter a lot for + celeris, since the io_uring, epoll and std engines take different + code paths. + + **Security vulnerabilities must not be reported here.** Use the + repository's Security tab → "Report a vulnerability" instead (see + [SECURITY.md](../blob/main/SECURITY.md)). + - type: dropdown + id: engine + attributes: + label: Engine + description: Which engine were you running when the bug occurred? + options: + - std + - epoll + - io_uring + - adaptive + validations: + required: true + - type: dropdown + id: arch + attributes: + label: Architecture + options: + - amd64 + - arm64 + - other + validations: + required: true + - type: input + id: version + attributes: + label: celeris version + description: Output of `go list -m github.com/goceleris/celeris`, or the commit SHA. + placeholder: v1.6.0 + validations: + required: true + - type: input + id: os + attributes: + label: OS / kernel + description: Distribution and kernel version (`uname -sr`). Kernel matters for io_uring. + placeholder: Ubuntu 24.04, Linux 6.8.0 + - type: textarea + id: repro + attributes: + label: Minimal reproduction + description: A self-contained Go program (or test) that reproduces the problem. The smaller, the faster we can fix it. + render: go + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected vs actual + description: What did you expect to happen, and what happened instead? Include logs, panics or `-race` output if you have them. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..a6a91309 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/goceleris/celeris/security/advisories/new + about: Report a vulnerability privately. Never open a public issue for security problems. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 330b626c..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: Feature Request -about: Suggest a new feature -title: '' -labels: enhancement -assignees: '' ---- - -**Problem** -What problem does this feature solve? - -**Proposed Solution** -Describe your proposed API or behavior. - -**Alternatives Considered** -Any alternative approaches you've considered. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..faaa6c57 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,29 @@ +name: Feature request +description: Suggest a new feature or an improvement +title: "[feature]: " +labels: ["enhancement", "needs-triage"] +body: + - type: markdown + attributes: + value: | + Large or breaking proposals are best discussed here before any + code is written (see [GOVERNANCE.md](../blob/main/GOVERNANCE.md)). + - type: textarea + id: problem + attributes: + label: Problem + description: What problem does this feature solve? Who hits it, and how often? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposal + description: Describe the API or behaviour you have in mind. Sketches of Go code are welcome. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives + description: Other approaches you considered, including "do nothing", and why they fall short. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0b7ef5f1..ef389ece 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,8 @@ Brief description of the changes. +Closes # + ## Changes - @@ -11,3 +13,10 @@ Brief description of the changes. - [ ] Unit tests added/updated - [ ] `mage check` passes - [ ] Tested on Linux (if engine changes) + +Tested on: [ ] std [ ] epoll [ ] io_uring — [ ] amd64 [ ] arm64 + +## Release notes + +- [ ] Breaking change? (label `breaking`) +- [ ] Labeled for release notes (`bug` / `enhancement` / `performance` / `security` / `breaking` / `dependencies`) diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 00000000..a8089c0e --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,30 @@ +# Automatically generated release notes (GitHub Releases is the +# changelog — there is no CHANGELOG.md). PRs are grouped by label; label +# every PR with exactly one of the category labels below so it lands in +# the right section. Dependency bumps are excluded from the notes. +# +# https://docs.github.com/repositories/releasing-projects-on-github/automatically-generated-release-notes +changelog: + exclude: + labels: + - dependencies + - github_actions + categories: + - title: Breaking changes + labels: + - breaking + - title: Security + labels: + - security + - title: Fixes + labels: + - bug + - title: Performance + labels: + - performance + - title: Features + labels: + - enhancement + - title: Other + labels: + - "*" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92447175..fe905522 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,8 +24,10 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" # Magefiles carry `//go:build mage`, so `go vet ./...`, `go build` and @@ -33,49 +35,61 @@ jobs: # broken magefile can reach main green. Compile them here. - name: Install mage run: | - go install github.com/magefile/mage@latest + go install github.com/magefile/mage@v1.17.2 echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" - name: mage compiles run: mage -compile /tmp/mage-compile-check - name: Lint root module - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: version: v2.13 - name: Lint middleware/compress - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: version: v2.13 working-directory: middleware/compress - name: Lint middleware/metrics - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: version: v2.13 working-directory: middleware/metrics - name: Lint middleware/otel - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: version: v2.13 working-directory: middleware/otel - name: Lint middleware/protobuf - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: version: v2.13 working-directory: middleware/protobuf - name: actionlint # Workflow-YAML lint: catches script-injection vectors, unknown # runner labels, malformed shell, action input misuse — the - # whole class golangci-lint can't see. + # whole class golangci-lint can't see. Pinned to an exact version + # so a new actionlint release cannot turn main red on its own. run: | - go install github.com/rhysd/actionlint/cmd/actionlint@latest + go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12 actionlint -color + - name: zizmor + # Workflow security audit (unpinned actions, persisted credentials, + # template injection, excessive permissions). Complements + # actionlint, which checks syntax rather than security posture. + # Needs only the ephemeral job token (read) for the online audits; + # no repository secrets. Pinned to an exact version. + env: + GH_TOKEN: ${{ github.token }} + run: pipx run --spec zizmor==1.30.0 zizmor --color always .github/workflows unit: name: Unit (root + middleware sub-modules) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" # Excludes ./test/... to keep this job deterministic — those @@ -117,8 +131,10 @@ jobs: name: Conformance runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Conformance matrix (engines × protocols) @@ -154,8 +170,10 @@ jobs: CELERIS_PG_DSN: postgres://celeris:celeris@127.0.0.1:5432/celeristest?sslmode=disable CELERIS_REDIS_ADDR: 127.0.0.1:6379 steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Postgres conformance @@ -182,8 +200,10 @@ jobs: matrix: os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Build root module @@ -205,8 +225,10 @@ jobs: name: Vulnerability Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Install govulncheck diff --git a/.github/workflows/drivers.yml b/.github/workflows/drivers.yml index 59ce3108..4565cd01 100644 --- a/.github/workflows/drivers.yml +++ b/.github/workflows/drivers.yml @@ -91,8 +91,10 @@ jobs: env: CELERIS_PG_DSN: postgres://celeris:celeris@127.0.0.1:5432/celeristest?sslmode=disable steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Conformance @@ -132,8 +134,10 @@ jobs: env: CELERIS_REDIS_ADDR: 127.0.0.1:6379 steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Conformance @@ -173,8 +177,10 @@ jobs: env: CELERIS_REDIS_ADDR: 127.0.0.1:6379 steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Conformance (Redis driver against Valkey) @@ -210,8 +216,10 @@ jobs: env: CELERIS_MEMCACHED_ADDR: 127.0.0.1:11211 steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Conformance @@ -263,8 +271,10 @@ jobs: --health-timeout 5s --health-retries 10 steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Cluster conformance @@ -296,8 +306,10 @@ jobs: REDIS_IMAGE: redis:${{ matrix.redis }} CELERIS_REDIS_CLUSTER_ADDRS: "127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002" steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Start cluster @@ -382,8 +394,10 @@ jobs: CELERIS_REDIS_SENTINEL_ADDRS: "127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381" CELERIS_REDIS_SENTINEL_MASTER: mymaster steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" - name: Start sentinel stack diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ae41f94..f84df2e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,7 @@ on: types: [published] permissions: - contents: write + contents: read jobs: validate-tag: @@ -13,8 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check semver format + env: + TAG: ${{ github.event.release.tag_name }} run: | - TAG="${{ github.event.release.tag_name }}" if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|rc)\.[0-9]+)?$ ]]; then echo "::error::Tag '$TAG' is not valid semver (expected vX.Y.Z or vX.Y.Z-beta.N)" exit 1 @@ -24,19 +25,24 @@ jobs: ci: name: CI needs: validate-tag - uses: ./.github/workflows/ci.yml + uses: ./.github/workflows/ci.yml # zizmor: ignore[self-repository] -- actionlint 1.7.12 rejects the `$/` form tag-submodules: name: Tag Sub-Modules needs: [validate-tag, ci] runs-on: ubuntu-latest + # The only job that writes to the repository (pushes sub-module tags). + permissions: + contents: write steps: - - uses: actions/checkout@v7 - with: + # Keeps the job token: this is the one step that pushes (sub-module tags). + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: # zizmor: ignore[artipacked] fetch-depth: 0 - name: Create sub-module tags + env: + VERSION: ${{ github.event.release.tag_name }} run: | - VERSION="${{ github.event.release.tag_name }}" SUBMODULES="middleware/compress middleware/metrics middleware/otel middleware/protobuf" for sub in $SUBMODULES; do TAG="${sub}/${VERSION}" @@ -49,8 +55,9 @@ jobs: done git push origin --tags - name: Update sub-module go.mod versions + env: + VERSION: ${{ github.event.release.tag_name }} run: | - VERSION="${{ github.event.release.tag_name }}" SUBMODULES="middleware/compress middleware/metrics middleware/otel middleware/protobuf" for sub in $SUBMODULES; do GOMOD="${sub}/go.mod" @@ -70,13 +77,17 @@ jobs: needs: [validate-tag, ci, tag-submodules] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: actions/setup-go@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "1.27.0" + cache: false - name: Request root module from proxy + env: + VERSION: ${{ github.event.release.tag_name }} run: | - VERSION="${{ github.event.release.tag_name }}" MODULE="github.com/goceleris/celeris" echo "Notifying proxy for ${MODULE}@${VERSION}..." for attempt in 1 2 3; do @@ -89,8 +100,9 @@ jobs: sleep 10 done - name: Request sub-module versions from proxy + env: + VERSION: ${{ github.event.release.tag_name }} run: | - VERSION="${{ github.event.release.tag_name }}" SUBMODULES="middleware/compress middleware/metrics middleware/otel middleware/protobuf" for sub in $SUBMODULES; do MODULE="github.com/goceleris/celeris/${sub}" @@ -106,8 +118,9 @@ jobs: done done - name: Verify module availability + env: + VERSION: ${{ github.event.release.tag_name }} run: | - VERSION="${{ github.event.release.tag_name }}" go list -m "github.com/goceleris/celeris@${VERSION}" || echo "Root module not yet indexed" go list -m "github.com/goceleris/celeris/middleware/compress@${VERSION}" || echo "compress sub-module not yet indexed" go list -m "github.com/goceleris/celeris/middleware/metrics@${VERSION}" || echo "metrics sub-module not yet indexed" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..4503b56b --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,50 @@ +# OpenSSF Scorecard — automated supply-chain posture checks (branch +# protection, pinned dependencies, token permissions, dangerous workflow +# patterns, SAST, ...). Results are published to the public Scorecard API +# and uploaded to the repository's code-scanning dashboard. +# +# https://github.com/ossf/scorecard-action +name: Scorecard + +on: + # Re-score when branch protection / rulesets change. + branch_protection_rule: + # Weekly, Monday 06:23 UTC (off the hour to avoid the top-of-hour rush). + schedule: + - cron: "23 6 * * 1" + push: + branches: [main] + +# Default to read-only; the single job opts in to exactly what it needs. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Upload the SARIF results to code scanning. + security-events: write + # Publish results to the OpenSSF Scorecard API (OIDC). + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 + with: + results_file: results.sarif + results_format: sarif + # Publish to the Scorecard API so the badge and the public + # scorecard.dev page for the repo stay current. Requires the + # id-token: write permission above. + publish_results: true + + - name: Upload SARIF to code scanning + uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9 + with: + sarif_file: results.sarif diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 725b3238..c789a02a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -111,6 +111,51 @@ mage -l # List all available targets - Write clear commit messages following the `type: description` format (e.g., `feat:`, `fix:`, `perf:`, `security:`, `test:`, `chore:`) - Security-sensitive changes should note the CWE number in the commit message +### How changes get merged + +The full rule lives in [GOVERNANCE.md](GOVERNANCE.md); the short version: + +- Every change to `main` goes through a pull request — maintainers included. +- A PR merges when **all required checks are green** and it has an + **approving review from a code owner** of the files it touches + ([`.github/CODEOWNERS`](.github/CODEOWNERS)). +- The author merges if they have write access (a member of the + `contributors` team or a maintainer); otherwise the approving maintainer + merges, usually via auto-merge. +- **Nobody merges their own PR without a code-owner approval.** The + maintainer's admin bypass is reserved for release/infra emergencies and + is visible in the audit log. + +Who the maintainers and `contributors` members are, and how to become one, +is in [MAINTAINERS.md](MAINTAINERS.md). + +### Labels and release notes + +Release notes are **generated from PR labels** (see +[`.github/release.yml`](.github/release.yml)); GitHub Releases is the +changelog and there is **no `CHANGELOG.md`**. Label every PR with the +category it belongs to so it lands in the right section: + +| Label | Release-notes section | +|----------------|-----------------------| +| `breaking` | Breaking changes | +| `security` | Security | +| `bug` | Fixes | +| `performance` | Performance | +| `enhancement` | Features | +| `dependencies` | excluded (dependabot) | + +Anything else lands under "Other". If a change is breaking, label it +`breaking` *and* say so in the PR description. + +### Commit sign-off + +We recommend signing off your commits with `git commit -s`, which adds a +`Signed-off-by:` trailer certifying the +[Developer Certificate of Origin](https://developercertificate.org/). It is +not mandatory yet, but it may become a required check in the future, so +getting into the habit now costs nothing. + ## Code Style - Follow standard Go conventions @@ -131,6 +176,15 @@ mage -l # List all available targets ## Reporting Issues -Use GitHub Issues with the provided templates for bug reports and feature requests. +Use GitHub Issues with the provided forms for bug reports and feature +requests. Bug reports ask for the engine (std / epoll / io_uring / +adaptive), the architecture and a minimal reproduction — please fill them +in, they decide how fast the bug gets fixed. + +For security vulnerabilities, **do not open an issue**: use the Security +tab → "Report a vulnerability" as described in [SECURITY.md](SECURITY.md). + +## Project governance -For security vulnerabilities, see [SECURITY.md](SECURITY.md). +- [GOVERNANCE.md](GOVERNANCE.md) — roles, merge rule, decisions, releases +- [MAINTAINERS.md](MAINTAINERS.md) — who maintains celeris and how to join diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 00000000..3d09a4e2 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,96 @@ +# Governance + +This document describes how the celeris project is run: who holds which +role, how a change gets merged, how decisions are made, and how releases +are cut. It is deliberately short; when it and reality disagree, fix the +document. + +## Roles + +### Contributor + +Anyone who opens a pull request from a fork. No special access is needed. +Contributors get the same CI, the same review, and the same merge rule as +everybody else. + +### Member of the `contributors` team + +Members of the GitHub org team **`contributors`** have *write* access to +`goceleris/celeris` only (not to the other org repositories). A member: + +- can push branches to this repository and open PRs from them; +- can **approve** pull requests; +- may **merge their own PR only after a code-owner approval** and green + required checks (see [How changes get merged](#how-changes-get-merged)). + +Criteria for an invitation: about **three merged, non-trivial pull +requests** and sustained engagement (reviews, issue triage, follow-through +on feedback). A maintainer sends the invitation; there is no application +form — ask in an issue or a PR thread if you think you qualify. + +### Maintainer + +Maintainers have *admin* access. They cut releases, own +[`.github/CODEOWNERS`](.github/CODEOWNERS), manage the `contributors` team, +and are the final reviewers for the areas they own. The current maintainer +is **@FumingPower3925** (see [MAINTAINERS.md](MAINTAINERS.md)). + +## How changes get merged + +Every change to `main` goes through a pull request, including changes by +maintainers. A PR merges when **both** hold: + +1. all **required checks are green**, and +2. it has an **approving review from a code owner** of the files it + touches (CODEOWNERS is the source of truth). + +Who presses the button: + +- the **author**, if they have write access (a `contributors` member or a + maintainer), or +- the **approving maintainer**, typically by enabling auto-merge so the PR + lands as soon as checks pass. + +**Nobody merges their own PR without a code-owner approval.** The +maintainer's admin **bypass** of branch protection is reserved for +release and infrastructure emergencies (a broken release workflow, a +stuck required check, a security fix that must land before CI recovers). +Every bypass is visible in the repository audit log and should be +followed by a normal PR that explains it. + +## Decisions + +Today there is a **single maintainer**, so day-to-day decisions are theirs, +made in the open on issues and PRs. Once there is **more than one +maintainer**, decisions move to **lazy consensus**: a proposal (issue or +PR) that receives no objection from a maintainer within **72 hours** is +accepted. An objection blocks until resolved by discussion; if maintainers +cannot agree, the proposal is dropped rather than forced. + +Large or breaking changes should start as an issue before code is written +so the design can be discussed without a diff attached. + +## Releases + +- The maintainer tags **`vX.Y.Z`** on `main` after the + [goceleris/probatorium](https://github.com/goceleris/probatorium) + **nightly** validation matrix and the **weekend soak** have passed on + the release candidate. A release that has not been through both is not + cut. +- Sub-module tags (`middleware//vX.Y.Z`) are created automatically + by the release workflow. +- **Release notes are generated from PR labels** (`breaking`, `security`, + `bug`, `performance`, `enhancement`; see + [`.github/release.yml`](.github/release.yml)) plus hand-written + highlights at the top. Label your PR correctly and it will appear in the + right section. +- **GitHub Releases is the changelog.** There is no `CHANGELOG.md`, and + none should be added. +- Security fixes follow [SECURITY.md](SECURITY.md); a fix may ship as a + patch release outside the normal cadence. + +## Changing this document + +Governance changes go through a PR like any other change, reviewed by a +maintainer. Once there is more than one maintainer they require lazy +consensus as described above. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 00000000..dcc150ff --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,35 @@ +# Maintainers + +The people who keep celeris moving. Roles and the rules they follow are +defined in [GOVERNANCE.md](GOVERNANCE.md). + +## Maintainers + +Admin access; cut releases; own [`.github/CODEOWNERS`](.github/CODEOWNERS). + +| GitHub | Areas | Since | +|------------------|-------|-------| +| @FumingPower3925 | all | 2026 | + +## `contributors` team + +Write access to `goceleris/celeris` only. Members may approve PRs and merge +their own PRs after a code-owner approval and green required checks. + +| GitHub | Focus | +|---------|-------| +| @WdnLiu | general | + +## How to become one + +- **`contributors` team**: about three merged, non-trivial pull requests + plus sustained engagement (reviews, triage, follow-through). A + maintainer sends the invitation — say so on an issue or PR if you think + you qualify. Details in + [GOVERNANCE.md → Roles](GOVERNANCE.md#roles). +- **Maintainer**: by invitation from the existing maintainers, after a + sustained record as a `contributors` member and ownership of an area in + CODEOWNERS. + +Keep this file in sync with the org team membership and CODEOWNERS when +either changes. diff --git a/SECURITY.md b/SECURITY.md index 0b103a0f..ce4f3042 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -216,14 +216,25 @@ If you discover a security vulnerability in celeris, please report it responsibl **Do not open a public GitHub issue for security vulnerabilities.** -Instead, please email security@goceleris.dev with: +Preferred channel — **private vulnerability reporting** (enabled on this +repository): open the repository's **Security** tab and choose +**"Report a vulnerability"**, or go directly to +. The report +is visible only to the maintainers, and the resulting advisory, CVE and +credit are handled in the same place. + +Alternative channel: email **security@goceleris.dev**. + +Either way, please include: - A description of the vulnerability -- Steps to reproduce -- Potential impact +- Steps to reproduce (a minimal Go program is ideal) +- Potential impact and the engine(s) affected (std / epoll / io_uring / adaptive) - Suggested fix (if any) -We will acknowledge receipt within 48 hours and aim to provide a fix within 7 days for critical issues. +We will **acknowledge receipt within 72 hours** and aim to provide a fix +within 7 days for critical issues. Fixes ship as a patch release of the +supported line and are announced through a GitHub Security Advisory. ## Scope