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
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@

## Issue (or Discussion) Link / イシューまたはディスカッションのリンク

## Design Doc / 設計ドキュメント
<!--
Link the approved design doc under docs/design-doc/ if this PR implements one.
Write "N/A" if a design doc was not required (small fix, refactor, follows existing design).
See CONTRIBUTING.md for when a design doc is required.

設計に関わる変更は docs/design-doc/ の approve 済みドキュメントへのリンクを貼る。
不要な場合(小さな修正・リファクタ・既存設計の踏襲)は "N/A" と明記する。
-->

## ADRs / 追加した ADR
<!--
List any ADRs added in this PR (docs/adr/NNNN-*.md). Write "None" if there are none.
この PR で追加した ADR があればリストする。無ければ "None"。
-->

## Impact / 影響範囲
-- 既存のDBスキーマに影響があるなど

Expand All @@ -14,6 +30,8 @@

## Checklist / セルフチェックリスト
- [ ] Updated relevant documentation (Wiki, comments, etc.) / 関連するドキュメント(Wikiやコメント)を更新した
- [ ] Design doc is linked above, or marked N/A / 上の Design Doc 欄にリンクまたは N/A を記入した
- [ ] Added ADRs are listed above, or marked None / 追加した ADR を上にリストした、または None と記入した

## Screenshots or Video / スクリーンショット・動画

Expand Down
63 changes: 63 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Contributing

For local setup and commands, see [README.dev.md](./README.dev.md).
This document describes **how to land new features and design changes**.

## Implementation Flow

```
┌─ Decide whether a design doc is required
├─ Required → write under docs/design-doc/ → review → approve → start implementing
└─ Not required → start implementing

While implementing, add an ADR under docs/adr/ each time a design decision is made

→ Open a PR (link the design doc and any related ADRs)
```

### 1. Decide whether a design doc is required

Write a design doc **before** implementing if any of the following apply:

- Changes a public API, DB schema, config file, or other externally visible interface
- Hard to roll back (e.g. requires data migration)
- Spans multiple modules / introduces new structure
- Adds a new external dependency (middleware / SaaS / library)

Otherwise (small bug fixes, internal refactors, work that follows an existing
design), no design doc is needed — a PR description is enough.

### 2. Write the design doc

- Copy `docs/design-doc/template.md` to `docs/design-doc/<feature-name>.md`
- Open a PR for review
- **Do not start implementation before approval** — this is what prevents rework
- Once approved, update the Status to `approved` and move on to implementation

### 3. Implement

As design decisions come up during implementation, record each one as an ADR.
A "design decision" here means things like:

- The algorithm / data structure / middleware you chose, and why
- Trade-offs someone might later ask "why did you do it this way?" about
- Branch points where you want to preserve the alternatives you considered

Use ADRs to capture the finer-grained decisions that didn't make it into the
design doc.

### 4. Add an ADR

- Copy `docs/adr/template.md` to `docs/adr/NNNN-kebab-case-title.md`
- `NNNN` is a zero-padded sequence number (e.g. `0001-use-valkey-for-rate-limit.md`)
- **One decision per file.** Don't bundle multiple decisions into one ADR
- Don't edit ADRs after they're accepted. If a decision is overturned, write a
new ADR and set the old one's Status to `superseded`

### 5. Open the PR

- If you wrote a design doc, link it from the PR description
- Link any ADRs you added
- Run the [pre-commit checks](./CLAUDE.md) (`cargo fmt` / `cargo clippy` / `cargo test`)
67 changes: 67 additions & 0 deletions docs/adr/0001-adopt-design-doc-and-adr-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# 0001. Adopt design doc and ADR workflow

# Status
accepted

# Context

UsageGate has been developed without a formal way to capture design rationale.
Decisions get made in commits, chat, and the maintainer's head — none of which
are durable or discoverable for future contributors or future-self.

As the project moves toward an OSS + cloud model, we need:

- A review checkpoint before implementing non-trivial changes (to avoid rework)
- A durable record of *why* a given approach was chosen, not just *what* was built
- Documentation that lives with the code and goes through the same review pipeline as code

# Decision

Adopt a two-document workflow, with both kinds of docs living in the repo under `docs/`:

- **Design docs** (`docs/design-doc/`) — forward-looking proposals for non-trivial
or hard-to-reverse changes. **Must be approved before implementation begins.**
- **ADRs** (`docs/adr/`) — one decision per file, recording decisions as they are
made (often during implementation). Immutable once accepted; overturned by writing
a new ADR that supersedes the old one.

