Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ Thanks for your interest. This guide applies to every repository under [`resq-so

## Onboarding

Two curls get you from a bare machine to a working ResQ dev loop:
One curl gets you from a bare machine to a working ResQ dev loop:

```bash
# 1. Install the `resq` CLI (SHA-verified release binary, cargo fallback)
curl -fsSL https://raw.githubusercontent.com/resq-software/dev/main/scripts/install-resq.sh | sh

# 2. Inside a cloned ResQ repo, install the canonical git hooks
cd <repo> && curl -fsSL https://raw.githubusercontent.com/resq-software/dev/main/scripts/install-hooks.sh | sh
curl -fsSL https://get.resq.software | sh
```

The second script installs six hooks (pre-commit, commit-msg, prepare-commit-msg, pre-push, post-checkout, post-merge) that delegate to `resq pre-commit`. It also offers to scaffold a repo-type-aware `local-pre-push` (Rust / Python / Node / .NET / C++ / Nix).
This installs the SHA256-verified `resq` CLI (with a `cargo install --git` fallback), optionally clones a repo, and — when run inside a repo — installs the canonical git hooks: six hooks (pre-commit, commit-msg, prepare-commit-msg, pre-push, post-checkout, post-merge) that delegate to `resq pre-commit`, plus an offer to scaffold a repo-type-aware `local-pre-push` (Rust / Python / Node / .NET / C++ / Nix).

Full contract: [`resq-software/dev/AGENTS.md#git-hooks`](https://github.com/resq-software/dev/blob/main/AGENTS.md#git-hooks).

Expand Down Expand Up @@ -57,6 +53,23 @@ resq hooks doctor # report drift between installed and canonical hooks
resq hooks update # rewrite installed hooks from embedded templates
```

## Engineering standards

Org-wide code standards live in [`docs/standards/`](./docs/standards/) — a
three-tier model plus a security overlay:

- [**Tier 1 — Baseline**](./docs/standards/01-baseline.md): required toolchain,
hard rules, code shape (every repo).
- [**Tier 2 — Language enforcement**](./docs/standards/02-languages.md): per-language
tooling and idioms (TS, Python, C#, Rust, C/C++, Shell, SQL, …).
- [**Tier 3 — Safety overlay**](./docs/standards/03-safety-overlay.md): JSF / MISRA /
NASA Power of Ten for device- and flight-adjacent code.
- [**Security overlay**](./docs/standards/04-security.md): untrusted input, secrets,
auth, crypto.

Per-repo specifics (commands, architecture, deliberate deviations) still live in
each repo's `AGENTS.md`.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Opening a PR

1. Branch from the default branch; name it per the pattern above.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Organization-wide community health files, issue/PR templates, and the public pro
| `profile/README.md` | The org profile shown at [github.com/resq-software](https://github.com/resq-software) |
| `assets/` | Shared assets (banner, logo) used across org READMEs |
| `README.template.md` | Standardized README template for new ResQ repositories |
| [`docs/standards/`](docs/standards/) | Org-wide engineering standards — the three-tier model (baseline, per-language, safety overlay) + security overlay |

### Community Health Files

Expand Down
117 changes: 52 additions & 65 deletions README.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,86 +16,52 @@
═══════════════════════════════════════════════════════════════════
-->

<!-- BANNER: 1200×300 recommended. Store in assets/banner.png or skip entirely -->
<p align="center">
<img src="assets/banner.png" alt="{{PROJECT_NAME}} Banner" width="100%" />
</p>
<!-- ─────────────────────────────────────────────────────────────────────
HERO — editorial / centered. Keep it calm: a mark, the name, one line,
a short badge row, a single nav line. Everything lives inside one
centered <div>. The "ResQ README Template" marker comment above must
stay (org tooling checks for it).
───────────────────────────────────────────────────────────────────── -->
<div align="center" markdown="1">

<!-- MARK: a square logo (~96–120px, assets/logo.png) reads cleaner in this
centered layout than a wide banner. Swap src/width for a 1200×300
banner if you prefer one. -->
<img src="assets/logo.png" alt="{{PROJECT_NAME}}" width="120" />

<h1 align="center">{{PROJECT_NAME}}</h1>

<!-- TAGLINE: one sentence. What it is and who it's for. -->
<p align="center">
{{ONE_LINE_DESCRIPTION}}
</p>

<!--
BADGES — keep this row short (4–6 max).
Delete the blocks that don't apply. The correct URL pattern per ecosystem:
<p align="center"><em>{{ONE_LINE_DESCRIPTION}}</em></p>

── CI (all projects) ───────────────────────────────────────────────
https://img.shields.io/github/actions/workflow/status/resq-software/{{REPO}}/ci.yml?branch=main
<!-- BADGES — keep to 4–6. Pick ONE version badge for your ecosystem and
delete the rest. `flat` + a logo + the ResQ sky accent (0ea5e9) keeps
the row quiet and consistent. Blank lines around this block are load-
bearing: they let GitHub render the Markdown badges inside the <div>. -->

── Version ─────────────────────────────────────────────────────────
npm: https://img.shields.io/npm/v/{{NPM_PACKAGE}}
crates: https://img.shields.io/crates/v/{{CRATE_NAME}}
PyPI: https://img.shields.io/pypi/v/{{PYPI_PACKAGE}}
NuGet: https://img.shields.io/nuget/v/{{NUGET_PACKAGE}}

── Coverage ─────────────────────────────────────────────────────────
https://codecov.io/gh/resq-software/{{REPO}}/graph/badge.svg

── License (Apache-2.0, all ResQ projects) ─────────────────────────
https://img.shields.io/badge/license-Apache--2.0-blue.svg
-->
<p align="center">
<!-- CI -->
<a href="https://github.com/resq-software/{{REPO}}/actions/workflows/ci.yml">
<img src="https://img.shields.io/github/actions/workflow/status/resq-software/{{REPO}}/ci.yml?branch=main&label=ci&style=flat-square" alt="CI" />
</a>
<!-- Version — pick ONE block below based on ecosystem, delete the rest -->
<!-- npm -->
<a href="https://www.npmjs.com/package/{{NPM_PACKAGE}}">
<img src="https://img.shields.io/npm/v/{{NPM_PACKAGE}}?style=flat-square&label=npm" alt="npm version" />
</a>
<!-- crates.io -->
<a href="https://crates.io/crates/{{CRATE_NAME}}">
<img src="https://img.shields.io/crates/v/{{CRATE_NAME}}?style=flat-square" alt="crates.io" />
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/{{PYPI_PACKAGE}}/">
<img src="https://img.shields.io/pypi/v/{{PYPI_PACKAGE}}?style=flat-square" alt="PyPI" />
</a>
<!-- NuGet -->
<a href="https://www.nuget.org/packages/{{NUGET_PACKAGE}}">
<img src="https://img.shields.io/nuget/v/{{NUGET_PACKAGE}}?style=flat-square" alt="NuGet" />
</a>
<!-- Coverage -->
<a href="https://codecov.io/gh/resq-software/{{REPO}}">
<img src="https://codecov.io/gh/resq-software/{{REPO}}/graph/badge.svg" alt="Coverage" />
</a>
<!-- License -->
<a href="./LICENSE">
<img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg?style=flat-square" alt="License: Apache-2.0" />
</a>
<!-- Stars -->
<a href="https://github.com/resq-software">
<img src="https://img.shields.io/github/stars/resq-software.svg?color=gold&style=flat-square&label=Total%20Stars" alt="Total Stars" />
</a>
</p>
[![CI](https://img.shields.io/github/actions/workflow/status/resq-software/{{REPO}}/ci.yml?branch=main&style=flat&logo=githubactions&logoColor=white&label=ci&color=0ea5e9)](https://github.com/resq-software/{{REPO}}/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/{{NPM_PACKAGE}}?style=flat&logo=npm&label=npm&color=0ea5e9)](https://www.npmjs.com/package/{{NPM_PACKAGE}})
[![crates.io](https://img.shields.io/crates/v/{{CRATE_NAME}}?style=flat&logo=rust&logoColor=white&color=0ea5e9)](https://crates.io/crates/{{CRATE_NAME}})
[![PyPI](https://img.shields.io/pypi/v/{{PYPI_PACKAGE}}?style=flat&logo=pypi&logoColor=white&color=0ea5e9)](https://pypi.org/project/{{PYPI_PACKAGE}}/)
[![NuGet](https://img.shields.io/nuget/v/{{NUGET_PACKAGE}}?style=flat&logo=nuget&logoColor=white&color=0ea5e9)](https://www.nuget.org/packages/{{NUGET_PACKAGE}})
[![Coverage](https://codecov.io/gh/resq-software/{{REPO}}/graph/badge.svg)](https://codecov.io/gh/resq-software/{{REPO}})
[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-0ea5e9?style=flat)](./LICENSE)

<!-- NAV ROW — quick links. Keep it to one line; drop entries that don't apply. -->
<p align="center">
<a href="https://docs.resq.software"><b>Documentation</b></a>
&nbsp;·&nbsp;
<a href="https://resq.software"><b>Website</b></a>
&nbsp;·&nbsp;
<a href="#quick-start"><b>Quick Start</b></a>
<a href="#quick-start"><b>Quick&nbsp;Start</b></a>
&nbsp;·&nbsp;
<a href="https://github.com/resq-software/{{REPO}}/issues/new/choose"><b>Report Bug</b></a>
<a href="https://github.com/resq-software/{{REPO}}/issues/new/choose"><b>Report&nbsp;Bug</b></a>
&nbsp;·&nbsp;
<a href="https://github.com/resq-software/{{REPO}}/issues/new/choose"><b>Request Feature</b></a>
<a href="https://github.com/resq-software/{{REPO}}/issues/new/choose"><b>Request&nbsp;Feature</b></a>
</p>

</div>

<p align="center">◆&nbsp;&nbsp;&nbsp;◆&nbsp;&nbsp;&nbsp;◆</p>

---

<!-- TABLE OF CONTENTS: include when the README is longer than ~150 lines -->
Expand All @@ -115,6 +81,7 @@
- [Changelog](#changelog)
- [License](#license)
- [Acknowledgements](#acknowledgements)
- [Stats](#stats)

---

Expand Down Expand Up @@ -385,6 +352,26 @@ Licensed under the [Apache License, Version 2.0](./LICENSE).

---

## Stats

<!-- Repobeats renders a live activity panel (commits, PRs, issues,
contributors) as a single SVG. Generate the embed URL for THIS repo at
https://repobeats.axiom.co — paste the per-repo hash below. Delete this
section for private repos or where activity stats aren't useful. -->

<div align="center">

![{{PROJECT_NAME}} activity](https://repobeats.axiom.co/api/embed/{{REPOBEATS_HASH}}.svg "Repobeats analytics image")

<!-- Contributor avatars — auto-generated, no setup beyond the repo path. -->
<a href="https://github.com/resq-software/{{REPO}}/graphs/contributors">
<img src="https://contrib.rocks/image?repo=resq-software/{{REPO}}" alt="Contributors" />
</a>

</div>

---

<!--
═══════════════════════════════════════════════════════════════════
AUTOMATION REFERENCE — delete this section before publishing
Expand Down
69 changes: 69 additions & 0 deletions docs/standards/01-baseline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Tier 1 — Repo-wide Baseline

Applies to **every** repository, regardless of language. If a repo can't meet a
baseline rule, that's a written deviation in its `AGENTS.md`, not a silent skip.

## Required toolchain

Every repo must have, wired into CI via the org `required` check:

- **Formatter** — runs in CI in check mode; no unformatted code on `main`.
- **Linter** — runs in CI; warnings are errors in CI (`-D warnings`-style).
- **Type checker** — where the language has one (TS, Python, C#); enabled in
strict mode.
- **Tests** — for any non-trivial logic. New behavior ships with a test.
- **Security scan** — the org `security-scan.yml` (CodeQL/OSV/Dependency Review/
zizmor/actionlint, opt-in Gitleaks/Semgrep/Snyk).

## Hard rules

```text
No secrets in code. Use env vars or a secret manager; validate at startup.
No unchecked external input. Validate at every trust boundary; fail closed.
No unbounded retries. Every retry loop has a max attempt count + backoff.
No missing timeouts. Every network / IO call has an explicit timeout.
No silent catch/except. Handle, wrap, or propagate — never swallow.
No TODOs in production paths. Unless linked to a tracked issue.
No hand-edited generated files. Regenerate; edit the source/template.
No mutation where avoidable. Prefer immutable data; localize necessary mutation.
```

## Code shape

These are defaults; languages may override in [Tier 2](./02-languages.md) where
idioms differ (e.g. Go pointer receivers).

- **Functions** focused — aim < 50 lines; extract when responsibilities stack.
- **Files** cohesive — 200–400 lines typical, 800 max; many small files over few
large ones.
- **Nesting** shallow — prefer early returns over > 4 levels of nesting.
- **Names** descriptive — `camelCase`/`snake_case` per language; booleans read as
`is`/`has`/`should`/`can`; constants `UPPER_SNAKE_CASE`.
- **No magic numbers** — name meaningful thresholds, delays, limits.

## Errors & logging

- Handle errors explicitly at every layer; user-facing messages stay friendly,
server-side logs carry the detail.
- Structured logs (key/value or JSON), not `print`-debugging left in.
- Never leak secrets, tokens, or PII into logs or error messages.

## Repository hygiene

Enforced by [`repo-standards.yml`](../../.github/workflows/repo-standards.yml):

- A detectable `LICENSE` (Apache-2.0 unless a repo declares otherwise).
- A real `README.md` — start from [`README.template.md`](../../README.template.md);
no leftover `{{PLACEHOLDER}}` tokens.
- Org community-health files (`CONTRIBUTING`, `SECURITY`, `CODE_OF_CONDUCT`,
`SUPPORT`) are inherited org-wide from this repo — don't duplicate unless
overriding.
- Conventional Commits + the branch-name pattern (see [`CONTRIBUTING.md`](../../CONTRIBUTING.md)).

## Definition of done

- [ ] Formatter, linter, type-checker, tests, security scan green (`required` ✓)
- [ ] No secrets, no swallowed errors, no unbounded loops/timeouts
- [ ] New behavior covered by tests
- [ ] Public API / behavior change reflected in docs and CHANGELOG
- [ ] Any standards deviation documented in `AGENTS.md`
102 changes: 102 additions & 0 deletions docs/standards/02-languages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Tier 2 — Language Enforcement

Per-language tooling and idioms. A repo's `lang` custom property selects which
section applies; polyglot repos apply every relevant section. These extend
[Tier 1](./01-baseline.md) and override it where the language idiom differs.

---

## TypeScript

The most important move is **strictness**, not style.

- `tsconfig.json` extends a strict base:
```jsonc
{
"compilerOptions": {
"strict": true,
"noImplicitOverride": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noFallthroughCasesInSwitch": true
}
}
```
- No `any`. Use `unknown` at trust boundaries and narrow.
- Validate all external data (API responses, env, user input) with Zod / Valibot
/ TypeBox before it enters typed code.
- Lint with [typescript-eslint](https://typescript-eslint.io/) recommended +
type-checked configs. Format with Prettier/Biome. Base style: Google TS guide.

## JavaScript (legacy / scripts / Node tooling)

- ESLint recommended; prefer migrating to TypeScript when a file grows logic.
- Google JS style guide as the base; prefer ESM.

## Python

- [PEP 8](https://peps.python.org/pep-0008/) + [PEP 257](https://peps.python.org/pep-0257/) baseline; Google Python style for structure.
- Tooling: **Ruff** (lint + format), **Pyright** or **mypy** (strict), **pytest**,
**Bandit** (SAST), **pip-audit** (deps). Manage with **uv**.
- Type-hint public functions; `from __future__ import annotations` where helpful.

## C\#

- [Microsoft .NET coding conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions); Google C# guide only when aligning a polyglot repo to Google style.
- `dotnet format` + `.editorconfig`; `<Nullable>enable</Nullable>`; treat warnings
as errors where practical; Roslyn analyzers (`Microsoft.CodeAnalysis.NetAnalyzers`).
- Prefer `async`/`await` end-to-end; no `.Result`/`.Wait()` deadlock traps.

## Rust

Discipline is mostly compiler-enforced.

```text
cargo fmt --check
cargo clippy -- -D warnings
cargo test
cargo audit
cargo deny check
```
Comment thread
WomB0ComB0 marked this conversation as resolved.

- Add `#![forbid(unsafe_code)]` at the crate root where the crate allows it
(it's a source attribute, not a CLI flag).
- Follow the [Rust API Guidelines](https://github.com/rust-lang/api-guidelines)
for public surfaces.
- Treat every `unsafe` block as a mini C island: document the invariants,
isolate it, review it, test it, fuzz it. See [Tier 3](./03-safety-overlay.md).

## C / C++

Tooling baseline; the analyzability rules live in [Tier 3](./03-safety-overlay.md).

- `clang-format` + `clang-tidy`; build clean at `-Wall -Wextra -Werror`.
- Sanitizers (ASan/UBSan/TSan) in test builds; static analysis in CI.
- C++: modern, RAII, smart pointers, STL; avoid raw `new`/`delete`, RTTI-heavy
designs, and clever template metaprogramming without a systems reason.

## Shell

- [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html);
**ShellCheck** clean. `set -euo pipefail` (bash) / `set -eu` (POSIX sh).
- Quote every expansion. Prefer `printf` over `echo` for data. Bound every loop.

## SQL

- **SQLFluff** for lint/format; consistent naming (snake_case tables/columns).
- Parameterized queries only — never string-concatenate user input.
- Migrations are forward-only and reviewed; every query that can grow is bounded
(`LIMIT`, pagination).

## Markdown / JSON / YAML

- Prettier (md/json/yaml) + **yamllint**; Google Markdown guide for docs.
- Workflow YAML: **actionlint** + **zizmor** (already in `security-scan.yml`).

---

## Release & versioning

Conventional Commits drive versioning. Per-ecosystem tooling (release-it, PSR,
cargo-release/release-plz, MinVer) is documented in the
[README template's automation appendix](../../README.template.md).
Loading
Loading