Skip to content

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 or
  • git@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".