The workflow, criteria for when a design doc is required, and templates are
documented in `CONTRIBUTING.md`. The PR template requires contributors to link
the relevant design doc and any ADRs added in the PR.

# Alternatives Considered

- **Status quo (no formal design docs / ADRs).** Rejected: rationale keeps getting
lost; no audit trail; onboarding new contributors is harder than it needs to be.
- **Design docs only, no ADRs.** Rejected: design docs are forward-looking and
approved upfront. They don't naturally capture the finer-grained decisions
that emerge during implementation. Forcing them to would either bloat the doc
or leave decisions undocumented.
- **ADRs only, no design docs.** Rejected: ADRs are snapshots of decisions
already made. Without a design-doc step, there is no review checkpoint before
implementation, so rework risk goes up for larger changes.
- **External wiki / Notion / Google Docs.** Rejected: design docs should be
reviewed in the same PR pipeline as code, version-controlled alongside it,
and survive independently of any external SaaS account.

# Consequences

- Positive:
- Decisions are traceable, version-controlled, and reviewable in PRs
- The design-doc approval gate reduces wasted implementation effort on larger changes
- ADRs build up a narrative of *why* the system looks the way it does
- Negative / trade-offs:
- Process overhead: contributors must write a doc before / during implementation
- In the current MVP-priority phase, heavy upfront design can slow delivery.
Mitigated by the explicit "when is a design doc required" criteria in
`CONTRIBUTING.md` — small fixes / refactors / follow-ups skip the design doc
- Affected modules / operations:
- All future feature work follows the flow in `CONTRIBUTING.md`
- The PR template enforces linking design docs and ADRs

# References

- [CONTRIBUTING.md](../../CONTRIBUTING.md)
- [docs/design-doc/template.md](../design-doc/template.md)
- [docs/adr/template.md](./template.md)
- [.github/PULL_REQUEST_TEMPLATE.md](../../.github/PULL_REQUEST_TEMPLATE.md)
39 changes: 39 additions & 0 deletions docs/adr/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!--
An ADR records a decision that has been made. One file per decision.
Filename: `NNNN-kebab-case-title.md` (e.g. `0001-use-valkey-for-rate-limit.md`).

A design doc proposes what to do; an ADR is a snapshot of what was decided and why.
Don't edit ADRs after they're accepted — if a decision is overturned, write a new
ADR and set the old one's status to `superseded by ADR-XXXX`.
-->

# NNNN. Title

<!-- e.g. "0003. Use Valkey as the quota counter backend" -->

# Status
<!-- proposed / accepted / rejected / deprecated / superseded -->

# Context

<!-- Why this decision was needed. Background, constraints, assumptions. -->

# Decision

<!-- What was decided. Be definitive — no hedging. -->

# Alternatives Considered

<!-- Other options compared and why each was rejected. At least one. -->

# Consequences

<!-- Impact of the decision. Separate the good, the bad, and the trade-offs accepted. -->

- Positive:
- Negative / trade-offs:
- Affected modules / operations:

# References

<!-- Related design docs / issues / PRs / external material. -->
57 changes: 57 additions & 0 deletions docs/design-doc/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!--
Use this template for changes that are non-trivial, hard to reverse, or change
external interfaces. Skip it for small bug fixes, internal refactors, or work
that follows an existing design (a PR description is enough for those).

When in doubt, write a design doc if any of the following apply:
- Changes a public API, DB schema, config file, or other externally visible interface
- Hard to roll back (e.g. requires data migration)
- Spans multiple modules / introduces new structure
- Adds a new external dependency (middleware / SaaS / library)
-->

# Summary

<!-- 1-2 lines: what and why. Details go below. -->

# Context

<!-- Current state and the problem. Why now? Link related issues / prior discussion. -->

# Goals

<!-- What this design should achieve. Measurable is better. -->

# Non-Goals

<!-- Explicitly out of scope. Prevents "why didn't you do X?" later. -->

# Proposed Design

<!-- The design you're proposing. Diagrams / code sketches / sequences as needed. -->

# Alternatives Considered

<!-- Options you considered but rejected, and why. At least one. -->

# Cross-cutting Concerns

<!-- Fill in the ones that apply. Write "N/A" for the rest — don't omit. -->

- Security / auth:
- Performance / scalability:
- Data migration / backward compatibility:
- Operations / monitoring / rollback:
- Test strategy:

# Rollout Plan

<!-- Order of release. Feature flag / staged rollout if needed. -->

# Open Questions

<!-- Unresolved items that must be answered before approval. Write "None" if empty. -->

# Status

<!-- draft / in review / approved / superseded (approver and date are tracked in the PR) -->
Loading