From 828891448ed2f8c891562ae9d3563639f692c6af Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:06 +0200 Subject: [PATCH 1/7] ci: pin actions and tools to exact versions, drop checkout credentials, add zizmor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every third-party action in ci.yml and drivers.yml now references the commit SHA the current tag resolves to (with the version as a trailing comment so dependabot's github-actions ecosystem keeps it current): actions/checkout v7.0.1, actions/setup-go v7.0.0, golangci/golangci-lint-action v9.3.0. A floating major tag can be moved by anyone with push access to the action repository; a SHA cannot. actions/checkout gets `persist-credentials: false` in every job — none of them pushes or uses the token after checkout, so the job token no longer sits in .git/config where any later step (or a compromised dependency) could read it. Tool installs are pinned too: mage v1.17.2 and actionlint v1.7.12 instead of @latest, so a new upstream release cannot turn main red on its own. govulncheck stays @latest on purpose — its vulnerability database is fetched at runtime, the binary version is not the freshness that matters. A zizmor step runs next to actionlint (pipx, exact version 1.30.0). actionlint checks workflow syntax; zizmor checks security posture — unpinned actions, persisted credentials, template injection, excessive permissions. It only needs the ephemeral read-only job token for its online audits, no repository secrets. Workflow semantics are otherwise unchanged. org hardening review 2026-09-06 --- .github/ISSUE_TEMPLATE/bug_report.md | 26 ---------- .github/ISSUE_TEMPLATE/feature_request.md | 16 ------ .github/workflows/ci.yml | 62 +++++++++++++++-------- .github/workflows/drivers.yml | 42 ++++++++++----- 4 files changed, 70 insertions(+), 76 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md 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/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/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 From ccf28debd24877a5aeb86d695ef41f11faacf7d6 Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:06 +0200 Subject: [PATCH 2/7] ci(release): SHA-pin actions, least-privilege token, env-scoped tag name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same SHA pins as ci.yml (checkout v7.0.1, setup-go v7.0.0). The workflow granted `contents: write` to every job; only tag-submodules pushes tags. The top level is now `contents: read` and the write grant moves onto that single job, so a compromise of the proxy-notify or validate steps cannot push to the repository. `${{ github.event.release.tag_name }}` was spliced directly into six `run:` scripts. It is now passed through step `env:` and read as a plain shell variable — identical behaviour for every valid tag, but a crafted tag name can no longer become shell code (zizmor template-injection). notify-proxy's setup-go gets `cache: false`: the job only runs `go list -m` against the proxy and needs no module cache, and a cache restored into a release-triggered job is a poisoning vector. notify-proxy's checkout gets `persist-credentials: false`; tag-submodules keeps the default because it pushes (explicit zizmor ignore with the reason on the step). The reusable-workflow call keeps the `./` form because actionlint 1.7.12 does not yet accept GitHub's `$/` syntax. org hardening review 2026-09-06 --- .github/workflows/release.yml | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) 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" From 881095a9c46a34695643dbd6dab2a1a7816d8940 Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:06 +0200 Subject: [PATCH 3/7] ci: add OpenSSF Scorecard workflow Runs ossf/scorecard-action (v2.4.4, SHA-pinned) on push to main, weekly, and whenever branch protection changes; publishes results to the Scorecard API and uploads SARIF to code scanning via github/codeql-action/upload-sarif (v4.37.9, SHA-pinned). Top-level permissions are read-all; the single job adds only security-events: write (SARIF upload) and id-token: write (OIDC for publish_results). Checkout does not persist credentials. Scorecard gives a continuous, public measurement of the supply-chain posture the rest of this review hardens (pinned dependencies, token permissions, branch protection, dangerous workflow patterns). org hardening review 2026-09-06 --- .github/workflows/scorecard.yml | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/scorecard.yml 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 From 8843255f30b5f3a6568612b4705be884c7085b05 Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:06 +0200 Subject: [PATCH 4/7] docs: add GOVERNANCE.md, MAINTAINERS.md and CODEOWNERS Write down how the project is actually run so contributors do not have to infer it: Contributor (fork PRs) -> member of the org team `contributors` (write on celeris only; may approve; may merge own PRs only after a code-owner approval and green required checks; ~3 merged non-trivial PRs + sustained engagement) -> Maintainer (admin, cuts releases, owns CODEOWNERS; currently FumingPower3925). The merge rule is stated once: required checks green + approval from a code owner; the author with write access or the approving maintainer (auto-merge) merges; nobody merges their own PR without a code-owner approval; the admin bypass is for release/infra emergencies and is visible in the audit log. Decisions are the single maintainer's today, lazy consensus (72 h) once there is more than one. Releases are tagged after the probatorium nightly and weekend soak pass; release notes come from PR labels; GitHub Releases is the changelog (no CHANGELOG.md). CODEOWNERS routes every PR to @FumingPower3925 and shows how to delegate an area (commented example). MAINTAINERS.md lists the maintainer and the `contributors` team (WdnLiu) and links to the criteria. org hardening review 2026-09-06 --- .github/CODEOWNERS | 14 +++++++ GOVERNANCE.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++ MAINTAINERS.md | 35 +++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 GOVERNANCE.md create mode 100644 MAINTAINERS.md 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/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. From 4bee6af6ed85ea895a0e0807b9d15464e8c067aa Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:07 +0200 Subject: [PATCH 5/7] docs(contributing): document merge rule, labels/release notes and DCO sign-off Mirror the governance merge rule in the place contributors actually read; tell them which label to put on a PR (bug / enhancement / performance / security / breaking / dependencies) now that release notes are generated from labels and there is no CHANGELOG.md; recommend `git commit -s` (DCO) without making it mandatory yet; point the security paragraph at private vulnerability reporting; link GOVERNANCE.md and MAINTAINERS.md. Everything else is unchanged. org hardening review 2026-09-06 --- CONTRIBUTING.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) 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 From 2b42f9fc909fc049a957c9a7a4f3635a616dc4fc Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:07 +0200 Subject: [PATCH 6/7] docs(security): prefer private vulnerability reporting, 72 h acknowledgement Private vulnerability reporting is enabled on the repository, so the Security tab -> "Report a vulnerability" flow becomes the preferred channel (report, advisory, CVE and credit all in one place, visible only to maintainers); security@goceleris.dev stays as the alternative. The acknowledgement window is stated as 72 hours, which is what a single-maintainer project can actually promise. Supported-versions table and per-release notes are kept as they were. org hardening review 2026-09-06 --- SECURITY.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) 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 From 51a5e124bcd64a4ba08a81215af09e90049c37bd Mon Sep 17 00:00:00 2001 From: Albert Bausili Date: Sun, 6 Sep 2026 00:47:07 +0200 Subject: [PATCH 7/7] chore(github): issue forms, PR template checklist and release-notes config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the markdown issue templates with issue forms. The bug form requires engine (std / epoll / io_uring / adaptive), architecture (amd64 / arm64 / other), celeris version and a Go reproduction, and asks for OS/kernel and expected-vs-actual — the fields that decide whether an engine bug can be reproduced at all. Both forms apply `needs-triage`. config.yml disables blank issues and routes security reports to the private advisory form instead of a public issue. The PR template gains "Closes #", an engine x architecture "Tested on" line, a breaking-change checkbox and a "labeled for release notes" checkbox, matching the label-driven release notes. .github/release.yml defines the generated release-notes sections (Breaking changes / Security / Fixes / Performance / Features / Other) and excludes dependabot's `dependencies` and `github_actions` labels. GitHub Releases is the changelog; there is no CHANGELOG.md. org hardening review 2026-09-06 --- .github/ISSUE_TEMPLATE/bug_report.yml | 65 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 29 ++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 9 +++ .github/release.yml | 30 ++++++++++ 5 files changed, 138 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/release.yml 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.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: + - "*"