From eb47716cefb91c56b64fbe68f53e1d4f259bf7c3 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 30 Sep 2026 05:48:10 +0800 Subject: [PATCH 1/2] chore: align project metadata with Apache Reqsign --- .asf.yaml | 10 +-- .github/scripts/release_rust/README.md | 10 +-- .github/scripts/release_rust/bootstrap.py | 17 +++-- .../scripts/release_rust/test_bootstrap.py | 49 +++++++++---- .github/workflows/discussion-thread-link.yml | 2 +- AGENTS.md | 2 +- NOTICE | 2 +- README.md | 4 +- SECURITY.md | 4 +- THREAT_MODEL.md | 10 +-- release/SKILL.md | 68 ++++++++++++------- reqsign/README.md | 2 +- 12 files changed, 114 insertions(+), 66 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index 20b5d5cd..bceb564d 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -18,7 +18,7 @@ # All configurations could be found here: https://github.com/apache/infrastructure-asfyaml/ github: - description: "Signing HTTP requests without heavy SDKs." + description: "Apache Reqsign: Signing HTTP requests without heavy SDKs." homepage: https://docs.rs/reqsign labels: - rust @@ -87,7 +87,7 @@ github: restrict_deletion: true restrict_force_push: true notifications: - commits: commits@opendal.apache.org - issues: commits@opendal.apache.org - pullrequests: commits@opendal.apache.org - discussions: dev@opendal.apache.org + commits: dev@reqsign.apache.org + issues: dev@reqsign.apache.org + pullrequests: dev@reqsign.apache.org + discussions: dev@reqsign.apache.org diff --git a/.github/scripts/release_rust/README.md b/.github/scripts/release_rust/README.md index 56ee1e09..4a751382 100644 --- a/.github/scripts/release_rust/README.md +++ b/.github/scripts/release_rust/README.md @@ -1,7 +1,6 @@ # Rust release helpers -These scripts define and publish the crates.io package set for Apache OpenDAL -reqsign. +These scripts define and publish the crates.io package set for Apache Reqsign. ## Publish plan @@ -49,9 +48,10 @@ including when discovery finds no missing names. It never changes an established crate. Existing crates must be migrated independently before the workflow can succeed. -Published crate metadata may still reference the former repository URL. The -audit accepts that historical metadata, but every Trusted Publisher must target -`apache/reqsign`. New placeholders and releases use the current repository URL. +Published crate metadata may still reference the former repository URL or the +former project name in a `0.0.0` placeholder description. The audit accepts that +historical metadata, but every Trusted Publisher must target `apache/reqsign`. +New placeholders and releases use the current project name and repository URL. Version `0.0.0` is an irreversible namespace reservation. It is not an ASF software release and contains no implementation. diff --git a/.github/scripts/release_rust/bootstrap.py b/.github/scripts/release_rust/bootstrap.py index af82370c..06e775c4 100644 --- a/.github/scripts/release_rust/bootstrap.py +++ b/.github/scripts/release_rust/bootstrap.py @@ -41,6 +41,10 @@ LEGACY_REPOSITORY = "https://github.com/apache/opendal-reqsign" PLACEHOLDER_VERSION = "0.0.0" PLACEHOLDER_DESCRIPTION = ( + "Namespace reservation for a crate planned by Apache Reqsign." +) +# Published placeholders retain their original description after a project rename. +LEGACY_PLACEHOLDER_DESCRIPTION = ( "Namespace reservation for a crate planned by Apache OpenDAL reqsign." ) PUBLISHER = { @@ -279,7 +283,10 @@ def validate_crate_metadata( ) if metadata.get("max_version") == PLACEHOLDER_VERSION: - if metadata.get("description") != PLACEHOLDER_DESCRIPTION: + if metadata.get("description") not in ( + PLACEHOLDER_DESCRIPTION, + LEGACY_PLACEHOLDER_DESCRIPTION, + ): raise RuntimeError( f"{planned.name} has an unexpected {PLACEHOLDER_VERSION} placeholder" ) @@ -416,11 +423,11 @@ def _placeholder_manifest(name: str) -> str: def _placeholder_readme(name: str) -> str: return f"""# {name} -This crate belongs to [Apache OpenDAL reqsign]({REPOSITORY}). +This crate belongs to [Apache Reqsign]({REPOSITORY}). -Version {PLACEHOLDER_VERSION} reserves the crates.io package name for Apache -OpenDAL reqsign. It is not an ASF software release, contains no implementation, -and must not be used as a dependency. +Version {PLACEHOLDER_VERSION} reserves the crates.io package name for Apache Reqsign. +It is not an ASF software release, contains no implementation, and must not be +used as a dependency. """ diff --git a/.github/scripts/release_rust/test_bootstrap.py b/.github/scripts/release_rust/test_bootstrap.py index bc4024ff..da8ac022 100644 --- a/.github/scripts/release_rust/test_bootstrap.py +++ b/.github/scripts/release_rust/test_bootstrap.py @@ -51,7 +51,7 @@ def metadata(name: str, *, version: str = "1.0.0", trustpub_only: bool = False): "description": ( PLACEHOLDER_DESCRIPTION if version == PLACEHOLDER_VERSION - else "An Apache OpenDAL reqsign crate" + else "An Apache Reqsign crate" ), "trustpub_only": trustpub_only, } @@ -418,25 +418,48 @@ def publish(project_dir, package, token): def test_partial_placeholder_resumes_without_republishing(self): planned = PlannedCrate("reqsign-new", "services/new") - client = FakeClient( - planned.name, - metadata(planned.name, version=PLACEHOLDER_VERSION), - ) + for description in ( + PLACEHOLDER_DESCRIPTION, + "Namespace reservation for a crate planned by Apache OpenDAL reqsign.", + ): + with self.subTest(description=description): + krate = metadata(planned.name, version=PLACEHOLDER_VERSION) + krate["description"] = description + client = FakeClient(planned.name, krate) + + with ( + tempfile.TemporaryDirectory() as tmpdir, + mock.patch("bootstrap.publish_placeholder") as publish, + ): + result = reconcile_crate( + Path(tmpdir), planned, client, "bootstrap-token" + ) + + publish.assert_not_called() + self.assertEqual( + result.actions, + ( + "configured Trusted Publishing", + "enabled Trusted Publishing only", + ), + ) + + def test_unrecognized_placeholder_is_not_reconciled(self): + planned = PlannedCrate("reqsign-new", "services/new") + krate = metadata(planned.name, version=PLACEHOLDER_VERSION) + krate["description"] = "Reserved by another project" + client = FakeClient(planned.name, krate) with ( tempfile.TemporaryDirectory() as tmpdir, mock.patch("bootstrap.publish_placeholder") as publish, + self.assertRaisesRegex(RuntimeError, "unexpected 0.0.0 placeholder"), ): - result = reconcile_crate(Path(tmpdir), planned, client, "bootstrap-token") + reconcile_crate(Path(tmpdir), planned, client, "bootstrap-token") publish.assert_not_called() - self.assertEqual( - result.actions, - ( - "configured Trusted Publishing", - "enabled Trusted Publishing only", - ), - ) + self.assertEqual(client.created_configs, 0) + self.assertEqual(client.restricted, 0) def test_ready_placeholder_is_a_noop(self): planned = PlannedCrate("reqsign-new", "services/new") diff --git a/.github/workflows/discussion-thread-link.yml b/.github/workflows/discussion-thread-link.yml index e1648774..b661328d 100644 --- a/.github/workflows/discussion-thread-link.yml +++ b/.github/workflows/discussion-thread-link.yml @@ -130,7 +130,7 @@ jobs: const stdout = await runAsfml([ 'search', - 'dev@opendal.apache.org', + 'dev@reqsign.apache.org', title, '--since', '7d', diff --git a/AGENTS.md b/AGENTS.md index 3221ef8c..af1ee053 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Project Overview -Apache OpenDAL reqsign — a Rust library for signing HTTP API requests across +Apache Reqsign — a Rust library for signing HTTP API requests across cloud providers (AWS, Azure, Google, Aliyun, Huawei, Tencent, Oracle, Volcengine). diff --git a/NOTICE b/NOTICE index 32dcf6d9..1c278c39 100644 --- a/NOTICE +++ b/NOTICE @@ -1,4 +1,4 @@ -Apache OpenDAL Reqsign +Apache Reqsign Copyright 2025-2026 The Apache Software Foundation This product includes software developed at diff --git a/README.md b/README.md index e065d486..66d716db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Apache OpenDAL Reqsign +# Apache Reqsign [![Build Status]][actions] [![Latest Version]][crates.io] [![Crate Downloads]][crates.io] @@ -185,6 +185,8 @@ Check out the [CONTRIBUTING.md](CONTRIBUTING.md) guide for more details on getti Submit [issues](https://github.com/apache/reqsign/issues/new/choose) for bug report or asking questions in [discussion](https://github.com/apache/reqsign/discussions/new?category=q-a). +Join the [development mailing list](mailto:dev@reqsign.apache.org) for project discussions and release votes. [Subscribe](mailto:dev-subscribe@reqsign.apache.org) before posting, or browse the [archives](https://lists.apache.org/list.html?dev@reqsign.apache.org). + ## Acknowledge Inspired a lot from: diff --git a/SECURITY.md b/SECURITY.md index e37b5433..0e63268c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -21,10 +21,10 @@ ## Reporting a Vulnerability -Apache OpenDAL Reqsign follows the +Apache Reqsign follows the [Apache Software Foundation security process](https://www.apache.org/security/). Please report suspected vulnerabilities privately to -`private@opendal.apache.org`. If you are unsure where to send the report, use +`private@reqsign.apache.org`. If you are unsure where to send the report, use the ASF Security Team address, `security@apache.org`. Do not open public GitHub issues or pull requests for security reports. diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md index 4507ac35..6f7311d4 100644 --- a/THREAT_MODEL.md +++ b/THREAT_MODEL.md @@ -17,11 +17,11 @@ under the License. --> -# Apache OpenDAL Reqsign Threat Model +# Apache Reqsign Threat Model ## 1. Status -This document defines the security boundary for Apache OpenDAL Reqsign. The +This document defines the security boundary for Apache Reqsign. The documentation is for maintainers, security reporters, downstream users, Apache OpenDAL integrators, direct `reqsign` users, and automated security scanners that need to decide whether a report describes a Reqsign vulnerability or a @@ -29,7 +29,7 @@ responsibility of the embedding application, a cloud provider, or a deployment. The canonical disclosure process is documented in [SECURITY.md](./SECURITY.md). Reports that may affect reqsign security should be sent privately to -`private@opendal.apache.org` before public disclosure. If you are unsure where +`private@reqsign.apache.org` before public disclosure. If you are unsure where to send the report, use `security@apache.org`. ## 2. Purpose @@ -587,8 +587,8 @@ We will revisit this threat model when any of the following changes: ## 10. Relationship To OpenDAL And Other Hosts -Reqsign is a sub-project related to Apache OpenDAL, and OpenDAL is the primary -integration this model expects maintainers to consider. Reqsign is still a +Apache Reqsign is an independent Apache top-level project. OpenDAL remains the +primary integration this model expects maintainers to consider. Reqsign is a reusable library: direct `reqsign` users and other embedding applications get the same Reqsign security properties and retain the same host-application responsibilities. diff --git a/release/SKILL.md b/release/SKILL.md index 43d9d014..5a7a55df 100644 --- a/release/SKILL.md +++ b/release/SKILL.md @@ -1,11 +1,11 @@ --- name: reqsign-release -description: Release Apache OpenDAL reqsign through the Apache RC, vote, dist, tag, crates.io, and announcement flow. +description: Release Apache Reqsign through the Apache RC, vote, dist, tag, crates.io, and announcement flow. --- -# Apache OpenDAL reqsign Release Skill +# Apache Reqsign Release Skill -Use this skill when preparing or executing an Apache OpenDAL reqsign release. +Use this skill when preparing or executing an Apache Reqsign release. ## Hard Rules @@ -15,12 +15,26 @@ Use this skill when preparing or executing an Apache OpenDAL reqsign release. - Every crate in the current publish plan must exist with the exact `apache/reqsign`, `release.yml`, `release` Trusted Publisher and `trustpub_only` enabled before creating the RC tag. - The repo release workflow publishes only formal `vX.Y.Z` tags. It uses short-lived GitHub OIDC credentials and never a long-lived crates.io token. - Source release artifacts live under Apache dist: - - RC: `https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z/` - - Final: `https://dist.apache.org/repos/dist/release/opendal/reqsign-X.Y.Z/` + - RC: `https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z/` + - Final: `https://dist.apache.org/repos/dist/release/reqsign/reqsign-X.Y.Z/` - If a wrong formal tag is pushed early, immediately cancel the Release workflow, delete the remote tag, and verify crates.io did not publish anything. ## Release Preparation +Before the first release as an independent project, confirm that ASF Infrastructure +has provisioned the Reqsign dev and release dist directories and that the Reqsign +`KEYS` file contains the release manager's signing key. Track the migration in +[INFRA-28423](https://issues.apache.org/jira/browse/INFRA-28423). Stop release +preparation if these resources are unavailable; do not upload a new Reqsign release +under OpenDAL. Historical releases remain in the +[OpenDAL archive](https://archive.apache.org/dist/opendal/). + +```bash +svn ls https://dist.apache.org/repos/dist/dev/reqsign/ +svn ls https://dist.apache.org/repos/dist/release/reqsign/ +svn cat https://dist.apache.org/repos/dist/release/reqsign/KEYS +``` + 1. Sync live state. ```bash @@ -28,8 +42,8 @@ Use this skill when preparing or executing an Apache OpenDAL reqsign release. git status --short --branch git tag --list 'vX.Y.Z*' --sort=version:refname git ls-remote --tags origin 'refs/tags/vX.Y.Z*' - svn ls https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z/ || true - svn ls https://dist.apache.org/repos/dist/release/opendal/reqsign-X.Y.Z/ || true + svn ls https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z/ || true + svn ls https://dist.apache.org/repos/dist/release/reqsign/reqsign-X.Y.Z/ || true ``` 2. Prepare version bump on a PR. @@ -147,10 +161,10 @@ shasum -a 512 -c apache-reqsign-X.Y.Z.tar.gz.sha512 tar -tzf apache-reqsign-X.Y.Z.tar.gz | rg '(^|/)LICENSE$|(^|/)NOTICE$|(^|/)Cargo.toml$' ``` -Confirm the signing key is present in Apache OpenDAL KEYS: +Confirm the signing key is present in Apache Reqsign KEYS: ```bash -svn cat https://dist.apache.org/repos/dist/release/opendal/KEYS | rg 'xuanwo@apache.org|Xuanwo|KEY_FINGERPRINT' +svn cat https://dist.apache.org/repos/dist/release/reqsign/KEYS | rg 'xuanwo@apache.org|Xuanwo|KEY_FINGERPRINT' ``` ## Upload RC Artifacts @@ -158,10 +172,10 @@ svn cat https://dist.apache.org/repos/dist/release/opendal/KEYS | rg 'xuanwo@apa Upload to Apache dev dist. ```bash -rm -rf /tmp/opendal-dist-dev-reqsign-X.Y.Z -svn co --depth=empty https://dist.apache.org/repos/dist/dev/opendal /tmp/opendal-dist-dev-reqsign-X.Y.Z +rm -rf /tmp/reqsign-dist-dev-X.Y.Z +svn co --depth=empty https://dist.apache.org/repos/dist/dev/reqsign /tmp/reqsign-dist-dev-X.Y.Z -cd /tmp/opendal-dist-dev-reqsign-X.Y.Z +cd /tmp/reqsign-dist-dev-X.Y.Z mkdir reqsign-X.Y.Z cp /tmp/reqsign-release-X.Y.Z/dist/* reqsign-X.Y.Z/ svn add reqsign-X.Y.Z @@ -172,9 +186,9 @@ svn commit --force-interactive -m "Prepare reqsign X.Y.Z release candidate" Verify the remote copy: ```bash -svn ls https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z/ +svn ls https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z/ rm -rf /tmp/reqsign-verify-X.Y.Z -svn co https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z /tmp/reqsign-verify-X.Y.Z +svn co https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z /tmp/reqsign-verify-X.Y.Z cd /tmp/reqsign-verify-X.Y.Z shasum -a 512 -c apache-reqsign-X.Y.Z.tar.gz.sha512 gpg --verify apache-reqsign-X.Y.Z.tar.gz.asc apache-reqsign-X.Y.Z.tar.gz @@ -182,28 +196,30 @@ gpg --verify apache-reqsign-X.Y.Z.tar.gz.asc apache-reqsign-X.Y.Z.tar.gz ## Start Vote -Create a GitHub Discussion in `apache/reqsign` General. +Create a GitHub Discussion in `apache/reqsign` General. Confirm that the vote is +forwarded to `dev@reqsign.apache.org` and that the mailing-list thread is linked +from the Discussion before counting the voting period. Title: ```text -[VOTE] Release Apache OpenDAL reqsign X.Y.Z - Vote Round 1 +[VOTE] Release Apache Reqsign X.Y.Z - Vote Round 1 ``` Body: ```text -Hello, Apache OpenDAL Community, +Hello, Apache Reqsign Community, -This is a call for a vote to release Apache OpenDAL reqsign version X.Y.Z. +This is a call for a vote to release Apache Reqsign version X.Y.Z. The release candidate: -https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z/ +https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z/ Keys to verify the release candidate: -https://downloads.apache.org/opendal/KEYS +https://downloads.apache.org/reqsign/KEYS Git tag for the release candidate: @@ -238,7 +254,7 @@ NAME 1. Verify vote state. - Confirm at least three binding `+1` votes and no blocking `-1` votes. + Confirm at least three binding `+1` votes from Reqsign PMC members and no blocking `-1` votes. 2. Publish vote result. @@ -247,15 +263,15 @@ NAME Title: ```text - [RESULT][VOTE] Release Apache OpenDAL reqsign X.Y.Z - Vote Round 1 + [RESULT][VOTE] Release Apache Reqsign X.Y.Z - Vote Round 1 ``` Body: ```text - Hello, Apache OpenDAL Community, + Hello, Apache Reqsign Community, - The vote to release Apache OpenDAL reqsign X.Y.Z has passed. + The vote to release Apache Reqsign X.Y.Z has passed. The vote PASSED with N +1 binding votes, no +0 or -1 votes. @@ -287,8 +303,8 @@ NAME ```bash svn mv --force-interactive \ - https://dist.apache.org/repos/dist/dev/opendal/reqsign-X.Y.Z \ - https://dist.apache.org/repos/dist/release/opendal/reqsign-X.Y.Z \ + https://dist.apache.org/repos/dist/dev/reqsign/reqsign-X.Y.Z \ + https://dist.apache.org/repos/dist/release/reqsign/reqsign-X.Y.Z \ -m "Release reqsign X.Y.Z" ``` diff --git a/reqsign/README.md b/reqsign/README.md index 12a3bc64..2383b8ee 100644 --- a/reqsign/README.md +++ b/reqsign/README.md @@ -1,4 +1,4 @@ -# reqsign +# Apache Reqsign Signing HTTP requests for AWS, Azure, Google, Huawei, Aliyun, Tencent and Oracle services. From 28be5c57dc2d5ad5f27e90fd63f26c6fd8d82eb1 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 30 Sep 2026 05:59:04 +0800 Subject: [PATCH 2/2] chore: address Reqsign metadata review feedback --- .asf.yaml | 6 +++--- .../scripts/release_rust/test_bootstrap.py | 20 ++----------------- THREAT_MODEL.md | 2 +- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index bceb564d..393acfcb 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -87,7 +87,7 @@ github: restrict_deletion: true restrict_force_push: true notifications: - commits: dev@reqsign.apache.org - issues: dev@reqsign.apache.org - pullrequests: dev@reqsign.apache.org + commits: commits@reqsign.apache.org + issues: commits@reqsign.apache.org + pullrequests: commits@reqsign.apache.org discussions: dev@reqsign.apache.org diff --git a/.github/scripts/release_rust/test_bootstrap.py b/.github/scripts/release_rust/test_bootstrap.py index da8ac022..1f7db8c8 100644 --- a/.github/scripts/release_rust/test_bootstrap.py +++ b/.github/scripts/release_rust/test_bootstrap.py @@ -26,6 +26,7 @@ from unittest import mock from bootstrap import CratesIoClient +from bootstrap import LEGACY_PLACEHOLDER_DESCRIPTION from bootstrap import LEGACY_REPOSITORY from bootstrap import PLACEHOLDER_DESCRIPTION from bootstrap import PLACEHOLDER_VERSION @@ -420,7 +421,7 @@ def test_partial_placeholder_resumes_without_republishing(self): planned = PlannedCrate("reqsign-new", "services/new") for description in ( PLACEHOLDER_DESCRIPTION, - "Namespace reservation for a crate planned by Apache OpenDAL reqsign.", + LEGACY_PLACEHOLDER_DESCRIPTION, ): with self.subTest(description=description): krate = metadata(planned.name, version=PLACEHOLDER_VERSION) @@ -444,23 +445,6 @@ def test_partial_placeholder_resumes_without_republishing(self): ), ) - def test_unrecognized_placeholder_is_not_reconciled(self): - planned = PlannedCrate("reqsign-new", "services/new") - krate = metadata(planned.name, version=PLACEHOLDER_VERSION) - krate["description"] = "Reserved by another project" - client = FakeClient(planned.name, krate) - - with ( - tempfile.TemporaryDirectory() as tmpdir, - mock.patch("bootstrap.publish_placeholder") as publish, - self.assertRaisesRegex(RuntimeError, "unexpected 0.0.0 placeholder"), - ): - reconcile_crate(Path(tmpdir), planned, client, "bootstrap-token") - - publish.assert_not_called() - self.assertEqual(client.created_configs, 0) - self.assertEqual(client.restricted, 0) - def test_ready_placeholder_is_a_noop(self): planned = PlannedCrate("reqsign-new", "services/new") client = FakeClient( diff --git a/THREAT_MODEL.md b/THREAT_MODEL.md index 6f7311d4..ea0fdeea 100644 --- a/THREAT_MODEL.md +++ b/THREAT_MODEL.md @@ -587,7 +587,7 @@ We will revisit this threat model when any of the following changes: ## 10. Relationship To OpenDAL And Other Hosts -Apache Reqsign is an independent Apache top-level project. OpenDAL remains the +Apache Reqsign is a top-level ASF project. OpenDAL remains the primary integration this model expects maintainers to consider. Reqsign is a reusable library: direct `reqsign` users and other embedding applications get the same Reqsign security properties and retain the same host-application