package conex

  1. Overview
  2. Docs

Repository state and validation logic

The repository keeps track of valid resources, which are added after successful verification of an author. The only configuration element is the quorum: how many janitors have to sign off a change.

The only resource which is signed with an asymmetric cryptographic operation is the author, which contains a list of resources the author vouches for. To validate a resource, first the authorised authors have to be validated. Once they are approved, resource validation is a lookup of a computed hash in a map which is part of the repository.

This module contains the program logic to validate the different resources, which have different rules:

  • validate_author requires a self-signature with a validated key OR has an empty list of resources and approved by a quorum of janitors
  • validate_account is successful if the account is in the authors resource list, and approved by a quorum of janitors
  • validate_key is successful if the key is in the authors resource list, and approved by a quorum of janitors
  • validate_team is successful if approved by a quorum of janitors
  • validate_authorisation is successful if approved by a quorum of janitors
  • validate_package is successful if approved by an authorised author OR a quorum of janitors
  • validate_release is successful if approved by an authorised author OR a quorum of janitors

Monotonicity requirements are as follows:

  • monoton_author requires the counter to increase, deletion is not supported (they can have an empty resource list and no public key).
  • monoton_team requires the counter to increase, deletion is not supported (a team may have no members)
  • monoton_authorisation requires the counter to increase, deletion is not supported
  • monoton_package requires the counter to increase, deletion is not supported (the list of releases can be empty)
  • monoton_release requires the counter to increase

Repository type, constructor, predicates

type t

The repository type

val repository : ?quorum:int -> (Conex_resource.Wire.t -> Conex_resource.Digest.t) -> unit -> t

repository ~quorum ~strict digest () is a fresh empty repository.

val quorum : t -> int

quorum repo is the configured quorum.

val find_team : t -> Conex_resource.identifier -> Conex_utils.S.t option

find_team repo id returns the members of the team id or None if there is no such team.

val id_loaded : t -> Conex_resource.identifier -> bool

id_loaded repo id is true if id has been loaded.

authorised repo auth id is true if id is a member of auth or member of a team which is authorised.

val contains : ?queued:bool -> t -> Conex_resource.Author.t -> Conex_resource.name -> Conex_resource.typ -> Conex_resource.Wire.t -> bool

contains ~queued author name typ data is true if data named name of typ is a member in the list of resources of author. If queued is true, membership of the resource in the queued list of resources is sufficient.

Validation

type conflict = [
  1. | `NameConflict of Conex_resource.name * Conex_resource.Author.r
  2. | `TypConflict of Conex_resource.typ * Conex_resource.Author.r
]

The variant of a conflict in the digest map.

val pp_conflict : conflict Conex_utils.fmt

pp_conflict is a pretty printer for conflict.

pp_ok pretty prints validation success

Errors which can occur during any validation.

pp_error prints validation errors.

val validate_author : t -> Conex_resource.Author.t -> (t, [> base_error | conflict | `InsufficientQuorum of Conex_resource.name * Conex_resource.typ * Conex_utils.S.t * int | `AuthorWithoutKeys of Conex_resource.identifier ]) result

validate_author repo author validates author: at least one public key must be approved by a quorum of janitors or the resource list is empty and it is approved by a quorum of janitors. The valid resource list is added to the repository (using add_index).

validate_account repo author account validates account of author: a quorum of janitors have to approve an account.

validate_key repo id key validates key of id: a quorum of janitors have to approve a key.

val validate_team : t -> Conex_resource.Team.t -> (t * [ `Quorum of Conex_utils.S.t ], [> base_error | `InsufficientQuorum of Conex_resource.name * Conex_resource.typ * Conex_utils.S.t * int | `MemberNotPresent of Conex_resource.identifier * Conex_utils.S.t ]) result

validate_team repo team validates team: a quorum of janitors have to approve a team, and all team members must be in the repository. If valid, the team is added to repo (using add_team).

val validate_authorisation : t -> Conex_resource.Authorisation.t -> ([ `Quorum of Conex_utils.S.t ], [> base_error | `InsufficientQuorum of Conex_resource.name * Conex_resource.typ * Conex_utils.S.t * int | `IdNotPresent of Conex_resource.name * Conex_utils.S.t ]) result

validate_authorisation repo auth validates auth: a quorum of janitors have to approve an authorisation, and all authorised ids have to be present in repo.

validate_package repo ~on_disk auth package validates package: an authorised identity must approve the package in repo, all releases must be prefixed with the package name, and if on_disk is given, the list of releases have to be identical.

validate_release repo ~on_disk auth package release validates release: an authorised (using auth) identity must approve the release in repo, it must be part of the releases of package, and if on_disk is given, the files listed must be equal, as well as their checksums.

Monotonicity

type m_err = [
  1. | `NotIncreased of Conex_resource.typ * Conex_resource.name
  2. | `Deleted of Conex_resource.typ * Conex_resource.name
  3. | `Msg of Conex_resource.typ * string
]

The variant of monotonicity errors.

val pp_m_err : m_err Conex_utils.fmt

pp_m_err is a pretty printer for m_err.

val monoton_author : ?old:Conex_resource.Author.t -> ?now:Conex_resource.Author.t -> t -> (unit, m_err) result

monoton_author ~old ~now repo checks that the counter increased.

val monoton_team : ?old:Conex_resource.Team.t -> ?now:Conex_resource.Team.t -> t -> (unit, m_err) result

monoton_team ~old ~now repo checks that the counter increased.

val monoton_authorisation : ?old:Conex_resource.Authorisation.t -> ?now:Conex_resource.Authorisation.t -> t -> (unit, m_err) result

monoton_authorisation ~old ~now repo checks that the counter increased.

val monoton_package : ?old:Conex_resource.Package.t -> ?now:Conex_resource.Package.t -> t -> (unit, m_err) result

monoton_package ~old ~now repo checks that the counter increased.

val monoton_release : ?old:Conex_resource.Release.t -> ?now:Conex_resource.Release.t -> t -> (unit, m_err) result

monoton_release ~old ~now repo checks that the counter increased.

Unsafe operations

These operations extend which resources are trusted. Usually you should not need them, but use validate_author and validate_team instead.

add_valid_resource id repo r marks resource r valid under id in repo. If the digest of r is already present for a different resource, an error will be returned.

val add_index : t -> Conex_resource.Author.t -> (t, conflict) result

add_index repo author applies add_valid_resource to each member of the resource list from author.

val add_team : t -> Conex_resource.Team.t -> t

add_team repo team adds the team to the repo.

val add_id : t -> Conex_resource.identifier -> t

add_id repo id adds the id to the repo.