* 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>
3.9 KiB
Hacking on gopass
Note: See CONTRIBUTING.md for an overview.
This document provides an overview on how to develop on gopass.
Development
This project uses GitHub Flow. In other words, create feature branches from master, open an PR against master, and rebase onto master if necessary.
Branch names, tag names, commit message format and file naming are specified in conventions.md.
We aim for compatibility with the latest stable Go Release only.
While this project is maintained by volunteers in their free time we aim to triage issues weekly and release a new version at least every quarter.
Setting up an isolated development environment
With GPG
gopass should fully respect GOPASS_HOMEDIR overriding all gopass internal paths.
However it will still use your normal GPG keyring and configuration. To override this
you will need to set GNUPGHOME as well and possibly generate a new keyring.
$ export GOPASS_DEBUG_LOG=/tmp/gp1.log
$ export GOPASS_HOMEDIR=/tmp/gp1
$ mkdir -p $GOPASS_HOMEDIR
$ export GNUPGHOME=$GOPASS_HOMEDIR/.gnupg
# Make sure that you're using the correct keyring.
$ gpg -K
gpg: directory '/tmp/gp1/.gnupg' created
gpg: keybox '/tmp/gp1/.gnupg/pubring.kbx' created
gpg: /tmp/gp1/.gnupg/trustdb.gpg: trustdb created
$ gpg --gen-key
$ go build && ./gopass setup --crypto gpg --storage gitfs
With age
Using age is recommended for development since it's easier to set up. Setting
GOPASS_HOMEDIR should be sufficient to ensure an isolated environment.
$ export GOPASS_DEBUG_LOG=/tmp/gp1.log
$ export GOPASS_HOMEDIR=/tmp/gp1
$ mkdir -p $GOPASS_HOMEDIR
$ go build && ./gopass setup --crypto age --storage gitfs
Extending gopass
The main extension model are small binaries that use the gopass API package. This package provides a small and easy to use API that should work with any up to date gopass setup.
This API encapsulates the exact same implementation that the CLI uses in a more nicely packaged format that's easier to use.
Note: The API is operating directly on the password store. It does not involve network operations or connecting to a gopass instance.
The API does not support setting up a new password store (yet). Users will need have an existing password store
or use gopass setup to create a new one. The API will attempt to load an existing configuration or use it's built-in
defaults. Then it initializes an existing password store and provides a simple set of CRUD operations.
Our API has some examples on how to use the API. The gopass-hibp binary should provide a more complete example that can be used as a blueprint.
import (
"context"
"fmt"
"github.com/gopasspw/gopass/pkg/gopass/api"
"github.com/gopasspw/gopass/pkg/gopass/secrets"
)
ctx := context.Background()
gp, err := api.New(ctx)
if err != nil {
panic(err)
}
// Listing secrets by their names (path within the store).
ls, err := gp.List(ctx)
if err != nil {
panic(err)
}
for _, s := range ls {
fmt.Printf("Secret: %s", s)
}
// Writing secrets to a specific location (path) in the store.
sec := secrets.New()
sec.SetPassword("foobar")
if err := gp.Set(ctx, "my/new/secret", sec); err != nil {
panic(err)
}
// Reading secrets by their name and revision from within the store.
sec, err = gp.Get(ctx, "my/new/secret", "latest")
if err != nil {
panic(err)
}
fmt.Printf("content of %s: %s\n", "my/new/secret", string(sec.Bytes()))
// Removing a secret by their name.
if err := gp.Remove(ctx, "my/new/secret"); err != nil {
panic(err)
}
// Cleaning up (waiting for background processing to complete).
if err := gp.Close(ctx); err != nil {
panic(err)
}