* docs(adr): resolve the A-13 collision, zero-pad numbers and add an index
Two records carried the number A-13:
docs/adr/A-13-expired-gpg-key-handling.md
docs/adr/A-13-screenshot-build-tag.md
An ADR number is a stable identifier, so a duplicate makes every citation
ambiguous. A-13-expired-gpg-key-handling.md keeps the number: it is cited
from docs/commands/recipients.md, docs/usecases/team-workflows.md and
docs/adr/A-14-team-workflows.md. The screenshot record has no inbound
citations and is renumbered to A-15.
Zero-pad A-3 through A-9 to A-03 through A-09 so the directory sorts
correctly now that the set has passed ten entries. None of these has an
inbound citation from another document; the single reference in
internal/backend/storage/fs/rcs.go is updated in this commit.
Add docs/adr/README.md as the index, recording the naming rules, the status
and authoring date of every record, and three facts that are otherwise only
discoverable from git history:
- A-01 and A-02 are cited from the CHANGELOG unreleased section but no file
was ever written for either; the numbers stay reserved.
- The A-13 collision and which record was renumbered.
- SECURITY_AUDIT_REPORT.md and CODE_QUALITY_REPORT.md, cited as the Source
of A-03 through A-10, were removed in 77894053 and are not in the tree.
No record content is changed apart from the H1 lines, which must match the
file names.
Signed-off-by: Pavel Lavrukhin <46395539+dantte-lp@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: add docs/conventions.md and adopt Conventional Commits
CONTRIBUTING.md required a bracketed [TAG] prefix on every commit subject.
That has not matched practice for some time: of the 344 commit subjects
since 2025-01-01, 225 are Conventional Commits and 67 use a [TAG]. The
CHANGELOG unreleased section uses a third set including [SECURITY] and
[PKG-BREAK], neither of which CONTRIBUTING.md lists.
Replace the [TAG] rule with Conventional Commits and add
docs/conventions.md as the single normative reference for:
- commit types (a closed list) and the scopes derived from the package
layout, including the five values that appear as types in the history but
are scopes: otp, age, bug, fscopy, openbsd;
- the distinction between a CLI break, which uses "!" and a
BREAKING CHANGE: footer and forces a major release, and a break confined
to pkg/gopass, which uses a PKG-BREAK: footer and does not (ADR A-12);
- Semantic Versioning, and which surfaces it does and does not cover;
- branch and tag names, including the release/ and prep/ prefixes owned by
the release automation;
- file naming for ADRs, documentation and Go sources.
The Developer Certificate of Origin requirement is unchanged. Conventional
Commits governs the subject line and the DCO adds a trailer, so the two are
independent.
Also correct the API Stability section of ARCHITECTURE.md, which still
described pkg/gopass/doc.go as carrying "an explicit instability warning"
and instructed consumers to "treat any pkg/ type or function change as
potentially breaking". Both statements predate ADR A-12: doc.go now
declares the package best-effort stable and permits additive changes in any
release. The section also referred to issue #3414 as an open decision; that
decision is recorded in A-12 with status accepted.
Extend the folder list in AGENTS.md with the five pkg/ directories it does
not mention (otp, passkey, pinentry/cli, protect, qrcon), using each
package's own doc comment as the description.
Signed-off-by: Pavel Lavrukhin <46395539+dantte-lp@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
11 KiB
Conventions
Normative reference for commit messages, versioning, branch and tag names, and file naming.
See CONTRIBUTING.md for the contribution workflow and docs/hacking.md for the development environment.
1. Commit messages
Commit subjects follow Conventional Commits 1.0.0.
1.1 Format
<type>[(<scope>)][!]: <description>
[optional body]
[optional footers]
Rules:
- Limit the subject line to 72 characters.
- Write the description in the imperative mood: "add", not "adds" or "added".
- Start the description in lowercase. Do not end it with a period.
- Include a
Signed-off-by:footer in every commit, as required by CONTRIBUTING.md. Conventional Commits governs the subject line; the Developer Certificate of Origin adds a trailer. Both apply. - Write the pull request title as a valid Conventional Commit.
The pull request title requirement follows from the merge strategy. Pull
requests are squash-merged: pull request #3489, titled fix: Avoid NPE when attempting to edit a non-existing secret, landed on master as the
single-parent commit eb1368e4 with the subject fix: Avoid NPE when attempting to edit a non-existing secret (#3489). The pull request title, not
the individual commit subjects, is the string that reaches CHANGELOG.md.
1.2 Types
This list is exhaustive. Reject any other type.
| Type | Meaning | SemVer impact | Changelog section |
|---|---|---|---|
feat |
New user-visible capability | MINOR | Added |
fix |
Bug fix | PATCH | Fixed |
security |
Security fix or hardening | PATCH | Security |
perf |
Performance improvement, no behaviour change | PATCH | Changed |
refactor |
Internal restructuring, no behaviour change | PATCH | Changed |
revert |
Reverts a previous commit | PATCH | Changed |
deps |
Dependency version change | PATCH | Changed |
docs |
Documentation only | none | omitted |
test |
Tests only | none | omitted |
build |
Build system: Makefile, goreleaser, Dockerfile | none | omitted |
ci |
GitHub Actions, linter configuration, workflows | none | omitted |
chore |
Housekeeping that fits nothing above | none | omitted |
Two entries extend the set suggested by the specification:
securitypopulates theSecuritysection of the changelog, which Keep a Changelog defines as a first-class category. Five commits since 2025-01-01 already use it.depsis the preferred type for hand-written dependency commits. Acceptchore(deps)as well: Dependabot emits it, and 147 of the 344 commit subjects since 2025-01-01 carry thechoretype, nearly all of them dependency bumps.
The following appear as commit types in the history and are not types. Use them
as scopes: otp (2 commits since 2025-01-01), age, bug, fscopy, and
openbsd (1 each).
1.3 Scopes
The scope is optional. Prefer to supply one. Do not invent scopes; omit the scope when none fits. Omit the scope for a change spanning several areas rather than listing more than one.
Commands — the 41 top-level subcommands: 39 registered by
(*Action).GetCommands in internal/action/commands.go, plus pwgen from
internal/action/pwgen and completion, both added by getCommands in
main.go:
alias audit cat clone completion config convert copy create delete doctor edit
env find fsck fscopy fsmove generate grep history init insert link list merge
mounts move otp process pwgen rcs recipients reorg setup show sum sync
templates unclip update version
Backends: age, gpg, plain, cryptfs, fossilfs, fs, gitfs, jjfs
Subsystems: action, audit, backend, cache, completion, config,
create, cui, editor, hashsum, hook, notify, out, queue,
recipients, reminder, store, store/leaf, store/root, tpl, tree,
updater
Public API: pkg/gopass, api, secrets, appdir, clipboard,
ctxutil, debug, fsutil, otp, passkey, pinentry, protect, pwgen,
qrcon, set, tempfile, termio
Meta: deps, release, changelog, docs, adr, ci, build
Write pkg/gopass out in full as a scope. Public-API changes must be greppable
against the A-12 stability contract.
1.4 Breaking changes
This repository has two independent compatibility surfaces. Mark them differently. Do not conflate them.
| Surface broken | Marker | Version impact |
|---|---|---|
| gopass CLI: commands, flags, output format, exit codes, config keys, store format | ! after the type or scope, and a BREAKING CHANGE: footer |
MAJOR |
Go module pkg/gopass only: an exported symbol removed or changed |
a PKG-BREAK: footer, no ! |
none; MINOR at most |
| Both | ! + BREAKING CHANGE: + PKG-BREAK: |
MAJOR |
Do not mark a module-only break with !. No CLI user can observe such a
change, and ! demands a major release.
Example of a module-only break, per A-12:
refactor(pkg/gopass): drop Store.GetRevision in favour of Store.History
Deprecated since 1.17.0; the two-minor / three-month window has elapsed.
PKG-BREAK: pkg/gopass: remove Store.GetRevision, use Store.History instead
Signed-off-by: Your Name <your@example.com>
The PKG-BREAK: footer is the machine-readable form of the [PKG-BREAK]
changelog tag mandated by A-12.
1.5 Changelog control footers
| Footer | Effect |
|---|---|
Changelog-Section: Added|Changed|Deprecated|Removed|Fixed|Security |
Overrides the type-to-section mapping. Required for Removed and Deprecated, which have no corresponding commit type. |
RELEASE_NOTES=<text> or RELEASE_NOTES=n/a |
Overrides the bullet text, or suppresses the entry. |
PKG-BREAK: <text> |
Emits a [PKG-BREAK]-prefixed bullet. |
2. Versioning
This project follows Semantic Versioning 2.0.0.
2.1 Covered by SemVer
SemVer applies to the gopass command line interface and its observable behaviour: subcommands, flags and their aliases, the stdout and stderr contracts, JSON output schemas, exit codes (docs/exit-codes.md), configuration keys (docs/config.md), the on-disk store format, and the generated shell completions and man page.
2.2 Not covered by SemVer
The Go module github.com/gopasspw/gopass carries no independent semver
guarantees. pkg/gopass is governed by A-12
and by the package documentation in pkg/gopass/doc.go, which declare it
best-effort stable:
- Additive changes — new exported symbols, new functional-option parameters — may appear in any release.
- Breaking changes — removal or signature change of an exported symbol, change
to an interface method set or to error semantics — require a
[PKG-BREAK]entry inCHANGELOG.mdand a deprecation window of two minor releases or three months, whichever is longer.
2.3 Precedence
Release a change that breaks only pkg/ consumers as MINOR or PATCH. Do not
bump MAJOR for it. Release a change that breaks CLI users as MAJOR regardless
of its pkg/ impact.
2.4 Pre-releases
Use vX.Y.Z-rc.N only: SemVer pre-release identifiers, dot-separated, numeric.
Sign the tag. Cut it from the merged release/vX.Y.Z-rc.N branch. See
docs/releases.md.
3. Branch names
<type>/<kebab-slug>[-<issue>]
- Use a commit type from §1.2 as
<type>. - Restrict the slug to
[a-z0-9-], plus the single/separator. Use no spaces and no underscores. Limit the whole name to 60 characters. - Append the issue number when one exists:
refactor/separate-storage-rcs-3411. - Do not create these prefixes by hand; the release automation owns them:
release/vX.Y.Zandrelease/vX.Y.Z-rc.N, created byhelpers/release/main.go, andprep/vX.Y.Z, documented in docs/releases.md. - Do not push feature branches to
gopasspw/gopass. Work on a fork.
4. Tag names
- Name releases
vX.Y.Zand pre-releasesvX.Y.Z-rc.N. - Sign every tag (
git tag -s). - Create no other tags in this repository.
.github/workflows/autorelease.yml triggers on push: tags: 'v*'.
helpers/release/main.go strips the leading v and parses the remainder as
semver.
5. File names
5.1 General rules
- Use lowercase kebab-case, restricted to
[a-z0-9._-]. - Use no spaces.
- Zero-pad any numeric component that participates in lexical ordering.
- Prefix with
YYYY-MM-DDwhen chronological order matters. - Order components from most general to most specific, left to right.
5.2 Architecture decision records
Name records docs/adr/A-NN-<kebab-slug>.md, with NN zero-padded to two
digits.
- Write the H1 as
# A-NN: <Title>, matching the file name. - Open the record with a
**Status:**line —proposed,accepted,deferred,implemented,partially implemented, orsuperseded by A-NN— and a**Source:**line. - Never reuse a number. Supersede a decision by writing a new record.
- Update docs/adr/README.md in the same commit that adds or supersedes a record.
5.3 Other documentation
- Name command specifications
docs/commands/<command>.md, where the file name is exactly the command name. - Name backend documents
docs/backends/<backend>.mdand use casesdocs/usecases/<kebab-slug>.md. - Use lowercase throughout. Keep the SCREAMING_CASE names of root-level documents, which is the GitHub convention.
5.4 Go files
- Use lowercase names with no underscores, except for the reserved suffixes below. Prefer a single word matching the primary type or the command.
- Place a command implementation in
internal/action/<command>.gowith an accompanyinginternal/action/<command>_test.go. - Reserved suffixes:
_test.go; theGOOSandGOARCHsuffixes_unix.go,_windows.go,_linux.go,_darwin.go,_others.go;_gen.gofor generated code;_fuzz.gofor fuzz targets. - Give a build-tag variant that is not
GOOS-based a descriptive suffix and an explicit//go:buildline, for examplescreenshot_supported.goandscreenshot_stub.go. - Split a file above roughly 600 lines along an existing type or feature seam.
6. Changelog
CHANGELOG.md follows Keep a Changelog 1.1.0:
an ## [Unreleased] section at the top, then one ## [X.Y.Z] - YYYY-MM-DD
section per release, each containing only the non-empty subsections of
Added, Changed, Deprecated, Removed, Fixed, and Security.
helpers/release generates the entries from commit subjects at release time,
using the mapping in §1.2 and the footers in §1.5. Do not edit CHANGELOG.md
by hand, with two exceptions. Add a hand-written ## [Unreleased] entry for:
- any change to the exported surface of
pkg/, as required by A-12; and - any
security:change.