TL;DR: How should we handle truly breaking changes? With a major version bump or a fork?
Background
gopass has accumulated a lot of features in the past. Some of them were contributed, some never truly finished. Also supporting troublesome dependencies like GnuPG and git adds to the maintenance burden.
It has become clear that we don't have enough time to support all of these feature and dependencies and we prefer to have a stable, polished core feature set over a huge number of partly broken features.
We had some small breaking changes in the last minor release and we will have more small breaking changes while we continue to clean up the code base leading up to a major breaking change in the next major release.
Upcoming Changes
Going forward we consider to:
- Drop GPG support, including most tooling we built around that (e.g. key export / import and such)
- Drop Git support
- Drop most configuration options
- Reduce the number of CLI subcommands and command line options
- Break compatibility with other pass implementations
This will break most existing setups and will require careful planning and execution.
If you care about any of these features the only (!) way to keep them from being removed are sustained, high quality contributions, e.g. triaging issues, improving documentation, test coverage and finally refactoring the code to make them better maintainable. Unless contributors step up to work on these, the aforementioned features will be dropped. Probably before the end of this year.
Upcoming Changes
While our goal is clear, it's not so clear how we want to get there.
Obviously we want to keep supporting our existing users (but not necessarily on their current stack).
Right now I see two options moving forward.
Both have in common that we will make smaller (possibly) breaking changes in the minor releases leading up to the next major release. We will try to limit the impact but features which are already broken, rarely used or poorly implemented will either be changed or removed.
Also we will work to add support for the storage and crypto backends that will be used in the next major release.
Crypto Backend
In the next major release our age might become our default crypto backend.
I have a very strong preference for age, but this is only possible if the project receives sustained attention and provides answers for some open questions (e.g. Go library support, agent support).
Storage / RCS Backend
While git itself is muss less troublesome to support than GnuPG it still adds unnecessary overhead.
If you think about how we use git you'll realize that we don't need most of it's features, e.g. we don't need merging (useless with encrypted files), branches, tags, or actually almost any other feature it has.
What do we really need in terms of storage / revision control?
- a Key-Value stores resembling a file system (tree)
- versioned values
Since we can't really merge or diff entries the versioning can just be a list ordered by the revision timestamp. Optionally we'd like to be able to hide the names of the keys (#673, #674).
These properties can trivially be implemented in Go.
Implementation cleanup
It's clear that in the next major release we'll reduce support for different backends, reducing the amount of code.
Eventually we'd like to get rid of complicated recipient key handling. If we're using age the recipient list will already include the whole public key with no need to additionally export or import keys to and from huge keyrings. We might even default to using GitHub username as the default mechanism (age can encrypt for ssh public keys which are publicly visible on GitHub).
Options
This section lists possible options how to reach a major reduction in tech debt with the next major release without loosing most of our users on the way.
Hard Fork
This would be the easiest option.
We would implement all required changes as detailed above in the 1.9 branch and before we start to actually remove features we'd fork the gopass repo to e.g. github.com/gopasspw/gopass2 and keep both repos around: One for the 1.x branch and the other for the 2.x branch.
Obviously we could also do that in the gopass repo with a different branch, but I think that might be more confusing.
However this approach has two big disadvantages:
- We'd still have to maintain the old gopass 1.x repo. Since our time is very limited this will slowly rot up to a point where it's unuseable. For a security critical project this isn't a good idea.
- Many users won't make the switch, cf. the Perl5/6 or Python 2/3 situation.
Provide an automated migration path
The second option would be to (try to) automatically migrate all users to the new backends.
This would require us to implement the migration tooling that would automatically migrate the users stores to the new backends in the 1.x branch. If a user misses one of the releases with this migration tooling they would need to resort to the last 1.x release before the can use the 2.x releases.
The big advantage is that this avoid the disadvantages of the first option.
The disadvantage that this is a pretty disruptive change.
Users will need to replace their remote setup (git) with something else (which doesn't exist, yet).
Also they will need to trust a different kind of crypto (which is likely much safer, but in some cases it might be perceived as a step back).
Request for Comments
Please let me know what you think. But please keep in mind that this is an open source project run by volunteers.
Feel free to share this proposal with any gopass users you know.
The question here is not if or when we'll make these breaking changes, only how!
The only way to prevent a feature from being dropped is to make sustained high quality contributions!
Edit: Updated to better reflect to current plans.