From ed849f748055edae00acc7f850498651627fc206 Mon Sep 17 00:00:00 2001 From: Pinky <5f5ab050ec58ae208332edd544ebf705221e24c1b86d82a6ca07038a7a8f6ac9@buzz.block.builderlab.xyz> Date: Wed, 30 Sep 2026 16:03:06 -0600 Subject: [PATCH] docs: state the actual unsafe-code policy The docs said every crate denies unsafe code, which was untrue before this PR and more so with buzz-private-file. State the real policy: denied by default, with narrow, maintainer-approved exceptions for code that has no safe alternative, and link the approval for this one. Signed-off-by: Pinky <5f5ab050ec58ae208332edd544ebf705221e24c1b86d82a6ca07038a7a8f6ac9@buzz.block.builderlab.xyz> --- AGENTS.md | 2 +- CONTRIBUTING.md | 20 ++++++++++++++++---- SECURITY.md | 4 +++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3c9d578bb9..6379f17b27 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -191,7 +191,7 @@ non-hook commands. **Commit with `git commit -s`.** The required **DCO Check** fails any PR with a commit missing a `Signed-off-by` trailer, and `just hooks` installs a `commit-msg` hook that adds it to commits you create locally (`git rebase` and `git cherry-pick` still need `--signoff`) — if you build commit commands programmatically, include `-s` every time. To repair a branch that already has unsigned commits: `git rebase --signoff main`, then force-push. Additional rules: -- No `unsafe` code +- No `unsafe` code without a maintainer-approved exception; see [Unsafe Code](CONTRIBUTING.md#unsafe-code) - Do not introduce new `unwrap()` or `expect()` in production paths — use `?` and proper error types - New public API must have doc comments diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbe4ba5dd2..c4dc6fee7c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -333,11 +333,23 @@ Fix all clippy warnings before submitting a PR. If you believe a warning is a false positive, add a targeted `#[allow(...)]` with a comment explaining why. -### No Unsafe Code +### Unsafe Code -All crates enforce `#![deny(unsafe_code)]`. Do not add unsafe blocks. If you -believe unsafe is genuinely necessary, open an issue first to discuss the -approach. +Unsafe Rust is denied by default, and many crates enforce this with +`#![deny(unsafe_code)]` or `#![forbid(unsafe_code)]`. Exceptions are limited +to code with no safe alternative, usually OS or FFI calls that `std` and +existing dependencies do not wrap safely. + +A new exception needs a maintainer's approval, recorded in an issue or on the +PR, before it merges. When adding one: + +- Put it in the smallest item that can hold it, behind a safe API, with an + item-level `#[allow(unsafe_code)]` where the crate denies unsafe code. +- Explain why each `unsafe` block is sound in a `// SAFETY:` comment. + +For example, `buzz-private-file` wraps the Win32 calls that make a file +owner-only, so `buzz-agent` keeps `#![forbid(unsafe_code)]` +([approval](https://github.com/block/buzz/pull/7991#issuecomment-5920461188)). ### Error Handling diff --git a/SECURITY.md b/SECURITY.md index add36efee4..abf3498cca 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -123,7 +123,9 @@ controllers. ### Dependency Management We use `cargo audit` in CI to scan for known vulnerabilities in dependencies. -`#![deny(unsafe_code)]` is enforced across all crates — no unsafe Rust. +Unsafe Rust is denied by default. Exceptions are narrow, maintainer-approved +calls with no safe alternative, usually OS or FFI calls; see +[CONTRIBUTING.md](CONTRIBUTING.md#unsafe-code). ---