Writing Successions
This section provides instructions for writing document successions.
It illustrates the fundamental writing operations using
an example document succession that includes a single document snapshot.
These instructions assume you have a document snapshot saved as either a file or a directory
on your file system, with its path assigned to the environment variable SNAPSHOT
.
The process for creating a document snapshot is beyond the scope of this toolkit and manual. The only requirement is that the document snapshot can be encoded as either a Git blob (file) or a Git tree (directory).
Setting Up
Document successions can be either signed or unsigned. A signed document succession is signed with an SSH key pair. Only holders of private SSH keys can create and amend signed document successions. In contrast, unsigned document successions can be amended and invalidated by anybody, making their utility limited to testing and learning purposes. To create a signed document succession, you need to sign Git commits, which in turn requires a private signing key.
This setup is only necessary once, as you can reuse the same private signing key for multiple document successions.
Generate an SSH Signing Key
A document succession is signed with an SSH signing key, not a GPG signing key. Although OpenSSH is primarily known for secure shell connections, it also supports digital signing.
Running the command:
ssh-keygen -t ed25519 -C "me@example.com" -N "" -f ~/.ssh/my_signing_key
will generate two files:
- a private SSH signing key file at
~/.ssh/my_signing_key
and - its corresponding public key file at
~/.ssh/my_signing_key.pub
.
The ED25519 digital signature scheme, recommended by GitLab, generates shorter public keys while also providing stronger encryption compared to older popular digital signature schemes like RSA. ED25519 was introduced in OpenSSH 6.5 in 2014.
Configure an SSH Signing Key
Configure Git to use SSH keys for signing:
git config --global gpg.format ssh
Then, specify the location of your private SSH signing key. For example:
git config --global user.signingkey ~/.ssh/my_signing_key
Keep the my_signing_key.pub
file as you will need both the private and public
keys to create and amend signed document successions.
Recording
A document succession is recorded as a chain of Git commits. To be discoverable on GitHub, this chain needs to be the default branch of a Git repository.
Creating a Local Document Succession
A signed document succession begins with an initial signed commit that includes
the allowed signing keys for subsequent signed commits.
The initial commit must be signed with the private key corresponding
to one of the public keys listed in signed_succession/allowed_signers
.
git init newrepo
cd newrepo
mkdir signed_succession
cut --delimiter=' ' --fields=1,2 ~/.ssh/my_signing_key.pub \
| xargs echo '* namespaces="git"' \
> signed_succession/allowed_signers
git add signed_succession
git commit -S --allow-empty-message --message=''
An allowed_signers
file within a signed_succession
subdirectory is used by
git-verify-commit
to verify the signatures of signed Git commits amending the document
succession.
Each line of the allowed_signers
file lists an SSH public key that is allowed to amend
the document succession.
The format of each line is:
* namespaces="git" ssh-ed25519 AAA123...
To create an unsigned document succession,
remove the commands for signed_succession
and in the git commit
line omit the -S
option
and add an --allow-empty
option.
Convert Git Commit Hash to Base DSI
The base DSI of a document succession is the base64url representation of the Git commit hash of the initial commit. To view the base DSI of the newly created local document succession, run:
git rev-list --max-parents=0 main | xxd -revert -plain | basenc --base64url | tr --delete '='
This manual assumes that the default branch is named main
.
Amending a New Edition
To add the contents of a document snapshot at the file system path ${SNAPSHOT}
as edition 1.2 of the succession, run the following:
mkdir -p 1/2
cp -r ${SNAPSHOT} 1/2/object
git add 1/2/object
git commit -S --message='1.2'
For an unsigned digital succession, omit the -S
option.
Publishing
Create an Empty GitHub Repository
Create a new GitHub repository that is empty and not initialized with any files.
Let <reponame>
represent the name given to this new repository.
Push the Document Succession to GitHub
git push <url-to-github-repo>
where <url-to-github-repo>
is replaced with either
https://github.com/<username>/<reponame>.git
orgit@github.com:<username>/<reponame>.git
.
Warning
If your GitHub repository is public, anyone can replicate your document succession. Therefore, you should not plan on changing any editions you have made public on GitHub. Instead, you should only amend your document succession with a new edition if your document succession has been public for more than a trivial amount of time.
Archive to Software Heritage
Publicly archive the document succession by saving the new repository to the Software Heritage Archive.
Danger
Once you save your document succession in the Software Heritage Archive, you will lose control over changing any archived editions. You will realistically only be able to amend it with new editions. This permanence of record is what makes this last step "publication".