Re-organize and flesh-out documentation, including writing the tutorials
--- type: change description: Re-organize and flesh-out documentation, including writing the tutorials fingerprint: AP5oeODaJO4eq84LRE3rlFgEVGyPa3OywpyftSgsrx13 credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl7VRQ8ACgkQlcRvpqQRSKwgPg//R95XdGAKyC5Db0n94rHGW9LY9bcnmIe3WEQlQu2UFLJWzwGk0xJNPHugBz7tKqzEMQ+dQJ6Dl1/UjoCzMfr70Bwv26hAJa+CYLwq0qOoAqmCNZkxBREvlQfGV6E82P3iXZVOsFyNyUUTJEsM9ZdOUQB7+wnBHqw67gsTqOkS/6xXr5EPvUZeyASdG2epgHIh+DciDo6O9h6rBjMtyTgOFkCOCHKsZN8a5elAl+LaRaNWh05DJSh3y0VwPlEqfuR+zph8r5Q64aIJEY2ZA8a91T2SJQhBnUVjZ6H9nEqdhuq3bVbxgGdcZoX07pJIFIaqwIICkzEuxGtuRT0PZUC4yz2fjoiI7ykVTEN5urVOXL+vfZbgbklyST+BAUg5Qlac7fD9CP7nlGQ+alcXwL2cHBkXfRZedzw+MCyn/Qph0cNPE10uzwgR3pSWx2Sr6FOaBW/CXSH9y9rhcSF38jgXA6XirSOy3GpqfwHQaC9ol5Vm2R948XS2u0qJV3RZlcuylE62ST4K8pOiHn97HrGZnfG7TyyiYNvWjAq9avYwNhd3klWpgLs+OrgFN+f08xQxqnVbVEpwKLCwXmhRMyW7UVDRgoGTcfB7MVvWVxqbE3/f9VawF/baX4q324f+cMVkchyk0UeGnV30pJrWoDSw3UN3FAQoS/PYWNW3dZgp5F0= account: mediocregopher
This commit is contained in:
parent
a1579dcc96
commit
a709a43696
55
README.md
55
README.md
@ -9,11 +9,12 @@ they do, and fine-grained control over which users can do what.
|
||||
**Pull requests and issues** - Facilitation of discussion via comment commits,
|
||||
and fine-grained (down to the file level) sign-off requirements.
|
||||
|
||||
**Tags and releases**\* - Mark releases in the repo itself, and provide
|
||||
immutable and verifiable git tags so there's never any funny business.
|
||||
**Tags and releases** - Mark releases in the repo itself, and provide
|
||||
immutable and verifiable git tags so there's never any funny business. (Not yet
|
||||
implemented)
|
||||
|
||||
**Plugins**\*: Extend all aspects of dehub functionality via executables managed
|
||||
in the repo itself (in the same style as git hooks).
|
||||
**Plugins**: Extend all aspects of dehub functionality via executables managed
|
||||
in the repo itself (in the same style as git hooks). (Not yet implemented)
|
||||
|
||||
## Key Concepts
|
||||
|
||||
@ -26,10 +27,10 @@ to the configuration of its parent in order to be considered _verifiable_. The
|
||||
configuration file is committed to the repo like any other file would be, and so
|
||||
is even able to define the access controls on itself.
|
||||
|
||||
Second, the commit message of every dehub commit contains YAML encoded metadata,
|
||||
which allows dehub to extend git and provide multiple commit types, each with
|
||||
its own capabilities and restrictions. Some example dehub commit types are
|
||||
`change` commits, `comment` commits, and `credential` commits.
|
||||
Second, the commit message of every dehub commit contains a YAML encoded
|
||||
payload, which allows dehub to extend git and provide multiple commit types,
|
||||
each with its own capabilities and restrictions. Some example dehub commit types
|
||||
are `change` commits, `comment` commits, and `credential` commits.
|
||||
|
||||
## Infrastructure (or lack thereof)
|
||||
|
||||
@ -40,17 +41,20 @@ infrastructure can be used to host any dehub project:
|
||||
* The most barebones [git
|
||||
daemon](https://git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon) server
|
||||
(with a simple pre-receive hook set up).
|
||||
|
||||
* A remote SSH endpoint.
|
||||
|
||||
* A mailing list (aka the old school way).
|
||||
|
||||
* Network file syncing utilities such as dropbox,
|
||||
[syncthing](https://github.com/syncthing/syncthing), or
|
||||
[NFS](https://en.wikipedia.org/wiki/Network_File_System).
|
||||
|
||||
* Existing git project hosts like GitHub, Bitbucket, or Keybase.
|
||||
* Decentralized filesystems such as IPFS\*.
|
||||
|
||||
_\* Planned feature, but not yet implemented._
|
||||
* Decentralized filesystems such as IPFS. (Not yet implemented)
|
||||
|
||||
# Getting Started
|
||||
## Getting Started {#getting-started}
|
||||
|
||||
The dehub project itself can be found by cloning
|
||||
`https://dehub.dev/src/dehub.git`.
|
||||
@ -58,7 +62,7 @@ The dehub project itself can be found by cloning
|
||||
Installation of the dehub tool is currently done via the `go get` command:
|
||||
|
||||
```
|
||||
go get dehub.dev/src/dehub.git/cmd/dehub
|
||||
go get -u -v dehub.dev/src/dehub.git/cmd/dehub
|
||||
```
|
||||
|
||||
This will install the binary to your `$GOBIN` path, which you'll want to put in
|
||||
@ -68,28 +72,33 @@ Once installed, running `dehub -h` should show you the help output of the
|
||||
command. You can continue on to the tutorials if you're not sure where to go
|
||||
from here.
|
||||
|
||||
## Tutorials
|
||||
### Tutorials {#tutorials}
|
||||
|
||||
The following tutorials will guide you through the basic usage of dehub. As
|
||||
dehub is still very much in development a high level of git and PGP profiency is
|
||||
still required in order to use dehub effectively.
|
||||
The following tutorials will guide you through the basic usage of dehub. Note
|
||||
that dehub is in the infancy of its development, and so a certain level of
|
||||
profiency with git and PGP is required in order to follow these tutorials.
|
||||
|
||||
TODO
|
||||
* [Tutorial 0: Say Hello!](/docs/tut0.html)
|
||||
* [Tutorial 1: Create Your Own Project](/docs/tut1.html)
|
||||
* [Tutorial 2: Access Controls](/docs/tut2.html)
|
||||
* [Tutorial 3: Commit Sign-Off](/docs/tut3.html)
|
||||
|
||||
## Documentation
|
||||
### Documentation
|
||||
|
||||
The [SPEC](/SPEC.html) is the best place to see every possible nitty-gritty
|
||||
The [SPEC](/docs/SPEC.html) is the best place to see every possible nitty-gritty
|
||||
detail of how dehub works. It attempts to be both human-readable and exhaustive
|
||||
in its coverage.
|
||||
|
||||
## Other links
|
||||
### Other links
|
||||
|
||||
[ROADMAP](/ROADMAP.html) documents upcoming features and other work required on
|
||||
the project. If you're looking to contribute, this is a great place to start.
|
||||
[ROADMAP](/docs/ROADMAP.html) documents upcoming features and other work
|
||||
required on the project. If you're looking to contribute, this is a great place
|
||||
to start.
|
||||
|
||||
[dehub-remote](/cmd/dehub-remote/) is a simple docker image which can be used to
|
||||
host a remote dehub project over http(s). The endpoint will automatically verify
|
||||
all pushed commits.
|
||||
all pushed commits. [Tutorial 4](#tutorials) provides a brief walkthrough on
|
||||
using it.
|
||||
|
||||
[git-http-server](/cmd/git-http-server/) is a small server which makes a git
|
||||
repo's file tree available via http. It will automatically render markdown files
|
||||
|
@ -10,7 +10,6 @@ Must be able to feel good about showing the project publicly, as well as be able
|
||||
to accept help from people asking to help.
|
||||
|
||||
* Figure out commit range syntax, use that everywhere.
|
||||
* Tutorials
|
||||
* Maybe move external host?
|
||||
|
||||
## Milestone: IPFS support
|
@ -7,12 +7,14 @@ and in practical use of the git tool. All references to a git-specific concept
|
||||
retain their meaning; dehub concepts build upon git concepts, but do not
|
||||
override them.
|
||||
|
||||
## dehub Project
|
||||
## Project {#project}
|
||||
|
||||
A dehub project is comprised of:
|
||||
|
||||
* A collection of files and directories.
|
||||
|
||||
* Meta actions related to those files, e.g. discussion, proposed changes, etc.
|
||||
|
||||
* Configuration defining which meta actions are allowed under which
|
||||
circumstances.
|
||||
|
||||
@ -20,11 +22,11 @@ All of these components are housed in a git repository. A dehub project does not
|
||||
require a central repository location (a "remote"), though it may use one if
|
||||
desired.
|
||||
|
||||
## Commit Payload
|
||||
## Commit Payload {#payload}
|
||||
|
||||
All commits in a dehub project contain a payload. The payload is encoded into
|
||||
the commit message as a YAML object. Here is the general structure of a commit
|
||||
message containing a payload:
|
||||
All commits in a dehub [project](#project) contain a payload. The payload is
|
||||
encoded into the commit message as a YAML object. Here is the general structure
|
||||
of a commit message containing a payload:
|
||||
|
||||
```
|
||||
Human readable message head
|
||||
@ -44,18 +46,18 @@ The message head is a human readable description of what is being committed, and
|
||||
is terminated at the first newline. Everything after the message head must be
|
||||
valid YAML which encodes the payload.
|
||||
|
||||
### Fingerprint
|
||||
### Fingerprint {#fingerprint}
|
||||
|
||||
Each payload object contains a `fingerprint` field. The fingerprint is an opaque
|
||||
byte string encoded using standard base-64. The algorithm used to generate the
|
||||
fingerprint will depend on the payload type, and can be found in each type's
|
||||
sub-section in this document.
|
||||
Each [payload](#payload) object contains a `fingerprint` field. The fingerprint
|
||||
is an opaque byte string encoded using standard base-64. The algorithm used to
|
||||
generate the fingerprint will depend on the payload type, and can be found in
|
||||
each type's sub-section in this document.
|
||||
|
||||
### Credential
|
||||
### Credential {#credential}
|
||||
|
||||
The `credentials` field is not requires, but in practice will be found on almost
|
||||
every payload. The field's value will be an array of credential objects. Only
|
||||
one credential object is currently supported, `pgp_signature`:
|
||||
The `credentials` field is not required, but in practice will be found on almost
|
||||
every [payload](#payload). The field's value will be an array of credential
|
||||
objects. Only one credential object is currently supported, `pgp_signature`:
|
||||
|
||||
```yaml
|
||||
type: pgp_signature
|
||||
@ -75,13 +77,13 @@ pub_key_id: XXX
|
||||
body: std-base-64 signature
|
||||
```
|
||||
|
||||
### Payload Types
|
||||
### Payload Types {#payload-types}
|
||||
|
||||
#### Change Payload
|
||||
#### Change Payload {#change-payload}
|
||||
|
||||
A change payload encompasses a set of changes to the files in the project. To
|
||||
construct the change payload one must reference the file tree of the commit
|
||||
which houses the payload as well as the file tree of its parent commit;
|
||||
A change [payload](#payload) encompasses a set of changes to the files in the
|
||||
project. To construct the change payload one must reference the file tree of the
|
||||
commit which houses the payload as well as the file tree of its parent commit;
|
||||
specifically one must take the difference between them.
|
||||
|
||||
A change payload looks like this:
|
||||
@ -98,9 +100,10 @@ description: |-
|
||||
made to the project's files.
|
||||
```
|
||||
|
||||
##### Change Payload Fingerprint
|
||||
##### Change Payload Fingerprint {#change-payload-fingerprint}
|
||||
|
||||
The unencoded fingerprint of a change payload is calculated as follows:
|
||||
The unencoded [fingerprint](#fingerprint) of a [change payload](#change-payload)
|
||||
is calculated as follows:
|
||||
|
||||
* Concatenate the following:
|
||||
* A uvarint indicating the number of bytes in the description string.
|
||||
@ -124,12 +127,12 @@ The unencoded fingerprint of a change payload is calculated as follows:
|
||||
* Prepend a 0 byte to the result of the SHA-256 hash.
|
||||
|
||||
This unencoded fingerprint is then standard base-64 encoded, and that is used as
|
||||
the value of the fingerprint field.
|
||||
the value of the `fingerprint` field.
|
||||
|
||||
#### Comment Payload
|
||||
#### Comment Payload {#comment-payload}
|
||||
|
||||
A comment payload encompasses no file changes, and is used only to contain a
|
||||
comment made by a single user.
|
||||
A comment [payload](#payload) encompasses no file changes, and is used only to
|
||||
contain a comment made by a single user.
|
||||
|
||||
A comment payload looks like this:
|
||||
|
||||
@ -146,9 +149,10 @@ comment: |-
|
||||
The message head of a comment payload will generally be a truncated form of the
|
||||
comment itself.
|
||||
|
||||
##### Comment Payload Fingerprint
|
||||
##### Comment Payload Fingerprint {#comment-payload-fingerprint}
|
||||
|
||||
The unencoded fingerprint of a comment payload is calculated as follows:
|
||||
The unencoded [fingerprint](#fingerprint) of a [comment
|
||||
payload](#comment-payload) is calculated as follows:
|
||||
|
||||
* Concatenate the following:
|
||||
* A uvarint indicating the number of bytes in the comment string.
|
||||
@ -157,13 +161,14 @@ The unencoded fingerprint of a comment payload is calculated as follows:
|
||||
* Prepend a 0 byte to the result of the SHA-256 hash.
|
||||
|
||||
This unencoded fingerprint is then standard base-64 encoded, and that is used as
|
||||
the value of the fingerprint field.
|
||||
the value of the `fingerprint` field.
|
||||
|
||||
#### Credential Payload
|
||||
|
||||
A credential payload contains only one or more credentials for an arbitrary
|
||||
fingerprint. Credential payloads can be combined with other payloads of the same
|
||||
fingerprint to create a new payload with many credentials.
|
||||
A credential [payload](#payload) contains only one or more credentials for an
|
||||
arbitrary [fingerprint](#fingerprint). Credential payloads can be combined with
|
||||
other payloads of the same fingerprint to create a new payload with many
|
||||
credentials.
|
||||
|
||||
A credential payload looks like this:
|
||||
|
||||
@ -184,13 +189,13 @@ commits:
|
||||
change_description: blah blah blah
|
||||
```
|
||||
|
||||
## Project Configuration
|
||||
## Project Configuration {#project-configuration}
|
||||
|
||||
The `.dehub` directory contains all meta information related to the dehub
|
||||
project. All files within `.dehub` are tracked by the git repo like any other
|
||||
files in the project.
|
||||
[project](#project). All files within `.dehub` are tracked by the git repo like
|
||||
any other files in the project.
|
||||
|
||||
### config.yml
|
||||
### config.yml {#config-yml}
|
||||
|
||||
The `.dehub/config.yml` file contains a yaml encoded configuration object:
|
||||
|
||||
@ -201,10 +206,10 @@ access_controls: [...]
|
||||
|
||||
Both fields are described in their own sub-section below.
|
||||
|
||||
#### Account
|
||||
#### Account {#account}
|
||||
|
||||
An account defines a specific user of the project. Every account has an ID; no
|
||||
two accounts within a project may share the same ID.
|
||||
An account defines a specific user of a [project](#project). Every account has
|
||||
an ID; no two accounts within a project may share the same ID.
|
||||
|
||||
An account looks like this:
|
||||
|
||||
@ -213,11 +218,12 @@ id: some_string
|
||||
signifiers: [...]
|
||||
```
|
||||
|
||||
##### Signifier
|
||||
##### Signifier {#signifier}
|
||||
|
||||
A signifier is used to signify that an account has taken some action. The most
|
||||
common use-case is to prove that an account created a particular credential. An
|
||||
account may have more than one signifier.
|
||||
A signifier is used to signify that an [account](#account) has taken some
|
||||
action. The most common use-case is to prove that an account created a
|
||||
particular [credential](#credential). An account may have more than one
|
||||
signifier.
|
||||
|
||||
Currently there is only one signifier type, `pgp_public_key`:
|
||||
|
||||
@ -235,11 +241,11 @@ type: pgp_public_key
|
||||
body: inlined ASCII-armored pgp public key
|
||||
```
|
||||
|
||||
#### Access Control
|
||||
#### Access Control {#access-control}
|
||||
|
||||
An access control allows or denies a particular commit from becoming a part of
|
||||
the project. Each action control has an action (allow or deny) and a set of
|
||||
filters:
|
||||
a [project](#project). Each access control has an action (allow or deny) and a
|
||||
set of filters (filters are described in the next section):
|
||||
|
||||
```yaml
|
||||
action: allow # or deny
|
||||
@ -253,29 +259,31 @@ and its action is taken.
|
||||
|
||||
An access control with no filters matches all commits.
|
||||
|
||||
##### Filters
|
||||
##### Filter {#filter}
|
||||
|
||||
There are many kinds of access control filters. Any filter can be applied to a
|
||||
commit, with no other input, and produce a boolean value. All filters have a
|
||||
`type` field which indicates their type.
|
||||
There are many kinds of [access control](#access-control) filters. Any filter
|
||||
can be applied to a commit, with no other input, and produce a boolean value.
|
||||
All filters have a `type` field which indicates their type.
|
||||
|
||||
###### Signature Filter
|
||||
###### Signature Filter {#signature-filter}
|
||||
|
||||
A filter of type `signature` asserts that a commit's payload contains signature
|
||||
credentials with certain properties. A signature filter must have one of these
|
||||
fields, which define the set of users or accounts whose signatures are
|
||||
applicable.
|
||||
A [filter](#filter) of type `signature` asserts that a commit's
|
||||
[payload](#payload) contains [signature credentials](#credential) with certain
|
||||
properties. A signature filter must have one of these fields, which define the
|
||||
set of users or [accounts](#account) whose signatures are applicable.
|
||||
|
||||
* `account_ids: [...]` - an array of account IDs, each having been defined in
|
||||
the accounts section of the [configuration](#config-yml).
|
||||
|
||||
* `account_ids: [...]` - an array of account IDs, each having been defined in the
|
||||
accounts section of the configuration.
|
||||
* `any_account: true` - matches any account defined in the accounts section of
|
||||
the configuration.
|
||||
|
||||
* `any: true` - matches any signature, whether or not its signifier has been
|
||||
defined in the configuration.
|
||||
|
||||
A `count` field may also be included. Its value may be a number or a string
|
||||
indicating a percent (e.g. `"50%"`). If not included it will be assumed to be
|
||||
`1`.
|
||||
A `count` field may also be included. Its value may be an absolute number (e.g.
|
||||
`5`) or it may be a string indicating a percent (e.g. `"50%"`). If not included
|
||||
it will be assumed to be `1`.
|
||||
|
||||
The count indicates how many accounts from the specified set must have a
|
||||
signature included. If a percent is given then that will be multiplied against
|
||||
@ -308,11 +316,11 @@ type: signature
|
||||
any: true
|
||||
```
|
||||
|
||||
###### Branch Filter
|
||||
###### Branch Filter {#branch-filter}
|
||||
|
||||
A filter of type `branch` matches the commit based on which branch in the repo
|
||||
it is being or has been committed to. Matching is performed on the short name
|
||||
of the branch, using globstar pattern matching.
|
||||
A [filter](#filter) of type `branch` matches the commit based on which branch in
|
||||
the repo it is being or has been committed to. Matching is performed on the
|
||||
short name of the branch, using globstar pattern matching.
|
||||
|
||||
A branch filter can have one or multiple patterns defined. The filter will match
|
||||
if at least one defined pattern matches the short form of the branch name.
|
||||
@ -334,11 +342,12 @@ patterns:
|
||||
- amy/**
|
||||
```
|
||||
|
||||
###### Files Changed Filter
|
||||
###### Files Changed Filter {#files-changed-filter}
|
||||
|
||||
A filter of type `files_changed` matches the commit based on which files were
|
||||
changed between the tree of the commit's parent and the commit's tree. Matching
|
||||
is performed on the paths of the changed files, relative to the repo root.
|
||||
A [filter](#filter) of type `files_changed` matches the commit based on which
|
||||
files were changed between the tree of the commit's parent and the commit's
|
||||
tree. Matching is performed on the paths of the changed files, relative to the
|
||||
repo root.
|
||||
|
||||
A files changed filter can have one or multiple patterns defined. The filter
|
||||
will match if any of the changed files matches at least one defined pattern.
|
||||
@ -360,12 +369,12 @@ patterns:
|
||||
- **.jpg
|
||||
```
|
||||
|
||||
###### Payload Type Filter
|
||||
###### Payload Type Filter {#payload-type-filter}
|
||||
|
||||
A filter of type `payload_type` matches a commit based on the type of its
|
||||
payload. A payload type filter can have one or more types defined. The filter
|
||||
will match if the commit's payload type matches at least one of the defined
|
||||
types.
|
||||
A [filter](#filter) of type `payload_type` matches a commit based on the type of
|
||||
its [payload](#payload). A payload type filter can have one or more types
|
||||
defined. The filter will match if the commit's payload type matches at least one
|
||||
of the defined types.
|
||||
|
||||
A payload type filter with only one matching type can be defined like this:
|
||||
|
||||
@ -383,13 +392,13 @@ payload_types:
|
||||
- change
|
||||
```
|
||||
|
||||
###### Commit Attributes Filter
|
||||
###### Commit Attributes Filter {#commit-attributes-filter}
|
||||
|
||||
A filter of type `commit_attributes` matches a commit based on certain
|
||||
attributes it has. A commit attributes filter may have one or more fields
|
||||
defined, each corresponding to a different attribute the commit may have. If
|
||||
more than one field is defined then all corresponding attributes on the commit
|
||||
must match for the filter to match.
|
||||
A [filter](#filter) of type `commit_attributes` matches a commit based on
|
||||
certain attributes it has. A commit attributes filter may have one or more
|
||||
fields defined, each corresponding to a different attribute the commit may have.
|
||||
If more than one field is defined then all corresponding attributes on the
|
||||
commit must match for the filter to match.
|
||||
|
||||
Currently the only possible attribute is `non_fast_forward: true`, which matches
|
||||
a commit which is not an ancestor of the HEAD of the branch it's being pushed
|
||||
@ -402,11 +411,11 @@ type: commit_attributes
|
||||
non_fast_forward: true
|
||||
```
|
||||
|
||||
###### Not Filter
|
||||
###### Not Filter {#not-filter}
|
||||
|
||||
A filter of type `not` matches a commit using the negation of a sub-filter,
|
||||
defined within the not filter. If the sub-filter returns true for the commit,
|
||||
then the not filter returns false, and vice-versa.
|
||||
A [filter](#filter) of type `not` matches a commit using the negation of a
|
||||
sub-filter, defined within the not filter. If the sub-filter returns true for
|
||||
the commit, then the not filter returns false, and vice-versa.
|
||||
|
||||
A not filter looks like this:
|
||||
|
||||
@ -418,10 +427,10 @@ filter:
|
||||
pattern: main
|
||||
```
|
||||
|
||||
##### Default Access Controls
|
||||
##### Default Access Controls {#default-access-controls}
|
||||
|
||||
These access controls will be implicitly appended to the list defined in the
|
||||
configuration:
|
||||
These [access controls](#access-control) will be implicitly appended to the list
|
||||
defined in the [configuration](#config-yml):
|
||||
|
||||
```yaml
|
||||
# Any account may add any commit to any non-main branch, provided there is at
|
||||
@ -460,30 +469,32 @@ configuration:
|
||||
```
|
||||
|
||||
These default access controls provide a useful baseline of requirements that all
|
||||
projects will (hopefully) find useful in their infancy.
|
||||
[projects](#project) will (hopefully) find useful in their infancy.
|
||||
|
||||
## Commit Verification
|
||||
## Commit Verification {#commit-verification}
|
||||
|
||||
The dehub protocol is designed such that every commit is "verifiable". A
|
||||
verifiable commit has the following properties:
|
||||
|
||||
* Its fingerprint is correctly formed.
|
||||
* All of its credentials are correctly formed.
|
||||
* Its [fingerprint](#fingerprint) is correctly formed.
|
||||
* All of its [credentials](#credential) are correctly formed.
|
||||
* If they are signatures, they are valid signatures of the commit's
|
||||
unencoded fingerprint.
|
||||
* The project's access controls allow the commit.
|
||||
* The project's [access controls](#access-control) allow the commit.
|
||||
|
||||
The project's configuration is referenced frequently when verifying a commit,
|
||||
such as when determining which access controls to apply and discovering
|
||||
signifiers of accounts. In all cases the configuration as defined in the
|
||||
commit's _parent_ is used when verifying that commit. The exception is the prime
|
||||
commit, which uses its own configuration.
|
||||
The [project's configuration](#config-yml) is referenced frequently when
|
||||
verifying a commit, such as when determining which access controls to apply and
|
||||
discovering [signifiers](#signifier) of [accounts](#account). In all cases the
|
||||
configuration as defined in the commit's _parent_ is used when verifying that
|
||||
commit. The exception is the [prime commit](#prime-commit), which uses its own
|
||||
configuration.
|
||||
|
||||
### Prime Commit
|
||||
### Prime Commit {#prime-commit}
|
||||
|
||||
The prime commit is the trusted seed of the project. When a user clones and
|
||||
verifies a dehub project they must, implicitly or explicitly, trust the contents
|
||||
of the prime commit. All other commits must be ancestors of the prime commit.
|
||||
The prime commit is the trusted seed of the [project](#project). When a user
|
||||
clones and verifies a dehub project they must, implicitly or explicitly, trust
|
||||
the contents of the prime commit. All other commits must be ancestors of the
|
||||
prime commit.
|
||||
|
||||
Manually specifying a prime commit is not currently spec'd, but it will be.
|
||||
|
128
docs/tut0.md
Normal file
128
docs/tut0.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Tutorial 0: Say Hello!
|
||||
|
||||
This tutorial will guide you through cloning a dehub project locally, creating a
|
||||
comment, and pushing that comment back up to the remote. The project in
|
||||
question: dehub itself!
|
||||
|
||||
This tutorial assumes you have [dehub installed](/index.html#getting-started),
|
||||
you have git and gpg installed, and you have a gpg key already created.
|
||||
|
||||
## Step 0: Clone the Project
|
||||
|
||||
Cloning the dehub project is as simple as cloning its git repo:
|
||||
|
||||
```
|
||||
git clone https://dehub.dev/src/dehub.git
|
||||
cd dehub
|
||||
```
|
||||
|
||||
Once cloned, feel free to look around the project. You should initially find
|
||||
yourself on the `main` branch, the primary branch of most dehub projects
|
||||
(analogous to the `master` branch of most git repos).
|
||||
|
||||
Calling `git log` will show the commits messages for all commits in the branch.
|
||||
You will notice the commit messages aren't formatted in the familiar way, for
|
||||
example:
|
||||
|
||||
```
|
||||
commit 351048e9aabef7dc0f99b00f02547e409859a33f
|
||||
Author: mediocregopher <>
|
||||
Date: Sat Apr 25 15:17:21 2020 -0600
|
||||
|
||||
Completely rewrite SPEC
|
||||
|
||||
---
|
||||
type: change
|
||||
description: |-
|
||||
Completely rewrite SPEC
|
||||
|
||||
It's good this time, and complete. After this rewrite it will be necessary to
|
||||
update a lot of the code, since quite a few things got renamed.
|
||||
fingerprint: AG0s3yILU+0uIZltVY7A9/cgxr/pXk2MzGwExsY/hbIc
|
||||
credentials:
|
||||
- type: pgp_signature
|
||||
pub_key_id: 95C46FA6A41148AC
|
||||
body: BIG LONG STRING
|
||||
account: mediocregopher
|
||||
```
|
||||
|
||||
Instead of just being a human-readable description they are YAML encoded payload
|
||||
objects. We will dive into these payload objects more throughout this tutorial
|
||||
series.
|
||||
|
||||
## Step 1: Checkout the Welcome Branch
|
||||
|
||||
Next you're going to checkout the public welcome branch. This is done through a
|
||||
normal git checkout command:
|
||||
|
||||
```
|
||||
git checkout public/welcome
|
||||
```
|
||||
|
||||
You can do `git log` to see all the comments people have been leaving in this
|
||||
branch. The `public/welcome` branch is differentiated from the `main` branch in
|
||||
two ways:
|
||||
|
||||
* It has been configured to allow comment commits from anonymous users to be
|
||||
pushed to it. Project configuration is covered in a future tutorial.
|
||||
|
||||
* It has no code files tracked, its only purpose is for comments.
|
||||
|
||||
## Step 2: Create Your Comment
|
||||
|
||||
Now that you've poked around the welcome branch a bit, it's time to leave a
|
||||
comment of your own! This is as easy as doing:
|
||||
|
||||
```
|
||||
dehub commit --anon-pgp-key=KEY_NAME comment
|
||||
```
|
||||
|
||||
(`KEY_NAME` should be replaced with any selector which will match your pgp key,
|
||||
such as the key ID, the name on the key, or the email.)
|
||||
|
||||
Your default text editor (defined by the EDITOR environment variable) will pop
|
||||
up and you can then write down your comment. When you save and close your editor
|
||||
dehub will sign the comment with your pgp key and create a commit with it.
|
||||
|
||||
If you're having trouble thinking of something to say, here's some prompts to
|
||||
get you going:
|
||||
|
||||
* Introduce yourself; say where you're from and what your interests are.
|
||||
|
||||
* How did you find dehub? Why is it interesting to you?
|
||||
|
||||
* If you're using dehub for a project, shill your project!
|
||||
|
||||
* If you'd like to get involved in dehub's development, let us know what your
|
||||
skills are and how you can help. Remember, it takes more than expert
|
||||
programmers to make a project successful.
|
||||
|
||||
Once you've created your commit you can call `git log` to verify that it's been
|
||||
created to your liking. If there's anything about the comment you'd like to
|
||||
change you can amend the commit like so:
|
||||
|
||||
```
|
||||
dehub commit --anon-pgp-key=KEY_NAME comment --amend
|
||||
```
|
||||
|
||||
## Step 3: Push Your Commit
|
||||
|
||||
As of now your comment commit only exists on your local machine. For everyone
|
||||
else to see it you'll need to push it to the dehub server, exactly like with a
|
||||
normal git commit. Pushing is done in the same way as a normal git commit as
|
||||
well: `git push`.
|
||||
|
||||
If you receive an error that's like `Updates were rejected because the tip of
|
||||
your current branch is behind` then someone else has pushed to the branch in
|
||||
between the last time you pulled and now. Do a `git pull --rebase` to pull in
|
||||
those new changes, and try pushing again.
|
||||
|
||||
## Step 4: Follow the Conversation
|
||||
|
||||
In order to see other people's responses to your comment, and all other parts of
|
||||
the conversation, all you need to do is call `git pull` with the
|
||||
`public/welcome` branch checked out.
|
||||
|
||||
You now have all the tools needed to participate in a dehub discussion thread!
|
||||
Continue on to [Tutorial 1](tut1.html) to set up your own dehub project and
|
||||
learn about credentials and their verification.
|
178
docs/tut1.md
Normal file
178
docs/tut1.md
Normal file
@ -0,0 +1,178 @@
|
||||
# Tutorial 1: Create Your Own Project
|
||||
|
||||
This tutorial will guide you through starting a dehub project of your own, as
|
||||
well as introducing some basic concepts regarding how commit payloads work. You
|
||||
will use an example hello world project to do this.
|
||||
|
||||
This tutorial assumes you have already completed [Tutorial 0](tut0.html).
|
||||
|
||||
## Step 0: Init the Project
|
||||
|
||||
A dehub project is initialized in the same way as a git project. An empty
|
||||
directory is created, and `dehub init` is run within that directory.
|
||||
|
||||
```
|
||||
mkdir hello-world
|
||||
cd hello-world
|
||||
dehub init
|
||||
```
|
||||
|
||||
`dehub init` does nearly exactly the same thing as `git init`, with the primary
|
||||
difference being that it sets the initial branch to be `main` instead of
|
||||
`master`. dehub makes a distinction between `main` and `master` in order to help
|
||||
prevent confusion between dehub and vanilla git projects, as well as to avoid
|
||||
conflicts when migrating vanilla git projects to dehub.
|
||||
|
||||
## Step 1: Add the First Account
|
||||
|
||||
A dehub project is not fully initialized until it has an account defined for it.
|
||||
dehub accounts refer to a specific user who has some kind of access to the
|
||||
project. Each account can have specific permissions for it, as well as multiple
|
||||
ways of signifying itself.
|
||||
|
||||
For now, you'll add a basic account `tut` with a pgp key signifier. First,
|
||||
create the `.dehub` directory, which is where all dehub project configuration
|
||||
goes, and put your pgp key there:
|
||||
|
||||
```
|
||||
mkdir .dehub
|
||||
gpg -a --export KEY_ID > .dehub/tut.asc
|
||||
```
|
||||
|
||||
Next you'll create the `.dehub/config.yml` file, which is where accounts are
|
||||
actually defined (amongst many other things). The file should have the following
|
||||
contents:
|
||||
|
||||
```yaml
|
||||
# contents of .dehub/config.yml
|
||||
---
|
||||
accounts:
|
||||
- id: tut
|
||||
signifiers:
|
||||
- type: pgp_public_key_file
|
||||
path: ".dehub/tut.asc"
|
||||
```
|
||||
|
||||
Finally, you'll commit these changes and the project will have its first commit!
|
||||
Committing changes works very similarly to committing comments (as you did in
|
||||
[Tutorial 0](tut0.html)). Where a comment commit merely carries a user's
|
||||
comment, a change commit describes a set of changes to the tracked files in the
|
||||
git repo.
|
||||
|
||||
```
|
||||
git add --all
|
||||
dehub commit --as tut change
|
||||
```
|
||||
|
||||
Like when you made a comment commit this will pop up with your editor asking for
|
||||
a description of the changes. Fill it in with something like `Initialize the
|
||||
project` and save/close the editor. Depending on your pgp key settings you'll
|
||||
likely be prompted for your pgp key password at this point. After that the
|
||||
commit has been created!
|
||||
|
||||
## Step 2: Inspect the Payload
|
||||
|
||||
In this step you're going to look at the commit you just created and learn about
|
||||
the contents of the payload. To view the commit do `git show`. Something similar
|
||||
to the following should be output as the commit message:
|
||||
|
||||
```
|
||||
commit 3cdcbc19546d4e6d817ebfba3e18afbc23283ec0
|
||||
Author: username <>
|
||||
Date: Sat Apr 25 15:17:21 2020 -0600
|
||||
|
||||
Initialize the project
|
||||
|
||||
---
|
||||
type: change
|
||||
description: Initialize the project
|
||||
fingerprint: AG0s3yILU+0uIZltVY7A9/cgxr/pXk2MzGwExsY/hbIc
|
||||
credentials:
|
||||
- type: pgp_signature
|
||||
pub_key_id: 95C46FA6A41148AC
|
||||
body: BIG LONG STRING
|
||||
account: tut
|
||||
```
|
||||
|
||||
All commits in a dehub project will contain a similar looking message. The first
|
||||
line (the head) is always a human readable description of the commit. In this
|
||||
case our commit description itself, `Initialize the project`, was used.
|
||||
|
||||
After the head comes the payload, which is always a YAML encoded object. All
|
||||
payloads have a `type` field indicating what type of payload they are. That type
|
||||
will determine what other fields the payload is expected to have. The other
|
||||
fields in this payload object are:
|
||||
|
||||
* `description`: This is the description which was input into the editor when
|
||||
creating the change commit.
|
||||
|
||||
* `fingerprint`: A unique descriptor for this set of changes. It is computed
|
||||
using both `description` and the files changed.
|
||||
|
||||
* `credentials`: A set of credentials for this commit, each one declaring
|
||||
that this commit has been given approval by a user. This commit has one
|
||||
`pgp_signature` credential, created by the `tut` account. The `body` is a
|
||||
signature of the `fingerprint` created by the `tut`'s pgp key.
|
||||
|
||||
## Step 3: Create Another Commit
|
||||
|
||||
Now that the initial commit is created, and configuration has been added to the
|
||||
dehub project, you can continue on to use the project for what it was intended
|
||||
for: greeting the world!
|
||||
|
||||
Add a simple "hello world" script to the project by doing:
|
||||
|
||||
```
|
||||
echo 'echo "hello world"' > hello.sh
|
||||
git add hello.sh
|
||||
dehub commit --as tut change --descr 'add hello.sh'
|
||||
```
|
||||
|
||||
You'll notice that this time around you used the `--descr` flag to declare the
|
||||
change's description, rather than opening up the editor
|
||||
|
||||
Once again you can inspect the payload you just created using `git show`, if
|
||||
you'd like, or continue on to the next step to learn about commit verification.
|
||||
|
||||
## Step 4: Verify Your Commits
|
||||
|
||||
All this work to create YAML encoded payloads has been done for one primary
|
||||
purpose: to make commits verifiable. A verifiable commit is one which follows
|
||||
the access controls defined by its parent.
|
||||
|
||||
Your dehub project doesn't have any explicitly defined access controls (that
|
||||
will be covered in a future tutorial), and so the defaults are used. By default,
|
||||
dehub requires that all commits in `main` are change commits which have been
|
||||
signed by at least one account.
|
||||
|
||||
In order to verify the HEAD commit you can do:
|
||||
|
||||
```
|
||||
dehub verify
|
||||
```
|
||||
|
||||
This command looks at the project configuration defined in the parent of HEAD
|
||||
and verifies that HEAD conforms to it. The HEAD of your project is a change
|
||||
commit signed by the account `tut`, and so should be verifiable.
|
||||
|
||||
Arbitrary commits can be verified using the `--rev` flag. This command will
|
||||
verify the parent of HEAD, i.e. the initial commit:
|
||||
|
||||
```
|
||||
dehub verify --rev HEAD^
|
||||
```
|
||||
|
||||
The initial commit doesn't have a parent, and so is a special case for
|
||||
verification. The initial commit uses the configuration defined within itself in
|
||||
order to verify itself. This creates an exploit opportunity: if you clone a
|
||||
remote dehub project and an attacker intercepts that request they will be able
|
||||
to send you back a project with a different initial commit than what you
|
||||
expected. The whole project will still be verifiable, even though it's been
|
||||
compromised. For this reason it's important to manually verify that the initial
|
||||
commit of projects you clone are configured correctly, using the expected
|
||||
signifiers for the expected accounts.
|
||||
|
||||
You are now able to initialize a project, configure accounts within it, commit
|
||||
changes to its files, and verify those commits. Well done! Continue on to
|
||||
[Tutorial 2](tut2.html), where you will learn how to configure dehub's access
|
||||
controls.
|
259
docs/tut2.md
Normal file
259
docs/tut2.md
Normal file
@ -0,0 +1,259 @@
|
||||
# Tutorial 2: Access Controls
|
||||
|
||||
Access controls, in the context of a dehub project, refer to configuration
|
||||
defining who is allowed to do what. These controls are defined within the dehub
|
||||
project itself, within the `.dehub/config.yml` file. This tutorial will guide
|
||||
you through the basics of how access controls work, how to define them, and some
|
||||
examples of what can be done with them.
|
||||
|
||||
This tutorial assumes you have already completed [Tutorial 1](tut1.html), and
|
||||
builds on top of the project which was started there.
|
||||
|
||||
## Step 0: Create a Restricted Account
|
||||
|
||||
Inside the project you started in [Tutorial 1](tut1.html) you're going to add
|
||||
another account to the project, called `tot`. Initially, `tot` will have all the
|
||||
same permissions as `tut`, except being allowed to modify the project
|
||||
configuration.
|
||||
|
||||
First, export your gpg key into the project for `tot` to use, the same key used
|
||||
for `tut`:
|
||||
|
||||
```
|
||||
gpg -a --export KEY_ID > .dehub/tot.asc
|
||||
```
|
||||
|
||||
(For the purposes of a tutorial it's fine for two accounts to share a
|
||||
key, but it's not something which generally makes sense to do.)
|
||||
|
||||
Now, modify the `.dehub/config.yml` to have the following contents:
|
||||
|
||||
```yaml
|
||||
# contents of .dehub/config.yml
|
||||
---
|
||||
accounts:
|
||||
- id: tut
|
||||
signifiers:
|
||||
- type: pgp_public_key_file
|
||||
path: ".dehub/tut.asc"
|
||||
- id: tot
|
||||
signifiers:
|
||||
- type: pgp_public_key_file
|
||||
path: ".dehub/tot.asc"
|
||||
|
||||
access_controls:
|
||||
- action: allow
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tut
|
||||
- type: files_changed
|
||||
pattern: .dehub/*
|
||||
|
||||
- action: deny
|
||||
filters:
|
||||
- type: files_changed
|
||||
pattern: .dehub/*
|
||||
```
|
||||
|
||||
The `accounts` section has been modified to add the `tot` account, but the
|
||||
primary change here has been to add the `access_controls` section. The next
|
||||
sub-sections will explain what exactly is being done here, but for now go ahead
|
||||
and commit these changes:
|
||||
|
||||
```
|
||||
git add --all
|
||||
dehub commit --as tut change --descr 'add new restricted tot account'
|
||||
```
|
||||
|
||||
### Access Controls
|
||||
|
||||
Each access control is an action/filters pair. For any commit being verified,
|
||||
the access controls defined in its parent commit are iterated through, in order,
|
||||
until one is found whose filters all match the commit being verified. The action
|
||||
for that access control, either `allow` or `deny`, is then taken.
|
||||
|
||||
If no access controls are defined, or none match, then the default access
|
||||
controls are used. These are explicitly defined in the [SPEC](SPEC.html), but
|
||||
the general effect of them is to require that all commits have one signature
|
||||
from any of the project's accounts.
|
||||
|
||||
### Access Control Filters
|
||||
|
||||
There are many different filter types, so only the ones used in the tutorial
|
||||
will be explained. An exhaustive listing can be found in the [SPEC](SPEC.html).
|
||||
|
||||
The `signature` filter matches commits which have a signature credential created
|
||||
by any one of the specified accounts. The `files_changed` filter matches commits
|
||||
which have changed files whose paths match the specified patterns (relative to
|
||||
the project's root).
|
||||
|
||||
### Putting it Together
|
||||
|
||||
The first of the new actions controls you've defined is:
|
||||
|
||||
```
|
||||
- action: allow
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tut
|
||||
- type: files_changed
|
||||
pattern: .dehub/*
|
||||
```
|
||||
|
||||
This allows any commits which have been signed by `tut` and which modify any of
|
||||
the files in `.dehub/*`. The second access control is:
|
||||
|
||||
```
|
||||
- action: deny
|
||||
filters:
|
||||
- type: files_changed
|
||||
pattern: .dehub/*
|
||||
```
|
||||
|
||||
This denies any commits which modify any of the files in `.dehub/*`. If a commit
|
||||
does not match the first access control, but does match this second access
|
||||
control, it can be assumed that the commit does _not_ have a signature from
|
||||
`tut` (because that's the only difference between them). Therefore, the effect
|
||||
of these two controls put together is to only allow `tut` to make changes to the
|
||||
`.dehub` directory's files.
|
||||
|
||||
## Step 1: Test the Restrictions
|
||||
|
||||
Let's say that your new user `tot` is having a bit of rebellious phase, and
|
||||
wants to kick `tut` out of the project. Change `.dehub/config.yml` to have the
|
||||
following contents (note that `accounts` has been left the same and so is mostly
|
||||
elided):
|
||||
|
||||
```
|
||||
# abbreviated contents of .dehub/config.yml
|
||||
---
|
||||
accounts:
|
||||
...
|
||||
|
||||
access_controls:
|
||||
- action: deny
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tut
|
||||
```
|
||||
|
||||
So edgy. Make the commit for `tot`, being sure that the value for the `--as`
|
||||
flag indicates you're committing _as_ `tot`:
|
||||
|
||||
```
|
||||
git add --all
|
||||
dehub commit --as tot change --descr 'tut is a butt'
|
||||
```
|
||||
|
||||
Somewhat unexpectedly, the commit has been created! You can see it by doing `git
|
||||
show`. Is dehub broken?
|
||||
|
||||
The fact is that, regardless of whether or not the `dehub` tool allows one to
|
||||
create this commit, `tut` can create this commit. The important thing is that
|
||||
`tot` is able to notice that it's been created and do something about it. In a
|
||||
real-world situation, both `tot` and `tut` would be using different computers,
|
||||
and when `tot` (or anyone else) receives the commit from `tut` they will try to
|
||||
verify it, fail to do so, and ignore it.
|
||||
|
||||
If you perform `dehub verify` you will be greeted with the following error:
|
||||
|
||||
```
|
||||
exiting: blah blah blah: commit matched and denied by this access control:
|
||||
action: deny
|
||||
filters:
|
||||
- type: files_changed
|
||||
pattern: .dehub/*
|
||||
```
|
||||
|
||||
Because the parent of this commit's config disallows this commit (via the given
|
||||
access control) it is not verifiable. Go ahead and delete the commit by doing:
|
||||
|
||||
```
|
||||
git reset --hard "$(git rev-list HEAD | tail -3 | head -n1)"
|
||||
```
|
||||
|
||||
## Step 2: Different Restrictions
|
||||
|
||||
In light of `tot`'s recent actions it might be prudent to pull back their
|
||||
permissions a bit. Go ahead and change the `.dehub/config.yml` to:
|
||||
|
||||
|
||||
```
|
||||
# abbreviated contents of .dehub/config.yml
|
||||
---
|
||||
accounts:
|
||||
...
|
||||
|
||||
access_controls:
|
||||
- action: allow
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tot
|
||||
- type: branch
|
||||
pattern: tot/*
|
||||
|
||||
- action: deny
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tot
|
||||
```
|
||||
|
||||
and commit the change:
|
||||
|
||||
```
|
||||
git add --all
|
||||
dehub commit --as tut change --descr 'restrict tot to non-main branches'
|
||||
```
|
||||
|
||||
After this, `tot` will still be able to interact with the project, but only
|
||||
within branches whose names have the prefix `tot/`; the `main` branch remains
|
||||
open to other accounts, such as `tut`, due to the default access controls.
|
||||
|
||||
### Check the New Restrictions
|
||||
|
||||
`tot` has decided to do something constructive and wants to make a shell script
|
||||
which wraps the `echo` command. So helpful. Make a new branch for `tot` to use,
|
||||
and create a commit on it:
|
||||
|
||||
```
|
||||
git checkout -b tot/echo-script
|
||||
echo 'echo "$@"' > echo.sh
|
||||
git add echo.sh
|
||||
dehub commit --as tot change --descr "added echo.sh script"
|
||||
```
|
||||
|
||||
Check that the commit verifies (it should, since it's on a branch with the
|
||||
prefix `tot/`):
|
||||
|
||||
```
|
||||
dehub verify
|
||||
```
|
||||
|
||||
Now, as a final sanity check, you'll cherry-pick the commit onto `main` and
|
||||
ensure that it does _not_ verify there.
|
||||
|
||||
```
|
||||
git checkout main
|
||||
git cherry-pick tot/echo-script
|
||||
```
|
||||
|
||||
Running `dehub verify` now should fail, even though the commit remains the same.
|
||||
The only difference is the branch name; the commit is allowed in branches with
|
||||
the prefix `tot/`, and disallowed otherwise.
|
||||
|
||||
Finally, reverse that cherry-pick to make main verifiable again:
|
||||
|
||||
```
|
||||
git reset --hard "$(git rev-list HEAD | tail -4 | head -n1)"
|
||||
```
|
||||
|
||||
You now have an understanding of how dehub's access controls work. Access
|
||||
controls are extremely flexible and can be formulated to fit a wide-variety of
|
||||
use-cases. In [Tutorial 3](tut3.html) we'll see how access controls can be
|
||||
formulated to allow for commit sign-offs, where multiple accounts must accredit
|
||||
a commit before it can be verified, and how such a commit can be created.
|
247
docs/tut3.md
Normal file
247
docs/tut3.md
Normal file
@ -0,0 +1,247 @@
|
||||
# Tutorial 3: Commit Sign-Off
|
||||
|
||||
Commit sign-off is a common pattern in vanilla git projects, where a commit must
|
||||
be approved by one or more people (besides the commit author themselves) in
|
||||
order to be allowed into the primary branch.
|
||||
|
||||
dehub is able to accomplish this same pattern using only the access controls
|
||||
which have already been covered in this tutorial series and a command which has
|
||||
not: `dehub combine`. This tutorial will guide you through using `dehub combine`
|
||||
to facilitate commit sign-off.
|
||||
|
||||
This tutorial assumes you have already completed [Tutorial 2](tut2.html), and
|
||||
builds on top of the project which was started there.
|
||||
|
||||
## Step 0: Loosen the Previous Restrictions
|
||||
|
||||
In the [previous tutorial](tut2.html) you took an existing project, added a new
|
||||
user `tot` to it, and then restricted `tot` to only be allowed to make commits
|
||||
in a certain subset of branches which excluded the `main` branch.
|
||||
|
||||
As seen in that tutorial, `tot` is not able to create commits for the `main`
|
||||
branch _at all_. In this tutorial we're going to open `main` back up to `tot`,
|
||||
but only with a very important caveat: `tot`'s commits must be approved by
|
||||
someone else.
|
||||
|
||||
In the `hello-world` project which was used for previous tutorials, with the
|
||||
`main` branch checked out, go ahead and modify `.dehub/config.yml` to have the
|
||||
following contents:
|
||||
|
||||
```
|
||||
# contents of .dehub/config.yml
|
||||
---
|
||||
accounts:
|
||||
- id: tut
|
||||
signifiers:
|
||||
- type: pgp_public_key_file
|
||||
path: ".dehub/tut.asc"
|
||||
- id: tot
|
||||
signifiers:
|
||||
- type: pgp_public_key_file
|
||||
path: ".dehub/tot.asc"
|
||||
|
||||
access_controls:
|
||||
- action: allow
|
||||
filters:
|
||||
- type: signature
|
||||
account_ids:
|
||||
- tot
|
||||
- type: branch
|
||||
pattern: tot/*
|
||||
|
||||
- action: deny
|
||||
filters:
|
||||
- type: branch
|
||||
pattern: main
|
||||
- type: not
|
||||
filter:
|
||||
type: signature
|
||||
any_account: true
|
||||
count: 2
|
||||
```
|
||||
|
||||
and commit the changes:
|
||||
|
||||
```
|
||||
git add .dehub/config.yml
|
||||
dehub commit --as tut change --descr 'require commit sign-offs in main'
|
||||
```
|
||||
|
||||
The primary change was to replace the old access control denying `tot` the
|
||||
ability to commit to anything (outside of `tot/*` branches) with this one:
|
||||
|
||||
```
|
||||
- action: deny
|
||||
filters:
|
||||
- type: branch
|
||||
pattern: main
|
||||
- type: not
|
||||
filter:
|
||||
type: signature
|
||||
any_account: true
|
||||
count: 2
|
||||
```
|
||||
|
||||
There are two new things here. The first is the new fields on the `signature`
|
||||
filter: `any_account` replaces the `account_ids` field, and refers to any
|
||||
account which is defined in the `accounts` section; `count` declares how many
|
||||
accounts must have a signature on the commit for the filter to match (if not
|
||||
specified it defaults to 1).
|
||||
|
||||
The second new thing is the `not` filter: `not` wraps any other filter, and
|
||||
reverses whether or not it matches. In this case, it's wrapping our `signature`
|
||||
filter, such that this access control will match only if the commit _does not_
|
||||
have signature credentials from 2 different accounts.
|
||||
|
||||
The total effect of this access control is to deny any commits to `main` which
|
||||
do not have signature credentials from 2 different accounts. In effect, commit
|
||||
sign-off.
|
||||
|
||||
## Step 1: Some Changes to Merge
|
||||
|
||||
In the previous tutorial `tot` created a new script, `echo.sh`, in a new branch
|
||||
called `tot/echo-script`. Check that branch out, rebase it on `main` (this will
|
||||
help in later steps), and add another script to it:
|
||||
|
||||
```
|
||||
git checkout tot/echo-script
|
||||
git rebase main
|
||||
echo 'echo "$@" | awk "{ print toupper(\$0) }"' > echo-upper.sh
|
||||
git add echo-upper.sh
|
||||
dehub commit --as tot change --descr 'echo-upper.sh'
|
||||
```
|
||||
|
||||
Now the `tot/echo-script` branch contains two commits which aren't on `main`,
|
||||
both of them signed by `tot`. What will happen next is that the branch's commits
|
||||
will be combined into a single commit, be given accreditation by both `tut` and
|
||||
`tot`, and added to the `main` branch.
|
||||
|
||||
## Step 2: Accreditation
|
||||
|
||||
First, `tot` will accredit both commits, and unify the two descriptions in the
|
||||
process. To do this, you will create your first `credential` commit:
|
||||
|
||||
```
|
||||
dehub commit --as tot credential --start HEAD^^ --descr 'add echo.sh and echo-upper.sh'
|
||||
```
|
||||
|
||||
A `credential` commit, at its core, contains nothing except credentials for any
|
||||
arbitrary fingerprint. To view the credential commit you just made
|
||||
do: `git show`. You should see a commit message like:
|
||||
|
||||
```
|
||||
Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
|
||||
|
||||
---
|
||||
type: credential
|
||||
commits:
|
||||
- f085f13fa839ece122476601d970460ac249dc69 # these will be different
|
||||
- 40a81ffb4f52dc4149570672f7f7fc053f12226a
|
||||
change_description: add echo.sh and echo-upper.sh
|
||||
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
|
||||
credentials:
|
||||
- type: pgp_signature
|
||||
pub_key_id: XXX
|
||||
body: BIG LONG STRING
|
||||
account: tot
|
||||
```
|
||||
|
||||
You'll notice that the credential commit's fingerprint is different than either
|
||||
of the two commits it accredits. This is the fingerprint is based on the
|
||||
_combination_ of the two commits; it is based on the total of the file changes
|
||||
and the description provided by the user. The two commits are enumerated in the
|
||||
`commits` field of the payload, and the description provided by the user is
|
||||
stored in the `change_description` field.
|
||||
|
||||
The combined commits have now been accredited by `tot`, but not `tut`, and so
|
||||
they still lack a necessary credential. Have `tut` make a credential now:
|
||||
|
||||
```
|
||||
dehub commit --as tut credential --rev HEAD
|
||||
```
|
||||
|
||||
This form of the `credential` sub-command only accredits a single commit. When a
|
||||
single commit is accredited and it itself is a credential commit then the new
|
||||
commit which is created is merely a copy of the specified credential commit with
|
||||
the caller's own credential appended to the `credentials` list. You can see this
|
||||
with `git show`, which should look like:
|
||||
|
||||
```
|
||||
Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
|
||||
|
||||
---
|
||||
type: credential
|
||||
commits:
|
||||
- f085f13fa839ece122476601d970460ac249dc69 # these will be different
|
||||
- 40a81ffb4f52dc4149570672f7f7fc053f12226a
|
||||
change_description: add echo.sh and echo-upper.sh
|
||||
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
|
||||
credentials:
|
||||
- type: pgp_signature
|
||||
pub_key_id: XXX
|
||||
body: BIG LONG STRING
|
||||
account: tot
|
||||
- type: pgp_signature
|
||||
pub_key_id: XXX
|
||||
body: BIG LONG STRING
|
||||
account: tut
|
||||
```
|
||||
|
||||
There is now enough credentials to combine both commits in the `tot/echo-script`
|
||||
branch into a single commit on the `main` branch.
|
||||
|
||||
## Step 3: Combination
|
||||
|
||||
At this point the `tot/echo-script` branch has the following elements in place:
|
||||
|
||||
* Two change commits, which we want to combine and bring over to `main`.
|
||||
* A credential commit made by `tot` for the combined changes.
|
||||
* A credential commit made by `tut` for the combined changes, which includes
|
||||
`tot`'s credentials.
|
||||
|
||||
Combining the commits and placing them on `main` is done with a single command:
|
||||
|
||||
```
|
||||
dehub combine --start HEAD^^^^ --end HEAD --onto main
|
||||
```
|
||||
|
||||
This `combine` command combines all changes made within the given commit range,
|
||||
the last change description found in that range (in this case it will be from
|
||||
`tut`'s credential commit), and all credentials for that set of changes. The
|
||||
command combines them into a single commit which it places on the `main` branch.
|
||||
You can see the commit you've just created by doing:
|
||||
|
||||
```
|
||||
git checkout main
|
||||
git show
|
||||
```
|
||||
|
||||
The commit should contain both of the new files, and the message should look
|
||||
something like:
|
||||
|
||||
```
|
||||
add echo.sh and echo-upper.sh
|
||||
|
||||
---
|
||||
type: change
|
||||
description: add echo.sh and echo-upper.sh
|
||||
fingerprint: ALOcEuKJkgIdz27z0fjF1NEbK6Y9cEh2RH4/sL3uf3oa
|
||||
credentials:
|
||||
- type: pgp_signature
|
||||
pub_key_id: XXX
|
||||
body: BIG LONG BODY
|
||||
account: tot
|
||||
- type: pgp_signature
|
||||
pub_key_id: XXX
|
||||
body: BIG LONG BODY
|
||||
account: tut
|
||||
```
|
||||
|
||||
The commit is accredited by two different accounts, and so is allowed to be on
|
||||
the `main` branch. This can be verified by doing `dehub verify`.
|
||||
|
||||
You now are able to require commit sign-off and create signed-off commits! The
|
||||
access control settings surrounding commit sign-offs are entirely up to you and
|
||||
your project's needs. You can require sign-off from specific accounts, any
|
||||
accounts, only on specific files, only in certain branches, etc... all using the
|
||||
same basic access control building blocks.
|
Loading…
Reference in New Issue
Block a user