gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-anastasis] branch master updated: import Sphinx-generated Texinfo


From: gnunet
Subject: [taler-anastasis] branch master updated: import Sphinx-generated Texinfo documentation
Date: Mon, 05 Apr 2021 21:08:15 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new c9f8270  import Sphinx-generated Texinfo documentation
c9f8270 is described below

commit c9f8270d35c07b1e6b72299ba4767dbb3cb5fa52
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Apr 5 21:08:12 2021 +0200

    import Sphinx-generated Texinfo documentation
---
 .gitignore                                         |    1 +
 doc/Makefile.am                                    |   12 +
 doc/anastasis-figures/anastasis-db.png             |  Bin 0 -> 38801 bytes
 .../anastasis_challenge_payment.png                |  Bin 0 -> 20331 bytes
 doc/anastasis-figures/anastasis_challengecode.png  |  Bin 0 -> 17678 bytes
 doc/anastasis-figures/anastasis_reducer_backup.png |  Bin 0 -> 47081 bytes
 .../anastasis_reducer_recovery.png                 |  Bin 0 -> 48943 bytes
 doc/anastasis-figures/anastasis_truth.png          |  Bin 0 -> 19493 bytes
 doc/anastasis-figures/anastasis_truth_payment.png  |  Bin 0 -> 13430 bytes
 doc/anastasis.texi                                 | 2794 ++++++++++++++++++++
 doc/configuration-format.texi                      |   73 -
 doc/ledger-sme-legal-check.txt                     |  214 --
 doc/manual.texi                                    | 1296 ---------
 doc/merchant-api.content.texi                      | 1068 --------
 doc/next_steps.txt                                 |   38 -
 doc/taler-config.texi                              |   47 -
 16 files changed, 2807 insertions(+), 2736 deletions(-)

diff --git a/.gitignore b/.gitignore
index e781d3a..f10bbe4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -124,3 +124,4 @@ src/util/anastasis-config
 src/util/test_anastasis_child_management
 src/include/anastasis_error_codes.h
 src/lib/test_anastasis_api_home/
+doc/anastasis.info
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 0ea14b6..22bdf23 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,2 +1,14 @@
 man_MANS = \
   anastasis-httpd.1
+
+info_TEXINFOS = \
+  anastasis.texi
+
+EXTRA_DIST = \
+ anastasis-figures/anastasis-db.png \
+ anastasis-figures/anastasis_reducer_backup.png \
+ anastasis-figures/anastasis_truth_payment.png \
+ anastasis-figures/anastasis_challenge_payment.png \
+ anastasis-figures/anastasis_reducer_recovery.png \
+ anastasis-figures/anastasis_challengecode.png \
+ anastasis-figures/anastasis_truth.png
diff --git a/doc/anastasis-figures/anastasis-db.png 
b/doc/anastasis-figures/anastasis-db.png
new file mode 100644
index 0000000..03eed9d
Binary files /dev/null and b/doc/anastasis-figures/anastasis-db.png differ
diff --git a/doc/anastasis-figures/anastasis_challenge_payment.png 
b/doc/anastasis-figures/anastasis_challenge_payment.png
new file mode 100644
index 0000000..a0593eb
Binary files /dev/null and 
b/doc/anastasis-figures/anastasis_challenge_payment.png differ
diff --git a/doc/anastasis-figures/anastasis_challengecode.png 
b/doc/anastasis-figures/anastasis_challengecode.png
new file mode 100644
index 0000000..fc30f4f
Binary files /dev/null and b/doc/anastasis-figures/anastasis_challengecode.png 
differ
diff --git a/doc/anastasis-figures/anastasis_reducer_backup.png 
b/doc/anastasis-figures/anastasis_reducer_backup.png
new file mode 100644
index 0000000..87b0a9b
Binary files /dev/null and b/doc/anastasis-figures/anastasis_reducer_backup.png 
differ
diff --git a/doc/anastasis-figures/anastasis_reducer_recovery.png 
b/doc/anastasis-figures/anastasis_reducer_recovery.png
new file mode 100644
index 0000000..7d3cc9a
Binary files /dev/null and 
b/doc/anastasis-figures/anastasis_reducer_recovery.png differ
diff --git a/doc/anastasis-figures/anastasis_truth.png 
b/doc/anastasis-figures/anastasis_truth.png
new file mode 100644
index 0000000..7f23fa2
Binary files /dev/null and b/doc/anastasis-figures/anastasis_truth.png differ
diff --git a/doc/anastasis-figures/anastasis_truth_payment.png 
b/doc/anastasis-figures/anastasis_truth_payment.png
new file mode 100644
index 0000000..70a6b3d
Binary files /dev/null and b/doc/anastasis-figures/anastasis_truth_payment.png 
differ
diff --git a/doc/anastasis.texi b/doc/anastasis.texi
new file mode 100644
index 0000000..810e3eb
--- /dev/null
+++ b/doc/anastasis.texi
@@ -0,0 +1,2794 @@
+\input texinfo   @c -*-texinfo-*-
+@c %**start of header
+@setfilename anastasis.info
+@documentencoding UTF-8
+@ifinfo
+@*Generated by Sphinx 3.4.3.@*
+@end ifinfo
+@settitle Anastasis Manual
+@defindex ge
+@paragraphindent 0
+@exampleindent 4
+@finalout
+@dircategory CATEGORY
+@direntry
+* MENU ENTRY: (anastasis.info). DESCRIPTION
+@end direntry
+
+@definfoenclose strong,`,'
+@definfoenclose emph,`,'
+@c %**end of header
+
+@copying
+@quotation
+Anastasis 0.0.0, Apr 05, 2021
+
+Anastasis team
+
+Copyright @copyright{} 2014-2021 Anastasis SARL (GPLv3+ or GFDL 1.3+)
+@end quotation
+
+@end copying
+
+@titlepage
+@title Anastasis Manual
+@insertcopying
+@end titlepage
+@contents
+
+@c %** start of user preamble
+
+@c %** end of user preamble
+
+@ifnottex
+@node Top
+@top Anastasis Manual
+@insertcopying
+@end ifnottex
+
+@c %**start of body
+@anchor{anastasis doc}@anchor{0}
+@c This file is part of Anastasis
+@c Copyright (C) 2019. 2021 Anastasis SARL
+@c
+@c Anastasis is free software; you can redistribute it and/or modify it under 
the
+@c terms of the GNU General Public License as published by the Free Software
+@c Foundation; either version 2.1, or (at your option) any later version.
+@c
+@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+@c A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
details.
+@c
+@c You should have received a copy of the GNU Lesser General Public License 
along with
+@c Anastasis; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+@c
+@c @author Christian Grothoff
+@c @author Dominik Meister
+@c @author Dennis Neufeld
+
+Anastasis is a service that allows the user to securely deposit a
+@strong{core secret} with an open set of escrow providers and recover it if 
the secret is
+lost.  The @strong{core secret} itself is protected from the escrow providers 
by
+encrypting it with a @strong{master key}.  The main objective of Anastasis is 
to
+ensure that the user can reliably recover the @strong{core secret}, while 
making
+this difficult for everyone else.  Furthermore, it is assumed that the user is
+unable to reliably remember any secret with sufficiently high entropy, so we
+cannot simply encrypt using some other key material in possession of the user.
+
+To uniquely identify users, an “unforgettable” @strong{identifier} is used.  
This
+identifier should be difficult to guess for anybody but the user. However, the
+@strong{identifier} is not expected to have sufficient entropy or secrecy to be
+cryptographically secure. Examples for such identifier would be a
+concatenation of the full name of the user and their social security or
+passport number(s).  For Swiss citizens, the AHV number could also be used.
+
+The adversary model of Anastasis has two types of adversaries: weak
+adversaries which do not know the user’s @strong{identifier}, and strong
+adversaries which somehow do know a user’s @strong{identifier}.  For weak
+adversaries the system guarantees full confidentiality.  For strong
+adversaries, breaking confidentiality additionally requires that Anastasis
+escrow providers must have colluded.  The user is able to specify a set of
+@strong{policies} which determine which Anastasis escrow providers would need 
to
+collude to break confidentiality. These policies also set the bar for the user
+to recover their core secret.
+
+A @strong{recovery document} includes all of the information a user needs to
+recover access to their core secret.  It specifies a set of @strong{escrow
+methods}, which specify how the user should convince the Anastasis server
+that they are “real”.  Escrow methods can for example include SMS-based
+verification, video identification or a security question.  For each escrow
+method, the Anastasis server is provided with @strong{truth}, that is data the
+Anastasis operator may learn during the recovery process to authenticate the
+user.  Examples for truth would be a phone number (for SMS), a picture of the
+user (for video identification), or the (hash of) a security answer.  A strong
+adversary is assumed to be able to learn the truth, while weak adversaries
+must not.  In addition to a set of escrow methods and associated Anastasis
+server operators, the @strong{recovery document} also specifies 
@strong{policies}, which
+describe the combination(s) of the escrow methods that suffice to obtain
+access to the core secret.  For example, a @strong{policy} could say that the
+escrow methods (A and B) suffice, and a second policy may permit (A and C).  A
+different user may choose to use the policy that (A and B and C) are all
+required.  Anastasis imposes no limit on the number of policies in a
+@strong{recovery document}, or the set of providers or escrow methods involved 
in
+guarding a user’s secret.  Weak adversaries must not be able to deduce
+information about a user’s @strong{recovery document} (except for its length, 
which
+may be exposed to an adversary which monitors the user’s network traffic).
+
+@menu
+* Anastasis DB Schema::
+* Anastasis Cryptography::
+* Anastasis REST API::
+* Anastasis Reducer API::
+* Authentication Methods::
+
+@end menu
+
+@node Anastasis DB Schema,Anastasis Cryptography,Top,Top
+@anchor{anastasis anastasis}@anchor{1}@anchor{anastasis 
anastasis-db-schema}@anchor{2}
+@chapter Anastasis DB Schema
+
+
+@image{anastasis-figures/anastasis-db,,,,png}
+
+@image{anastasis-figures/anastasis_challengecode,,,,png}
+
+@image{anastasis-figures/anastasis_challenge_payment,,,,png}
+
+@image{anastasis-figures/anastasis_truth,,,,png}
+
+@image{anastasis-figures/anastasis_truth_payment,,,,png}
+
+@node Anastasis Cryptography,Anastasis REST API,Anastasis DB Schema,Top
+@anchor{anastasis anastasis-cryptography}@anchor{3}
+@chapter Anastasis Cryptography
+
+
+When a user needs to interact with Anastasis, the system first derives some key
+material, but not the master secret, from the user’s @strong{identifier} using
+different HKDFs.  These HKDFs are salted using the respective escrow
+provider’s @strong{server salt}, which ensures that the accounts for the same 
user
+cannot be easily correlated across the various Anastasis servers.
+
+Each Anastasis server uses an EdDSA @strong{account key} to identify the 
account of
+the user.  The account private key is derived from the user’s 
@strong{identifier} using
+a computationally expensive cryptographic hash function.  Using an
+expensive hash algorithm is assumed to make it infeasible for a weak adversary 
to
+determine account keys by brute force (without knowing the user’s identifier).
+However, it is assumed that a strong adversary performing a targeted attack can
+compute the account key pair.
+
+The public account key is Crockford base32-encoded in the URI to identify the
+account, and used to sign requests.  These signatures are also provided in
+base32-encoding and transmitted using the HTTP header
+“Anastasis-Account-Signature”.
+
+When confidential data is uploaded to an Anastasis server, the respective
+payload is encrypted using AES-GCM with a symmetric key and initialization
+vector derived from the @strong{identifier} and a high-entropy @strong{nonce}. 
 The
+nonce and the GCM tag are prepended to the ciphertext before being uploaded to
+the Anastasis server.  This is done whenever confidential data is stored with
+the server.
+
+The @strong{core secret} of the user is (AES) encrypted using a symmetric 
@strong{master
+key}.  Recovering this master key requires the user to satisfy a particular
+@strong{policy}.  Policies specify a set of @strong{escrow methods}, each of 
which leads
+the user to a @strong{key share}. Combining those key shares (by hashing) 
allows
+the user to obtain a @strong{policy key}, which can be used to decrypt the 
@strong{master
+key}.  There can be many policies, satisfying any of these will allow the
+user to recover the master key.  A @strong{recovery document} contains the
+encrypted @strong{core secret}, a set of escrow methods and a set of policies.
+
+@menu
+* Key derivations::
+* Key Usage::
+* Availability Considerations::
+
+@end menu
+
+@node Key derivations,Key Usage,,Anastasis Cryptography
+@anchor{anastasis key-derivations}@anchor{4}
+@section Key derivations
+
+
+EdDSA and ECDHE public keys are always points on Curve25519 and represented
+using the standard 256 bit Ed25519 compact format.  The binary representation
+is converted to Crockford Base32 when transmitted inside JSON or as part of
+URLs.
+
+To start, a user provides their private, unique and unforgettable
+@strong{identifier} as a seed to identify their account.  For example, this 
could
+be a social security number together with their full name.  Specifics may
+depend on the cultural context, in this document we will simply refer to this
+information as the @strong{identifier}.
+
+This identifier will be first hashed with Argon2, to provide a @strong{kdf_id}
+which will be used to derive other keys later. The Hash must also include the
+respective @strong{server_salt}. This also ensures that the @strong{kdf_id} is 
different
+on each server. The use of Argon2 and the respective @strong{server_salt} is 
intended
+to make it difficult to brute-force @strong{kdf_id} values and help protect 
the user’s
+privacy. Also this ensures that the @strong{kdf_id}s on every server differs. 
However,
+we do not assume that the @strong{identifier} or the @strong{kdf_id} cannot be
+determined by an adversary performing a targeted attack, as a user’s
+@strong{identifier} is likely to always be known to state actors and may
+likely also be available to other actors.
+
+@example
+kdf_id := Argon2( identifier, server_salt, keysize )
+@end example
+
+@strong{identifier}: The secret defined from the user beforehand.
+
+@strong{server_salt}: The salt from the Server.
+
+@strong{keysize}: The desired output size of the KDF, here 32 bytes.
+
+@menu
+* Verification::
+* Encryption::
+
+@end menu
+
+@node Verification,Encryption,,Key derivations
+@anchor{anastasis verification}@anchor{5}
+@subsection Verification
+
+
+For users to authorize “policy” operations we need an EdDSA key pair.  As we
+cannot assure that the corresponding private key is truly secret, such policy
+operations must never be destructive: Should an adversary learn the private
+key, they could access (and with the @strong{kdf_id} decrypt) the user’s 
policy (but
+not the core secret), or upload a new version of the
+@strong{encrypted recovery document} (but not delete an existing version).
+
+For the generation of the private key we use the @strong{kdf_id} as the 
entropy source,
+hash it to derive a base secret which will then be processed to fit the
+requirements for EdDSA private keys.  From the private key we can then
+generate the corresponding public key.  Here, “ver” is used as a salt for the
+HKDF to ensure that the result differs from other cases where we hash
+@strong{kdf_id}.
+
+@example
+ver_secret := HKDF(kdf_id, "ver", keysize)
+eddsa_priv := eddsa_d_to_a(ver_secret)
+eddsa_pub := get_EdDSA_Pub(eddsa_priv)
+@end example
+
+@strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 
for the extraction phase, then HMAC-SHA256 is used for expansion phase.
+
+@strong{kdf_id}: Hashed identifier.
+
+@strong{key_size}: Size of the output, here 32 bytes.
+
+@strong{ver_secret}: Derived key from the kdf_id, serves as intermediate step 
for the generation of the private key.
+
+@strong{eddsa_d_to_a()}: Function which converts the ver_key to a valid EdDSA 
private key. Specifically, assuming the value eddsa_priv is in a 32-byte array 
“digest”, the function clears and sets certain bits as follows:
+
+@example
+digest[0] = (digest[0] & 0x7f) | 0x40;
+digest[31] &= 0xf8;
+@end example
+
+@strong{eddsa_priv}: The generated EdDSA private key.
+
+@strong{eddsa_pub}: The generated EdDSA public key.
+
+@node Encryption,,Verification,Key derivations
+@anchor{anastasis encryption}@anchor{6}
+@subsection Encryption
+
+
+For symmetric encryption of data we use AES256-GCM. For this we need a
+symmetric key and an initialization vector (IV).  To ensure that the
+symmetric key changes for each encryption operation, we compute the
+key material using an HKDF over a nonce and the kdf_id.
+
+@example
+(iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)
+@end example
+
+@strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 
for the extraction phase, then HMAC-SHA256 is used for expansion phase.
+
+@strong{kdf_id}: Hashed identifier.
+
+@strong{keysize}: Size of the AES symmetric key, here 32 bytes.
+
+@strong{ivsize}: Size of the AES GCM IV, here 12 bytes.
+
+@strong{prekey}: Original key material.
+
+@strong{nonce}: 32-byte nonce, must never match “ver” (which it cannot as the 
length is different). Of course, we must
+avoid key reuse. So, we have to use different nonces to get different keys and 
IVs (see below).
+
+@strong{key}: Symmetric key which is later used to encrypt the documents with 
AES256-GCM.
+
+@strong{iv}: IV which will be used for AES-GCM.
+
+@node Key Usage,Availability Considerations,Key derivations,Anastasis 
Cryptography
+@anchor{anastasis key-usage}@anchor{7}
+@section Key Usage
+
+
+The keys we have generated are then used to encrypt the @strong{recovery 
document} and
+the @strong{key_share} of the user.
+
+@menu
+* Encryption: Encryption<2>.
+* Signatures::
+
+@end menu
+
+@node Encryption<2>,Signatures,,Key Usage
+@anchor{anastasis id1}@anchor{8}
+@subsection Encryption
+
+
+Before every encryption a 32-byte nonce is generated.
+From this the symmetric key is computed as described above.
+We use AES256-GCM for the encryption of the @strong{recovery document} and
+the @strong{key_share}.  To ensure that the key derivation for the encryption
+of the @strong{recovery document} differs fundamentally from that of an
+individual @strong{key share}, we use different salts (“erd” and “eks” 
respectively).
+
+@example
+(iv0, key0) = HKDF(key_id, nonce0, "erd", keysize + ivsize)
+(encrypted_recovery_document, aes_gcm_tag) = AES256_GCM(recovery_document, 
key0, iv0)
+(iv_i, key_i) = HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize)
+(encrypted_key_share_i, aes_gcm_tag_i) = AES256_GCM(key_share_i, key_i, iv_i)
+@end example
+
+@strong{encrypted_recovery_document}: The encrypted @strong{recovery document} 
which contains the escrow methods, policies
+and the encrypted @strong{core secret}.
+
+@strong{nonce0}: Nonce which is used to generate @emph{key0} and @emph{iv0} 
which are used for the encryption of the @emph{recovery document}.
+Nonce must contain the string “ERD”.
+
+@strong{optional data}: Key material that optionally is contributed from the 
authentication method to further obfuscate the key share from the escrow 
provider.
+
+@strong{encrypted_key_share_i}: The encrypted @strong{key_share} which the 
escrow provider must release upon successful authentication.
+Here, @strong{i} must be a positive number used to iterate over the various 
@strong{key shares} used for the various @strong{escrow methods}
+at the various providers.
+
+@strong{nonce_i}: Nonce which is used to generate @emph{key_i} and @emph{iv_i} 
which are used for the encryption of the @strong{key share}. @strong{i} must be
+the same number as specified above for @emph{encrypted_key_share_i}. Nonce 
must contain the string “EKS” plus the according @emph{i}.
+
+As a special rule, when a @strong{security question} is used to authorize 
access to an
+@strong{encrypted_key_share_i}, then the salt “eks” is replaced with an 
(expensive) hash
+of the answer to the security question as an additional way to make the key 
share
+inaccessible to those who do not have the answer:
+
+@example
+powh = POW_HASH (qsalt, answer)
+ekss = HKDF("Anastasis-secure-question-uuid-salting",
+            powh,
+            uuid);
+(iv_i, key_i) = HKDF(key_id, nonce_i, ekss, [optional data], keysize + ivsize)
+@end example
+
+@strong{qsalt}: salt value used to hash answer to satisfy the challenge to 
prevent the provider from determining the answer via guessing.
+
+@strong{answer}: answer to the security question, in UTF-8, as entered by the 
user.
+
+@strong{powh}: result of the (expensive, proof-of-work) hash algorithm.
+
+@strong{uuid}: UUID of the challenge associated with the security question and 
the encrypted key share.
+
+@strong{ekss}: Replacement salt to be used instead of “eks” when deriving the 
key to encrypt/decrypt the key share.
+
+@node Signatures,,Encryption<2>,Key Usage
+@anchor{anastasis signatures}@anchor{9}
+@subsection Signatures
+
+
+The EdDSA keys are used to sign the data sent from the client to the
+server. Everything the client sends to server is signed. The following
+algorithm is equivalent for @strong{Anastasis-Policy-Signature}.
+
+@example
+(anastasis-account-signature) = eddsa_sign(h_body, eddsa_priv)
+ver_res = eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)
+@end example
+
+@strong{anastasis-account-signature}: Signature over the SHA-512 hash of the 
body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD} 
(1400) (see GNUnet EdDSA signature API for the use of purpose).
+
+@strong{h_body}: The hashed body.
+
+@strong{ver_res}: A boolean value. True: Signature verification passed, False: 
Signature verification failed.
+
+When requesting policy downloads, the client must also provide a signature:
+
+@example
+(anastasis-account-signature) = eddsa_sign(version, eddsa_priv)
+ver_res = eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)
+@end example
+
+@strong{anastasis-account-signature}: Signature over the SHA-512 hash of the 
body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} 
(1401) (see GNUnet EdDSA signature API for the use of purpose).
+
+@strong{version}: The version requested as a 64-bit integer, 2^64-1 for the 
“latest version”.
+
+@strong{ver_res}: A boolean value. True: Signature verification passed, False: 
Signature verification failed.
+
+@node Availability Considerations,,Key Usage,Anastasis Cryptography
+@anchor{anastasis availability-considerations}@anchor{a}
+@section Availability Considerations
+
+
+Anastasis considers two main threats against availability. First, the
+Anastasis server operators must be protected against denial-of-service attacks
+where an adversary attempts to exhaust the operator’s resources.  The API 
protects
+against these attacks by allowing operators to set fees for all
+operations. Furthermore, all data stored comes with an expiration logic, so an
+attacker cannot force servers to store data indefinitely.
+
+A second availability issue arises from strong adversaries that may be able to
+compute the account keys of some user.  While we assume that such an adversary
+cannot successfully authenticate against the truth, the account key does
+inherently enable these adversaries to upload a new policy for the account.
+This cannot be prevented, as the legitimate user must be able to set or change
+a policy using only the account key.  To ensure that an adversary cannot
+exploit this, policy uploads first of all never delete existing policies, but
+merely create another version.  This way, even if an adversary uploads a
+malicious policy, a user can still retrieve an older version of the policy to
+recover access to their data.  This append-only storage for policies still
+leaves a strong adversary with the option of uploading many policies to
+exhaust the Anastasis server’s capacity.  We limit this attack by requiring a
+policy upload to include a reference to a @strong{payment identifier} from a 
payment
+made by the user.  Thus, a policy upload requires both knowledge of the
+@strong{identity} and making a payment.  This effectively prevents and 
adversary
+from using the append-only policy storage from exhausting Anastasis server
+capacity.
+
+@node Anastasis REST API,Anastasis Reducer API,Anastasis Cryptography,Top
+@anchor{anastasis anastasis-rest-api}@anchor{b}
+@chapter Anastasis REST API
+
+@anchor{anastasis salt}@anchor{c}
+@menu
+* Receiving Configuration::
+* Receiving Terms of Service::
+* Manage policy::
+* Managing truth::
+
+@end menu
+
+@node Receiving Configuration,Receiving Terms of Service,,Anastasis REST API
+@anchor{anastasis config}@anchor{d}@anchor{anastasis 
receiving-configuration}@anchor{e}
+@section Receiving Configuration
+
+
+@anchor{anastasis get--config}@anchor{f}
+@deffn {HTTP Get} GET /config
+
+Obtain the configuration details of the escrow provider.
+
+@strong{Response:}
+
+Returns an @ref{10,,EscrowConfigurationResponse}.
+@anchor{anastasis escrowconfigurationresponse}@anchor{10}
+@example
+interface EscrowConfigurationResponse @{
+
+  // Protocol identifier, clarifies that this is an Anastasis provider.
+  name: "anastasis";
+
+  // libtool-style representation of the Exchange protocol version, see
+  // 
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+  // The format is "current:revision:age".
+  version: string;
+
+  // Currency in which this provider processes payments.
+  currency: string;
+
+  // supported authorization methods
+  methods: AuthorizationMethodConfig[];
+
+  // maximum policy upload size supported
+  storage_limit_in_megabytes: number;
+
+  // Payment required to maintain an account to store policy documents for a 
year.
+  // Users can pay more, in which case the storage time will go up 
proportionally.
+  annual_fee: Amount;
+
+  // Payment required to upload truth.  To be paid per upload.
+  truth_upload_fee: Amount;
+
+  // how long until the service expires deposited truth
+  // (unless refreshed via another POST)?
+  truth_lifetime: RelativeTime;
+
+  // Limit on the liability that the provider is offering with
+  // respect to the services provided.
+  liability_limit: Amount;
+
+  // salt value with 128 bits of entropy
+  // Different providers
+  // will use different high-entropy salt values. The resulting
+  // **provider salt** is then used in various operations to ensure
+  // cryptographic operations differ by provider.  A provider must
+  // never change its salt value.
+  server_salt: string;
+
+@}
+@end example
+@anchor{anastasis authorizationmethodconfig}@anchor{11}
+@example
+interface AuthorizationMethodConfig @{
+  // name of the authorization method
+  type: string;
+
+  // Fee for accessing key share using this method
+  cost: Amount;
+
+@}
+@end example
+@end deffn
+
+@node Receiving Terms of Service,Manage policy,Receiving 
Configuration,Anastasis REST API
+@anchor{anastasis receiving-terms-of-service}@anchor{12}@anchor{anastasis 
terms}@anchor{13}
+@section Receiving Terms of Service
+
+
+@anchor{anastasis get--terms}@anchor{14}
+@deffn {HTTP Get} GET /terms
+
+Obtain the terms of service provided by the escrow provider.
+
+@strong{Response:}
+
+Returns the terms of service of the provider, in the best language
+and format available based on the client’s request.
+@end deffn
+
+@anchor{anastasis get--privacy}@anchor{15}
+@deffn {HTTP Get} GET /privacy
+
+Obtain the privacy poliy of the service provided by the escrow provider.
+
+@strong{Response:}
+
+Returns the privacy policy of the provider, in the best language
+and format available based on the client’s request.
+@end deffn
+
+@node Manage policy,Managing truth,Receiving Terms of Service,Anastasis REST 
API
+@anchor{anastasis id2}@anchor{16}@anchor{anastasis manage-policy}@anchor{17}
+@section Manage policy
+
+
+This API is used by the Anastasis client to deposit or request encrypted
+recovery documents with the escrow provider.  Generally, a client will deposit
+the same encrypted recovery document with each escrow provider, but provide
+a different truth to each escrow provider.
+
+Operations by the client are identified and authorized by @code{$ACCOUNT_PUB}, 
which
+should be kept secret from third parties. @code{$ACCOUNT_PUB} should be an 
account
+public key using the Crockford base32-encoding.
+
+In the following, UUID is always defined and used according to RFC 
4122@footnote{https://tools.ietf.org/html/rfc4122}.
+
+@anchor{anastasis get--policy-$ACCOUNT_PUB[?version=$NUMBER]}@anchor{18}
+@deffn {HTTP Get} GET /policy/$ACCOUNT_PUB[?version=$NUMBER]
+
+Get the customer’s encrypted recovery document.  If “version”
+is not specified, the server returns the latest available version.  If
+“version” is specified, returns the policy with the respective
+“version”.  The response must begin with the nonce and
+an AES-GCM tag and continue with the ciphertext.  Once decrypted, the
+plaintext is expected to contain:
+
+
+@itemize *
+
+@item
+the escrow policy
+
+@item
+the separately encrypted master public key
+@end itemize
+
+Note that the key shares required to decrypt the master public key are
+not included, as for this the client needs to obtain authorization.
+The policy does provide sufficient information for the client to determine
+how to authorize requests for @strong{truth}.
+
+The client MAY provide an “If-None-Match” header with an Etag.
+In that case, the server MUST additionally respond with an “304” status
+code in case the resource matches the provided Etag.
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 200 
OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
+
+The escrow provider responds with an @ref{19,,EncryptedRecoveryDocument} 
object.
+
+@item 304 Not 
modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The client requested the same resource it already knows.
+
+@item 400 Bad 
request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
+
+The $ACCOUNT_PUB is not an EdDSA public key.
+
+@item 402 Payment 
Required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The account’s balance is too low for the specified operation.
+See the Taler payment protocol specification for how to pay.
+
+@item 403 
Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The required account signature was invalid.
+
+@item 404 Not 
found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
+
+The requested resource was not found.
+@end table
+
+@emph{Anastasis-Version}: $NUMBER — The server must return actual version of 
the encrypted recovery document via this header.
+If the client specified a version number in the header of the request, the 
server must return that version. If the client
+did not specify a version in the request, the server returns latest version of 
the @ref{19,,EncryptedRecoveryDocument}.
+
+@emph{Etag}: Set by the server to the Base32-encoded SHA512 hash of the body. 
Used for caching and to prevent redundancies. The server MUST send the Etag if 
the status code is 200 OK.
+
+@emph{If-None-Match}: If this is not the very first request of the client, 
this contains the Etag-value which the client has received before from the 
server.
+The client SHOULD send this header with every request (except for the first 
request) to avoid unnecessary downloads.
+
+@emph{Anastasis-Account-Signature}: The client must provide Base-32 encoded 
EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire 
to download the requested encrypted recovery document.  The purpose used MUST 
be @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} (1401).
+@end deffn
+
+@anchor{anastasis post--policy-$ACCOUNT_PUB}@anchor{1a}
+@deffn {HTTP Post} POST /policy/$ACCOUNT_PUB
+
+Upload a new version of the customer’s encrypted recovery document.
+While the document’s structure is described in JSON below, the upload
+should just be the bytestream of the raw data (i.e. 32-byte nonce followed
+by 16-byte tag followed by the encrypted document).
+If the request has been seen before, the server should do nothing, and 
otherwise store the new version.
+The body must begin with a nonce, an AES-GCM tag and continue with the 
ciphertext.  The format
+is the same as specified for the response of the GET method. The
+Anastasis server cannot fully validate the format, but MAY impose
+minimum and maximum size limits.
+
+@strong{Request}:
+
+@*Query Parameters:
+
+@itemize *
+
+@item
+@code{pay} – Optional argument, any non-empty value will do,
+suggested is @code{y} for @code{yes}.
+The client insists on making a payment for the respective
+account, even if this is not yet required. The server
+will respond with a @code{402 Payment required}, but only
+if the rest of the request is well-formed (account
+signature must match).  Clients that do not actually
+intend to make a new upload but that only want to pay
+may attempt to upload the latest backup again, as this
+option will be checked before the @code{304 Not modified}
+case.
+
+@item
+@code{timeout_ms=NUMBER} – @emph{Optional.}  If specified, the Anastasis 
server will
+wait up to @code{timeout_ms} milliseconds for completion of the payment before
+sending the HTTP response.  A client must never rely on this behavior, as the
+backend may return a response immediately.
+@end itemize
+
+
+@emph{If-None-Match}: This header MUST be present and set to the SHA512 hash 
(Etag) of the body by the client.
+The client SHOULD also set the “Expect: 100-Continue” header and wait for “100 
continue”
+before uploading the body.  The server MUST
+use the Etag to check whether it already knows the encrypted recovery document 
that is about to be uploaded.
+The server MUST refuse the upload with a “304” status code if the Etag matches
+the latest version already known to the server.
+
+@emph{Anastasis-Policy-Signature}: The client must provide Base-32 encoded 
EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire 
to upload an encrypted recovery document.
+
+@emph{Payment-Identifier}: Base-32 encoded 32-byte payment identifier that was 
included in a previous payment (see 402 status code). Used to allow the server 
to check that the client paid for the upload (to protect the server against DoS 
attacks) and that the client knows a real secret of financial value (as the 
@strong{kdf_id} might be known to an attacker). If this header is missing in 
the client’s request (or the associated payment has exceeded the upload limit), 
the server must retur [...]
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 204 No 
content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
+
+The encrypted recovery document was accepted and stored.  “Anastasis-Version” 
and “Anastasis-UUID” headers
+indicate what version and UUID was assigned to this encrypted recovery 
document upload by the server.
+
+@item 304 Not 
modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The same encrypted recovery document was previously accepted and stored.  
“Anastasis-Version” header
+indicates what version was previously assigned to this encrypted recovery 
document.
+
+@item 400 Bad 
request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
+
+The @code{$ACCOUNT_PUB} is not an EdDSA public key or mandatory headers are 
missing.
+The response body MUST elaborate on the error using a Taler error code in the 
typical JSON encoding.
+
+@item 402 Payment 
required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The account’s balance is too low for the specified operation.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 403 
Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The required account signature was invalid.  The response body may elaborate 
on the error.
+
+@item 413 Request entity too 
large@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14}:
+
+The upload is too large @emph{or} too small. The response body may elaborate 
on the error.
+@end table
+
+@strong{Details:}
+@anchor{anastasis encryptedrecoverydocument}@anchor{19}
+@example
+interface EncryptedRecoveryDocument @{
+  // Nonce used to compute the (iv,key) pair for encryption of the
+  // encrypted_compressed_recovery_document.
+  nonce: [32]; //bytearray
+
+  // Authentication tag
+  aes_gcm_tag: [16]; //bytearray
+
+  // Variable-size encrypted recovery document. After decryption,
+  // this contains a gzip compressed JSON-encoded `RecoveryDocument`.
+  // The nonce of the HKDF for this encryption must include the
+  // string "ERD".
+  encrypted_compressed_recovery_document: []; //bytearray of undefined length
+
+@}
+@end example
+@anchor{anastasis recoverydocument}@anchor{1b}
+@example
+interface RecoveryDocument @{
+  // Account identifier at backup provider, AES-encrypted with
+  // the (symmetric) master_key, i.e. an URL
+  // https://sync.taler.net/$BACKUP_ID and
+  // a private key to decrypt the backup.  Anastasis is oblivious
+  // to the details of how this is ultimately encoded.
+  backup_account: []; //bytearray of undefined length
+
+  // List of escrow providers and selected authentication method
+  methods: EscrowMethod[];
+
+  // List of possible decryption policies
+  policy: DecryptionPolicy[];
+
+@}
+@end example
+@anchor{anastasis escrowmethod}@anchor{1c}
+@example
+interface EscrowMethod @{
+  // URL of the escrow provider (including possibly this Anastasis server)
+  provider_url : string;
+
+  // Type of the escrow method (e.g. security question, SMS etc.)
+  escrow_type: string;
+
+  // UUID of the escrow method (see /truth/ API below).
+  uuid: string;
+
+  // Key used to encrypt the `Truth` this `EscrowMethod` is related to.
+  // Client has to provide this key to the server when using /truth/
+  truth_encryption_key: [32]; //bytearray
+
+  // Salt used to encrypt the truth on the Anastasis server.
+  truth_salt: [32]; //bytearray
+
+  // The challenge to give to the user (i.e. the security question
+  // if this is challenge-response).
+  // (Q: as string in base32 encoding?)
+  // (Q: what is the mime-type of this value?)
+  //
+  // For some methods, this value may be absent.
+  //
+  // The plaintext challenge is not revealed to the
+  // Anastasis server.
+  challenge: []; //bytearray of undefined length
+
+@}
+@end example
+@anchor{anastasis decryptionpolicy}@anchor{1d}
+@example
+interface DecryptionPolicy @{
+  // Salt included to encrypt master key share when
+  // using this decryption policy.
+  policy_salt: [32]; //bytearray
+
+  // Master key, AES-encrypted with key derived from
+  // salt and keyshares revealed by the following list of
+  // escrow methods identified by UUID.
+  encrypted_master_key: [32]; //bytearray
+
+  // List of escrow methods identified by their uuid.
+  uuid: string[];
+
+@}
+@end example
+@end deffn
+
+@node Managing truth,,Manage policy,Anastasis REST API
+@anchor{anastasis managing-truth}@anchor{1e}@anchor{anastasis truth}@anchor{1f}
+@section Managing truth
+
+
+This API is used by the Anastasis client to deposit @strong{truth} or request 
a (encrypted) @strong{key share} with
+the escrow provider.
+
+An @strong{escrow method} specifies an Anastasis provider and how the user 
should
+authorize themself.  The @strong{truth} API allows the user to provide the
+(encrypted) key share to the respective escrow provider, as well as auxiliary
+data required for such a respective escrow method.
+
+An Anastasis-server may store truth for free for a certain time period, or
+charge per truth operation using GNU Taler.
+
+@anchor{anastasis post--truth-$UUID}@anchor{20}
+@deffn {HTTP Post} POST /truth/$UUID
+
+Upload a @ref{21,,TruthUploadRequest}-Object according to the policy the 
client created before (see @ref{1b,,RecoveryDocument}).
+If request has been seen before, the server should do nothing, and otherwise 
store the new object.
+
+@strong{Request:}
+
+@*Query Parameters:
+
+@itemize *
+
+@item
+@code{timeout_ms=NUMBER} – @emph{Optional.}  If specified, the Anastasis 
server will
+wait up to @code{timeout_ms} milliseconds for completion of the payment before
+sending the HTTP response.  A client must never rely on this behavior, as the
+backend may return a response immediately.
+@end itemize
+
+
+@strong{Response:}
+
+
+@table @asis
+
+@item 204 No 
content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
+
+Truth stored successfully.
+
+@item 304 Not 
modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
+
+The same truth was previously accepted and stored under this UUID.  The
+Anastasis server must still update the expiration time for the truth when 
returning
+this response code.
+
+@item 402 Payment 
required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+This server requires payment to store truth per item.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 409 
Conflict@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10}:
+
+The server already has some truth stored under this UUID. The client should 
check that it
+is generating UUIDs with enough entropy.
+
+@item 412 Precondition 
failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13}:
+
+The selected authentication method is not supported on this provider.
+@end table
+
+@strong{Details:}
+@anchor{anastasis truthuploadrequest}@anchor{21}
+@example
+interface TruthUploadRequest @{
+  // Contains the information of an interface `EncryptedKeyShare`, but simply
+  // as one binary block (in Crockford Base32 encoding for JSON).
+  key_share_data: []; //bytearray
+
+  // Key share method, i.e. "security question", "SMS", "e-mail", ...
+  type: string;
+
+  // Nonce used to compute the (iv,key) pair for encryption of the
+  // encrypted_truth.
+  nonce: [32]; //bytearray
+
+  // Authentication tag of encrypted_truth
+  aes_gcm_tag: [16]; //bytearray
+
+  // Variable-size truth. After decryption,
+  // this contains the ground truth, i.e. H(challenge answer),
+  // phone number, e-mail address, picture, fingerprint, ...
+  // **base32 encoded**.
+  //
+  // The nonce of the HKDF for this encryption must include the
+  // string "ECT".
+  encrypted_truth: [80]; //bytearray
+
+  // mime type of truth, i.e. text/ascii, image/jpeg, etc.
+  truth_mime: string;
+
+@}
+@end example
+@end deffn
+
+@anchor{anastasis get--truth-$UUID[?response=$H_RESPONSE]}@anchor{22}
+@deffn {HTTP Get} GET /truth/$UUID[?response=$H_RESPONSE]
+
+Get the stored encrypted key share. If @code{$H_RESPONSE} is specified by the 
client, the server checks
+if @code{$H_RESPONSE} matches the expected response specified before within 
the @ref{21,,TruthUploadRequest} (see encrypted_truth).
+Also, the user has to provide the correct @emph{truth_encryption_key} with 
every get request (see below).
+When @code{$H_RESPONSE} is correct, the server responds with the encrypted key 
share.
+The encrypted key share is returned simply as a byte array and not in JSON 
format.
+
+@strong{Response}:
+
+
+@table @asis
+
+@item 200 
OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
+
+@ref{23,,EncryptedKeyShare} is returned in body (in binary).
+
+@item 202 
Accepted@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3}:
+
+The escrow provider will respond out-of-band (i.e. SMS).
+The body may contain human-readable instructions on next steps.
+
+@item >>208 Already Reported<<:
+
+An authentication challenge was recently send, client should
+simply respond to the pending challenge.
+
+@item 303 See 
other@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4}:
+
+The provider redirects for authentication (i.e. video identification/WebRTC).
+If the client is not a browser, it should launch a browser at the URL
+given in the “Location” header and allow the user to re-try the operation
+after successful authorization.
+
+@item 402 Payment 
required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
+
+The service requires payment for access to truth.
+See the Taler payment protocol specification for how to pay.
+The response body MAY provide alternative means for payment.
+
+@item 403 
Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
+
+The server requires a valid “response” to the challenge associated with the 
UUID.
+
+@item 404 Not 
found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
+
+The server does not know any truth under the given UUID.
+
+@item 410 
Gone@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11}:
+
+The server has not (recently) issued a challenge under the given UUID,
+but a reply was provided. (This does not apply for secure question.)
+
+@item 417 Expectation 
Failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18}:
+
+The decrypted ‘truth’ does not match the expectations of the authentication
+backend, i.e. a phone number for sending an SMS is not a number, or
+an e-mail address for sending an E-mail is not a valid e-mail address.
+
+@item 503 Service 
Unavailable@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4}:
+
+Server is out of Service.
+@end table
+
+@emph{Truth-Decryption-Key}: Key used to encrypt the @strong{truth} (see 
encrypted_truth within @ref{21,,TruthUploadRequest}) and which has to provided 
by the user. The key is stored with
+the according @ref{1c,,EscrowMethod}. The server needs this key to get the 
info out of @ref{21,,TruthUploadRequest} needed to verify the @code{$RESPONSE}.
+
+@strong{Details:}
+@anchor{anastasis encryptedkeyshare}@anchor{23}
+@example
+interface EncryptedKeyShare @{
+  // Nonce used to compute the decryption (iv,key) pair.
+  nonce_i: [32]; //bytearray
+
+  // Authentication tag
+  aes_gcm_tag_i: [16]; //bytearray
+
+  // Encrypted key-share in base32 encoding.
+  // After decryption, this yields a `KeyShare`.  Note that
+  // the `KeyShare` MUST be encoded as a fixed-size binary
+  // block (instead of in JSON encoding).
+  //
+  // HKDF for the key generation must include the
+  // string "eks" as salt.
+  // Depending on the method,
+  // the HKDF may additionally include
+  // bits from the response (i.e. some hash over the
+  // answer to the security question)
+  encrypted_key_share_i: [32]; //bytearray
+
+@}
+@end example
+@anchor{anastasis keyshare}@anchor{24}
+@example
+interface KeyShare @{
+  // Key material to concatenate with policy_salt and KDF to derive
+  // the key to decrypt the master key.
+  key_share: [32]; //bytearray
+
+  // Signature over method, uuid, and key_share.
+  account_sig: EddsaSignature;
+
+@}
+@end example
+@end deffn
+
+@node Anastasis Reducer API,Authentication Methods,Anastasis REST API,Top
+@anchor{anastasis anastasis-reducer-api}@anchor{25}
+@chapter Anastasis Reducer API
+
+
+This section describes the Anastasis Reducer API which is used by client 
applications
+to store or load the different states the client application can have.
+The reducer takes a @ref{26,,state} in JSON syntax and returns the new state 
in JSON syntax.
+
+For example a @strong{state} may take the following structure:
+
+@example
+@{
+  "backup_state": "CONTINENT_SELECTING",
+  "continents": [
+    "Europe",
+    "North_America"
+  ]
+@}
+@end example
+
+The new state depends on the previous one and on the transition 
@ref{27,,action} with its
+arguments given to the reducer. A @strong{transition argument} also is a 
statement in JSON syntax:
+
+@example
+@{
+  "continent": "Europe"
+@}
+@end example
+
+The new state returned by the reducer with the state and transition argument 
defined
+above would look like following for the transition @ref{27,,action} 
“select_continent”:
+
+@example
+@{
+  "backup_state": "COUNTRY_SELECTING",
+  "continents": [
+    "Europe",
+    "North_America"
+  ],
+  "selected_continent": "Europe",
+  "countries": [
+    @{
+      "code": "ch",
+      "name": "Switzerland",
+      "continent": "Europe",
+      "name_i18n": @{
+        "de_DE": "Schweiz",
+        "de_CH": "Schwiiz",
+        "fr": "Suisse",
+        "en": "Swiss"
+      @},
+      "currency": "CHF"
+    @},
+    @{
+      "code": "de",
+      "name": "Germany",
+      "continent": "Europe",
+      "continent_i18n": @{
+        "de": "Europa"
+      @},
+      "name_i18n": @{
+        "de_DE": "Deutschland",
+        "de_CH": "Deutschland",
+        "fr": "Allemagne",
+        "en": "Germany"
+      @},
+      "currency": "EUR"
+    @}
+  ]
+@}
+@end example
+
+@menu
+* States::
+* Backup Reducer::
+* Recovery Reducer::
+* Reducer transitions::
+
+@end menu
+
+@node States,Backup Reducer,,Anastasis Reducer API
+@anchor{anastasis states}@anchor{28}
+@section States
+
+
+Overall, the reducer knows the following states:
+
+@quotation
+
+
+@itemize -
+
+@item
+
+@table @asis
+
+@item @strong{ERROR}: The transition lead to an error. No further transitions 
are possible from
+
+this state, but the client may want to continue from a previous state.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{CONTINENT_SELECTING}: The user should specify the continent 
where they are living,
+
+so that we can show a list of countries to choose from.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{COUNTRY_SELECTING}: The user should specify the country where 
they are living,
+
+so that we can determine appropriate attributes, currencies and Anastasis
+providers.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{USER_ATTRIBUTES_COLLECTING}: The user should provide the 
country-specific personal
+
+attributes.
+@end table
+
+@item
+
+@table @asis
+
+@item @strong{AUTHENTICATIONS_EDITING}: The user should add authentication 
methods to be used
+
+during recovery.
+@end table
+
+@item
+@strong{POLICIES_REVIEWING}: The user should review the recovery policies.
+
+@item
+@strong{SECRET_EDITING}: The user should edit the secret to be backed up.
+
+@item
+
+@table @asis
+
+@item @strong{TRUTHS_PAYING}: The user needs to pay for one or more uploads of 
data associated
+
+with an authentication method.
+@end table
+
+@item
+@strong{POLICIES_PAYING}: The user needs to pay for storing the recovery 
policy document.
+
+@item
+@strong{BACKUP_FINISHED}: A backup has been successfully generated.
+
+@item
+
+@table @asis
+
+@item @strong{CHALLENGE_SELECTING}: The user needs to select an authorization 
challenge to
+
+proceed with recovery.
+@end table
+
+@item
+@strong{CHALLENGE_PAYING}: The user needs to pay to proceed with the 
authorization challenge.
+
+@item
+@strong{CHALLENGE_SOLVING}: The user needs to solve the authorization 
challenge.
+
+@item
+@strong{RECOVERY_FINISHED}: The secret of the user has been recovered.
+@end itemize
+@end quotation
+
+State names:
+
+@quotation
+
+
+@itemize -
+
+@item
+In SELECTING-states, the user has to choose one value out of a predefined set 
of values (for example a continent out of a set of continents).
+
+@item
+In COLLECTING-states, the user has to give certain values.
+
+@item
+In EDITING-states, the user is free to choose which values he wants to give.
+
+@item
+In REVEIWING-states, the user may make a few choices, but primarily is 
expected to affirm something.
+
+@item
+in PAYING-states, the user must make a payment.
+
+@item
+in FINISHED-states, the operation has definitively concluded.
+@end itemize
+@end quotation
+
+@node Backup Reducer,Recovery Reducer,States,Anastasis Reducer API
+@anchor{anastasis backup-reducer}@anchor{29}
+@section Backup Reducer
+
+@anchor{anastasis state}@anchor{26}@anchor{anastasis action}@anchor{27}
+
+@float Figure
+
+@image{anastasis-figures/anastasis_reducer_backup,,,fig-anastasis_reducer_backup,png}
+
+@caption{Backup states and their transitions.}
+
+@end float
+
+
+The illustration above shows the different states the reducer can have during 
a backup
+process.
+
+@node Recovery Reducer,Reducer transitions,Backup Reducer,Anastasis Reducer API
+@anchor{anastasis recovery-reducer}@anchor{2a}
+@section Recovery Reducer
+
+
+
+@float Figure
+
+@image{anastasis-figures/anastasis_reducer_recovery,,,fig-anastasis_reducer_recovery,png}
+
+@caption{Recovery states and their transitions.}
+
+@end float
+
+
+The illustration above shows the different states the reducer can have during 
a recovery
+process.
+
+@node Reducer transitions,,Recovery Reducer,Anastasis Reducer API
+@anchor{anastasis reducer-transitions}@anchor{2b}
+@section Reducer transitions
+
+
+In the following, the individual transitions will be specified in more detail.
+Note that we only show fields added by the reducer, typically the previous
+state is preserved to enable “back” transitions to function smoothly.
+
+@menu
+* Initial state::
+* Common transitions::
+* Backup transitions::
+* Recovery transitions::
+
+@end menu
+
+@node Initial state,Common transitions,,Reducer transitions
+@anchor{anastasis initial-state}@anchor{2c}
+@subsection Initial state
+
+
+The initial states for backup and recovery processes are:
+
+@strong{Initial backup state:}
+
+@example
+@{
+  "backup_state": "CONTINENT_SELECTING",
+  "continents": [
+    "Europe",
+    "North America"
+  ]
+@}
+@end example
+
+@strong{Initial recovery state:}
+
+@example
+@{
+  "recovery_state": "CONTINENT_SELECTING",
+  "continents": [
+    "Europe",
+    "North America"
+  ]
+@}
+@end example
+
+Here, “continents” is an array of English strings with the names of the
+continents which contain countries for which Anastasis could function (based
+on having providers that are known to operate and rules being provided for
+user attributes from those countries).
+
+For internationalization, another field “continents_i18n” may be present.
+This field would be a map of language names to arrays of translated
+continent names:
+
+@example
+@{
+  "recovery_state": "CONTINENT_SELECTING",
+  "continents": [
+    "Europe",
+    "North America"
+  ]
+  "continents_i18n":
+  @{
+    "de_DE" : [
+      "Europa",
+      "Nordamerika"
+      ],
+    "de_CH" : [
+      "Europa",
+      "Nordamerika"
+      ]
+  @}
+@}
+@end example
+
+Translations must be given in the same order as the main English array.
+
+@node Common transitions,Backup transitions,Initial state,Reducer transitions
+@anchor{anastasis common-transitions}@anchor{2d}
+@subsection Common transitions
+
+
+@strong{select_continent:}
+
+Here the user specifies the continent they live on.  Arguments (example):
+
+@example
+@{
+  "continent": "Europe"
+@}
+@end example
+
+The continent must be given using the English name from the “continents” array.
+Using a translated continent name is invalid and may result in failure.
+
+The reducer returns an updated state with a list of countries to choose from,
+for example:
+
+@example
+@{
+  "backup_state": "COUNTRY_SELECTING",
+  "selected_continent": "Europe",
+  "countries": [
+    @{
+      "code": "ch",
+      "name": "Switzerland",
+      "continent": "Europe",
+      "name_i18n": @{
+        "de_DE": "Schweiz",
+        "de_CH": "Schwiiz",
+        "fr": "Suisse",
+        "en": "Swiss"
+      @},
+      "currency": "CHF"
+    @},
+    @{
+      "code": "de",
+      "name": "Germany",
+      "continent": "Europe",
+      "continent_i18n": @{
+        "de": "Europa"
+      @},
+      "name_i18n": @{
+        "de_DE": "Deutschland",
+        "de_CH": "Deutschland",
+        "fr": "Allemagne",
+        "en": "Germany"
+      @},
+      "currency": "EUR"
+    @}
+  ]
+@}
+@end example
+
+Here “countries” is an array of countries on the “selected_continent”.  For
+each country, the “code” is the ISO 3166-1 alpha-2 country code.  The
+“continent” is only present because some countries span continents, the
+information is redundant and will always match “selected_continent”.  The
+“name” is the name of the country in English, internationalizations of the
+name may be provided in “name_i18n”.  The “currency” is @strong{an} official
+currency of the country, if a country has multiple currencies, it may appear
+multiple times in the list.  In this case, the user should select the entry
+with the currency they intend to pay with.  It is also possible for users
+to select a currency that does not match their country, but user interfaces
+should by default try to use currencies that match the user’s residence.
+
+@strong{select_country:}
+
+Selects the country (via the country code) and specifies the currency.
+The latter is needed as some countries have more than one currency,
+and some use-cases may also involve users insisting on paying with
+foreign currency.
+
+Arguments (example):
+
+@example
+@{
+  "country_code": "de",
+  "currency": "EUR"
+@}
+@end example
+
+The “country_code” must be an ISO 3166-1 alpha-2 country code from
+the array of “countries” of the reducer’s state.  The “currency”
+field must be a valid currency accepted by the Taler payment system.
+
+The reducer returns a new state with the list of attributes the
+user is expected to provide, as well as possible authentication
+providers that accept payments in the selected currency:
+
+@example
+@{
+  "backup_state": "USER_ATTRIBUTES_COLLECTING",
+  "selected_country": "de",
+  "currency": "EUR",
+  "required_attributes": [
+    @{
+      "type": "string",
+      "name": "full_name",
+      "label": "Full name",
+      "label_i18n": @{
+        "de_DE": "Vollstaendiger Name",
+        "de_CH": "Vollstaendiger. Name",
+        "fr": "Nom complet",
+        "en": "Full name"
+      @},
+      "widget": "anastasis_gtk_ia_full_name",
+      "uuid" : "9e8f463f-575f-42cb-85f3-759559997331"
+    @},
+    @{
+      "type": "date",
+      "name": "birthdate",
+      "label": "Birthdate",
+      "label_i18n": @{
+        "de_DE": "Geburtsdatum",
+        "de_CH": "Geburtsdatum",
+        "fr": "Date de naissance",
+        "en": "Birthdate"
+      @},
+      "uuid" : "83d655c7-bdb6-484d-904e-80c1058c8854"
+      "widget": "anastasis_gtk_ia_birthdate"
+    @},
+        @{
+           "type": "string",
+       "name": "tax_number",
+           "label": "Taxpayer identification number",
+           "label_i18n":@{
+                 "de_DE": "Steuerliche Identifikationsnummer",
+                 "de_CH": "Steuerliche Identifikationsnummer",
+                 "en": "German taxpayer identification number"
+           @},
+           "widget": "anastasis_gtk_ia_tax_de",
+       "uuid": "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
+           "validation-regex": "^[0-9]@{11@}$",
+           "validation-logic": "DE_TIN_check"
+        @},
+    @{
+      "type": "string",
+      "name": "social_security_number",
+      "label": "Social security number",
+      "label_i18n": @{
+        "de_DE": "Sozialversicherungsnummer",
+        "de_CH": "Sozialversicherungsnummer",
+        "fr": "Numéro de sécurité sociale",
+        "en": "Social security number"
+      @},
+      "widget": "anastasis_gtk_ia_ssn",
+          "validation-regex": "^[0-9]@{8@}[[:upper:]][0-9]@{3@}$",
+          "validation-logic": "DE_SVN_check"
+      "optional" : true
+  @}
+  ],
+  "authentication_providers": @{
+    "http://localhost:8089/": @{
+      "http_status": 200,
+      "methods": [
+        @{ "type" : "question",
+          "usage_fee" : "EUR:0.0" @},
+        @{ "type" : "sms",
+          "usage_fee" : "EUR:0.5" @}
+      ],
+      "annual_fee": "EUR:4.99",
+      "truth_upload_fee": "EUR:4.99",
+      "liability_limit": "EUR:1",
+      "currency": "EUR",
+      "truth_lifetime": @{ "d_ms" : 50000000 @},
+      "storage_limit_in_megabytes": 1,
+      "provider_name": "Anastasis 4",
+      "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+    @},
+    "http://localhost:8088/": @{
+      "http_status": 200,
+      "methods": [
+        @{ "type" : "question",
+          "usage_fee" : "EUR:0.01" @},
+        @{ "type" : "sms",
+          "usage_fee" : "EUR:0.55" @}
+      ],
+      "annual_fee": "EUR:0.99",
+      "truth_upload_fee": "EUR:3.99",
+      "liability_limit": "EUR:1",
+      "currency": "EUR",
+      "truth_lifetime": @{ "d_ms" : 50000000 @},
+      "storage_limit_in_megabytes": 1,
+      "provider_name": "Anastasis 4",
+      "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+    @}
+  @}
+@}
+@end example
+
+The array of “required_attributes” contains attributes about the user
+that must be provided includes:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{type}: the type of the attribute, for now only ‘string’ and ‘date’ are
+supported
+
+@item
+@strong{name}: the name of the attribute, this is the key under which the
+attribute value must be provided later. The name must be unique per response.
+
+@item
+@strong{label}: a human-readable description of the attribute in English.
+Translated descriptions may be provided under @strong{label_i18n}.
+
+@item
+@strong{uuid}: a UUID that uniquely identifies identical attributes across
+different countries. Useful to preserve values should the user enter
+some attributes, and then switch to another country.  Note that
+attributes must not be preserved if they merely have the same @strong{name},
+only the @strong{uuid} will be identical if the semantics is identicial.
+
+@item
+@strong{widget}: an optional name of a widget that is known to nicely render
+the attribute entry in user interfaces where named widgets are
+supported.
+
+@item
+@strong{validation-regex}: an optional extended POSIX regular expression
+that is to be used to validate (string) inputs to ensure they are
+well-formed.
+
+@item
+@strong{validation-logic}: optional name of a function that should be called
+to validate the input.  If the function is not known to the particular
+client, the respective validation can be skipped (at the expense of
+typos by users not being detected, possibly rendering secrets
+irrecoverable).
+
+@item
+@strong{optional}: optional boolean field that, if @code{true}, indicates that
+this attribute is not actually required but optional and users MAY leave
+it blank in case they do not have the requested information. Used for
+common fields that apply to some large part of the population but are
+not sufficiently universal to be actually required.
+@end itemize
+@end quotation
+
+The authentication providers are listed under a key that is the
+base URL of the service. For each provider, the following
+information is provided if the provider was successfully contacted:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status}: HTTP status code, always 200 on success.
+
+@item
+@strong{methods}: array of authentication methods supported by this
+provider. Includes the @strong{type} of the authentication method
+and the @strong{usage_fee} (how much the user must pay for authorization
+using this method during recovery).
+
+@item
+@strong{annual_fee}: fee the provider charges to store the recovery
+policy for one year.
+
+@item
+@strong{truth_upload_fee}: fee the provider charges to store a key share.
+
+@item
+@strong{truth_lifetime}: Taler-style relative time that specifies how
+long the provider will store truth data (key shares) after an upload.
+
+@item
+@strong{liability_limit}: amount the provider can be held liable for in
+case a key share or recovery document cannot be recovered due to
+provider failures.
+
+@item
+@strong{currency}: currency in which the provider wants to be paid,
+will match all of the fees.
+
+@item
+@strong{storage_limit_in_megabytes}: maximum size of an upload (for
+both recovery document and truth data) in megabytes.
+
+@item
+@strong{provider_name}: human-readable name of the provider’s business.
+
+@item
+@strong{salt}: salt value used by the provider, used to derive the
+user’s identity at this provider. Should be unique per provider,
+and must never change for a given provider.  The salt is
+base32 encoded.
+@end itemize
+@end quotation
+
+If contacting the provider failed, the information returned is:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status}: HTTP status code (if available, possibly 0 if
+we did not even obtain an HTTP response).
+
+@item
+@strong{error_code}: Taler error code, never 0.
+@end itemize
+@end quotation
+
+@strong{add_provider}:
+
+This operation can be performed in state “USER_ATTRIBUTES_COLLECTING”.  It
+adds one or more Anastasis providers to the list of providers the reducer
+should henceforth consider.  Note that removing providers is not possible at
+this time.
+
+Here, the client must provide an array with the base URLs of the
+providers to add, for example:
+
+@example
+@{
+  "urls": [
+    "http://localhost:8888/";,
+    "http://localhost:8089/";
+  ]
+@}
+@end example
+
+Note that existing providers will remain in the state.  The following is an
+example for an expected new state where the service on port 8089 is
+unreachable, the service on port 8088 was previously known, and service on
+port 8888 was now added:
+
+@example
+@{
+  "backup_state": "USER_ATTRIBUTES_COLLECTING",
+  "authentication_providers": @{
+    "http://localhost:8089/": @{
+      "error_code": 11,
+      "http_status": 0
+    @},
+    "http://localhost:8088/": @{
+      "http_status": 200,
+      "methods": [
+        @{ "type" : "question",
+          "usage_fee" : "EUR:0.01" @},
+        @{ "type" : "sms",
+          "usage_fee" : "EUR:0.55" @}
+      ],
+      "annual_fee": "EUR:0.99",
+      "truth_upload_fee": "EUR:3.99",
+      "liability_limit": "EUR:1",
+      "currency": "EUR",
+      "truth_lifetime": @{ "d_ms" : 50000000 @},
+      "storage_limit_in_megabytes": 1,
+      "provider_name": "Anastasis 4",
+      "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
+    @}
+    "http://localhost:8888/": @{
+      "methods": [
+        @{ "type" : "question",
+          "usage_fee" : "EUR:0.01" @},
+        @{ "type" : "sms",
+          "usage_fee" : "EUR:0.55" @}
+      ],
+      "annual_fee": "EUR:0.99",
+      "truth_upload_fee": "EUR:3.99",
+      "liability_limit": "EUR:1",
+      "currency": "EUR",
+      "truth_lifetime": @{ "d_ms" : 50000000 @},
+      "storage_limit_in_megabytes": 1,
+      "provider_name": "Anastasis 42",
+      "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
+    @}
+  @}
+@}
+@end example
+
+@node Backup transitions,Recovery transitions,Common transitions,Reducer 
transitions
+@anchor{anastasis backup-transitions}@anchor{2e}
+@subsection Backup transitions
+
+
+@strong{enter_user_attributes:}
+
+This transition provides the user’s personal attributes. The specific set of
+attributes required depends on the country of residence of the user.  Some
+attributes may be optional, in which case they should be omitted entirely
+(that is, not simply be set to @code{null} or an empty string).  Example
+arguments would be:
+
+@example
+@{
+  "identity_attributes": @{
+    "full_name": "Max Musterman",
+    "social_security_number": "123456789",
+    "birthdate": "2000-01-01",
+    "birthplace": "Earth"
+ @}
+@}
+@end example
+
+Note that at this stage, the state machines between backup and
+recovery diverge and the @code{recovery_state} will begin to look
+very different from the @code{backup_state}.
+
+For backups, if all required attributes are present, the reducer will
+transition to an @code{AUTHENTICATIONS_EDITING} state with the attributes added
+to it:
+
+@example
+@{
+  "backup_state": "AUTHENTICATIONS_EDITING",
+  "identity_attributes": @{
+    "full_name": "Max Musterman",
+    "social_security_number": "123456789",
+    "birthdate": "2000-01-01",
+    "birthplace": "Earth"
+  @}
+@}
+@end example
+
+If required attributes are missing, do not match the required regular
+expression or fail the custom validation logic, the reducer SHOULD transition
+to an error state indicating what was wrong about the input.  A reducer that
+does not support some specific validation logic MAY accept the invalid input
+and proceed anyway.  The error state will include a Taler error code that
+is specific to the failure, and optional details.  Example:
+
+@example
+@{
+  "backup_state": "ERROR",
+  "code": 8404,
+  "hint": "An input did not match the regular expression.",
+  "detail": "social_security_number"
+@}
+@end example
+
+Clients may safely repeat this transition to validate the user’s inputs
+until they statisfy all of the constraints.  This way, the user interface
+does not have to perform the input validation directly.
+
+@strong{add_authentication}:
+
+This transition adds an authentication method.  The method must be supported
+by one or more providers that are included in the current state.  Adding an
+authentication method requires specifying the @code{type} and 
@code{instructions} to
+be given to the user.  The @code{challenge} is encrypted and stored at the
+Anastasis provider. The specific semantics of the value depend on the
+@code{type}.  Typical challenges values are a phone number (to send an SMS to),
+an e-mail address (to send a PIN code to) or the answer to a security
+question.  Note that these challenge values will still be encrypted (and
+possibly hashed) before being given to the Anastasis providers.
+
+Note that the @code{challenge} must be given in Crockford Base32 encoding, as 
it
+MAY include binary data (such as a photograph of the user).  In the latter
+case, the optional @code{mime_type} field must be provided to give the MIME 
type
+of the value encoded in @code{challenge}.
+
+@example
+@{
+  "authentication_method":
+  @{
+    "type": "question",
+    "mime_type" : "text/plain",
+    "instructions" : "What is your favorite GNU package?",
+    "challenge" : "E1QPPS8A",
+  @}
+@}
+@end example
+
+If the information provided is valid, the reducer will add the new
+authentication method to the array of authentication methods:
+
+@example
+@{
+  "backup_state": "AUTHENTICATIONS_EDITING",
+  "authentication_methods": [
+    @{
+      "type": "question",
+      "mime_type" : "text/plain",
+      "instructions" : "What is your favorite GNU package?",
+      "challenge" : "E1QPPS8A",
+    @},
+    @{
+      "type": "email",
+      "instructions" : "E-mail to user@@*le.com",
+      "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
+    @}
+  ]
+@}
+@end example
+
+@strong{delete_authentication}:
+
+This transition can be used to remove an authentication method from the
+array of authentication methods. It simply requires the index of the
+authentication method to remove. Note that the array is 0-indexed:
+
+@example
+@{
+  "auth_method_index": 1
+@}
+@end example
+
+Assuming we begin with the state from the example above, this would
+remove the @code{email} authentication method, resulting in the following
+response:
+
+@example
+@{
+  "backup_state": "AUTHENTICATIONS_EDITING",
+  "authentication_methods": [
+    @{
+      "type": "question",
+      "mime_type" : "text/plain",
+      "instructions" : "What is your favorite GNU package?",
+      "challenge" : "gdb",
+    @}
+  ]
+@}
+@end example
+
+If the index is invalid, the reducer will instead
+transition into an ERROR state.
+
+@strong{next} (from “AUTHENTICATIONS_EDITING”):
+
+This transition confirms that the user has finished adding (or removing)
+authentication methods, and that the system should now automatically compute
+a set of reasonable recovery policies.
+
+This transition does not take any mandatory arguments.  Optional arguments can
+be provided to upload the recovery document only to a specific subset of the
+providers:
+
+@example
+@{
+  "provider_id": [
+    "http://localhost:8088/";,
+    "http://localhost:8089/";
+  ]
+@}
+@end example
+
+..note:
+
+@example
+This is currently not supported (#6760), the current implementation of the
+reducer ignores this optional argument.
+@end example
+
+The resulting state provides the suggested recovery policies in a way suitable
+for presentation to the user:
+
+@example
+@{
+  "backup_state": "POLICIES_REVIEWING",
+  "policies": [
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8088/";
+        @},
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 2,
+          "provider": "http://localhost:8087/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8088/";
+        @},
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 3,
+          "provider": "http://localhost:8089/";
+        @}
+      ]
+    @}
+  ]
+@}
+@end example
+
+For each recovery policy, the state includes the specific details of which
+authentication @code{methods} must be solved to recovery the secret using this
+policy.  The @code{methods} array specifies the index of the
+@code{authentication_method} in the @code{authentication_methods} array, as 
well as
+the provider that was selected to supervise this authentication.
+
+If no authentication method was provided, the reducer will transition into an
+ERROR state instead of suggesting policies.
+
+@strong{add_policy}:
+
+Using this transition, the user can add an additional recovery policy to the
+state.  The argument format is the same that is used in the existing state.
+An example for a possible argument would thus be:
+
+@example
+@{
+  "policy": [
+    @{
+      "auth_method_index": 1,
+      "provider": "http://localhost:8088/";
+    @},
+    @{
+      "auth_method_index": 3,
+      "provider": "http://localhost:8089/";
+    @}
+  ]
+@}
+@end example
+
+Note that the specified providers must already be in the
+@code{authentication_providers} of the state. You cannot add new providers at
+this stage.  The reducer will simply attempt to append the suggested policy to
+the “policies” array, returning an updated state:
+
+@example
+@{
+  "backup_state": "POLICIES_REVIEWING",
+  "policies": [
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 2,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 2,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8088/";
+        @},
+        @{
+          "authentication_method": 3,
+          "provider": "http://localhost:8089/";
+        @}
+      ]
+    @}
+  ]
+@}
+@end example
+
+If the new policy is invalid, for example because it add an unknown
+authentication method or the selected provider does not support the type of
+authentication, the reducer will transition into an ERROR state instead of
+adding the new policy.
+
+@strong{delete_policy:}
+
+This transition allows the deletion of a recovery policy. The argument
+simply specifies the index of the policy to delete, for example:
+
+@example
+@{
+  "policy_index": 3
+@}
+@end example
+
+Given as input the state from the example above, the expected new state would
+be:
+
+@example
+@{
+  "backup_state": "POLICIES_REVIEWING",
+  "policies": [
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 0,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 2,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @},
+    @{
+      "methods": [
+        @{
+          "authentication_method": 1,
+          "provider": "http://localhost:8089/";
+        @},
+        @{
+          "authentication_method": 2,
+          "provider": "http://localhost:8088/";
+        @}
+      ]
+    @}
+  ]
+@}
+@end example
+
+If the index given is invalid, the reducer will transition into an ERROR state
+instead of deleting a policy.
+
+@strong{next} (from “POLICIES_REVIEWING”):
+
+Using this transition, the user confirms that the policies in the current
+state are acceptable. The transition does not take any arguments.
+
+The reducer will simply transition to the @code{SECRET_EDITING} state:
+
+@example
+@{
+  "backup_state": "SECRET_EDITING",
+@}
+@end example
+
+If the array of @code{policies} is currently empty, the reducer will transition
+into an ERROR state instead of allowing the user to continue.
+
+@strong{enter_secret:}
+
+This transition provides the reducer with the actual core @code{secret} of the 
user
+that Anastasis is supposed to backup (and possibly recover). The argument is
+simply the Crockford-Base32 encoded @code{value} together with its @code{mime} 
type,
+for example:
+
+@example
+@{
+  "secret": @{
+     "value": "EDJP6WK5EG50",
+     "mime" : "text/plain"
+@}
+@end example
+
+If the application is unaware of the format, it set the @code{mime} field to 
>>`@w{`}<<null`.
+
+After adding a secret, the reducer may transition into different states
+depending on whether payment(s) are necessary.  If payments are needed, the
+@code{secret} will be stored in the state under @code{core_secret}.  
Applications
+should be careful when persisting the resulting state, as the 
@code{core_secret}
+is not protected in the @code{PAYING} states.  The @code{PAYING} states only 
differ
+in terms of what the payments are for (key shares or the recovery document),
+in all cases the state simply includes an array of Taler URIs that refer to
+payments that need to be made with the Taler wallet.
+
+If all payments are complete, the reducer will transition into the
+@code{BACKUP_FINISHED} state and (if applicable) delete the @code{core_secret} 
as an
+additional safety measure.
+
+Example results are thus:
+
+@example
+@{
+  "backup_state": "TRUTHS_PAYING",
+  "core_secret" : "DATA",
+  "payments": [
+    "taler://pay/...",
+    "taler://pay/..."
+  ]
+@}
+@end example
+
+@example
+@{
+  "backup_state": "POLICIES_PAYING",
+  "core_secret" : "DATA",
+  "payments": [
+    "taler://pay/...",
+    "taler://pay/..."
+  ]
+@}
+@end example
+
+@example
+@{
+  "backup_state": "BACKUP_FINISHED",
+@}
+@end example
+
+@strong{pay:}
+
+This transition suggests to the reducer that a payment may have been made or
+is immanent, and that the reducer should check with the Anastasis service
+provider to see if the operation is now possible.  The operation takes one
+optional argument, which is a @code{timeout} value that specifies how long the
+reducer may wait (in long polling) for the payment to complete:
+
+@example
+@{
+  "timeout":  @{ "d_ms" : 5000 @},
+@}
+@end example
+
+The specified timeout is passed on to the Anastasis service provider(s), which
+will wait this long before giving up.  If no timeout is given, the check is
+done as quickly as possible without additional delays.  The reducer will 
continue
+to either an updated state with the remaining payment requests, to the
+@code{BACKUP_FINISHED} state (if all payments have been completed and the 
backup
+finished), or into an @code{ERROR} state in case there was an irrecoverable 
error,
+indicating the specific provider and how it failed.  An example for this
+final error state would be:
+
+@example
+@{
+  "backup_state": "ERROR",
+  "http_status" : 500,
+  "upload_status" : 52,
+  "provider_url" : "https://bad.example.com/";,
+@}
+@end example
+
+Here, the fields have the following meaning:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{http_status} is the HTTP status returned by the Anastasis provider
+
+@item
+@strong{upload_status} is the Taler error code return by the provider
+
+@item
+@strong{provider_url} is the base URL of the failing provider
+@end itemize
+@end quotation
+
+In the above example, 52 would thus imply that the Anastasis provider failed to
+store information into its database.
+
+@node Recovery transitions,,Backup transitions,Reducer transitions
+@anchor{anastasis recovery-transitions}@anchor{2f}
+@subsection Recovery transitions
+
+
+@strong{enter_user_attributes:}
+
+This transition provides the user’s personal attributes. The specific set of
+attributes required depends on the country of residence of the user.  Some
+attributes may be optional, in which case they should be omitted entirely
+(that is, not simply be set to @code{null} or an empty string).  The
+arguments are identical to the >>**<<>>enter_user_attributes__<< transition 
from
+the backup process.  Example arguments would thus be:
+
+@example
+@{
+  "identity_attributes": @{
+    "full_name": "Max Musterman",
+    "social_security_number": "123456789",
+    "birthdate": "2000-01-01",
+    "birthplace": "Earth"
+  @}
+@}
+@end example
+
+However, in contrast to the backup process, the reducer will attempt to
+retrieve the latest recovery document from all known providers for the
+selected currency given the above inputs.  If a recovery document was found
+by any provider, the reducer will attempt to load it and transition to
+a state where the user can choose which challenges to satisfy:
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SELECTING",
+  "recovery_information": @{
+    "challenges": [
+      @{
+        "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
+        "cost": "TESTKUDOS:0",
+        "type": "question",
+        "instructions": "q1"
+      @},
+      @{
+        "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+        "cost": "TESTKUDOS:0",
+        "type": "email",
+        "instructions": "e-mail address m?il@@f*.bar"
+      @}
+    ],
+    "policies": [
+      [
+        @{
+          "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
+        @},
+        @{
+          "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
+        @}
+      ]
+    ],
+    "provider_url": "http://localhost:8088/";,
+    "version": 1
+  @},
+  "recovery_document": @{
+    ...
+  @}
+@}
+@end example
+
+The @code{recovery_document} is an internal representation of the recovery
+information and of no concern to the user interface. The pertinent information
+is in the @code{recovery_information}. Here, the @code{challenges} array is a 
list
+of possible challenges the user could attempt to solve next, while 
@code{policies}
+is an array of policies, with each policy being an array of challenges.
+Satisfying all of the challenges of one of the policies will enable the secret
+to be recovered.  The @code{provider_url} from where the recovery document was
+obtained and its @code{version} are also provided.  Each challenge comes with
+four mandatory fields:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{uuid}: a unique identifier of the challenge; this is what the
+UUIDs in the policies array refer to, but also this UUID may be
+included in messages sent to the user. They allow the user to
+distinguish different PIN/TANs should say the same phone number be
+used for SMS-authentication with different providers.
+
+@item
+@strong{cost}: this is the amount the Anastasis provider will charge
+to allow the user to pass the challenge.
+
+@item
+@strong{type}: this is the type of the challenge, as a string.
+
+@item
+@strong{instructions}: contains additional important hints for the user
+to allow the user to satisfy the challenge.  It typically includes
+an abbreviated form of the contact information or the security
+question. Details depend on @code{type}.
+@end itemize
+@end quotation
+
+If a recovery document was not found, either the user never performed
+a backup, entered incorrect attributes or used a provider not yet in
+the list of Anastasis providers.  Hence, the user must now either
+select a different provider, or go @code{back} and update the identity
+attributes.  In the case a recovery document was not found, the
+transition fails, returning the error code and a human-readable error
+message together with a transition failure:
+
+@example
+@{
+  "recovery_state": "ERROR",
+  "error_message": "account unknown to Anastasis server",
+  "error_code": 9,
+@}
+@end example
+
+Here, the @code{error_code} is from the @code{enum ANASTASIS_RecoveryStatus}
+and describes precisely what failed about the download, while the
+@code{error_message} is a human-readable (English) explanation of the code.
+Applications may want to translate the message using GNU gettext;
+translations should be available in the “anastasis” text domain.
+However, in general it should be sufficient to display the slightly
+more generic Taler error code that is returned with the new state.
+
+@strong{change_version:}
+
+Even if a recovery document was found, it is possible that the user
+intended to recover a different version, or recover a backup where
+the recovery document is stored at a different provider. Thus, the
+reducer allows the user to explicitly switch to a different provider
+or recovery document version using the @code{change_version} transition,
+which takes a provider URL and policy version as arguments:
+
+@example
+@{
+  "provider_url": "https://localhost:8080/";,
+  "version": 2
+@}
+@end example
+
+Note that using a version of 0 implies fetching @code{the latest version}.  The
+resulting states are the same as those of the @code{enter_user_attributes}
+transition, except that the recovery document version is not necessarily the
+latest available version at the provider.
+
+@strong{select_challenge:}
+
+Selecting a challenge takes different, depending on the state of the payment.
+A comprehensive example for @code{select_challenge} would be:
+
+@example
+@{
+    "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
+    "timeout" : @{ "d_ms" : 5000 @},
+    "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+@}
+@end example
+
+The @code{uuid} field is mandatory and specifies the selected challenge.
+The other fields are optional, and are needed in case the user has
+previously been requested to pay for the challenge.  In this case,
+the @code{payment_secret} identifies the previous payment request, and
+@code{timeout} says how long the Anastasis service should wait for the
+payment to be completed before giving up (long polling).
+
+Depending on the type of the challenge and the need for payment, the
+reducer may transition into @code{CHALLENGE_SOLVING} or @code{CHALLENGE_PAYING}
+states.  In @code{CHALLENGE_SOLVING}, the new state will primarily specify
+the selected challenge:
+
+@example
+@{
+  "backup_state": "CHALLENGE_SOLVING",
+  "selected_challenge_uuid": 
"80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
+@}
+@end example
+
+In @code{CHALLENGE_PAYING}, the new state will include instructions for payment
+in the @code{challenge_feedback}. In general, @code{challenge_feedback} 
includes
+information about attempted challenges, with the final state being 
@code{solved}:
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SELECTING",
+  "recovery_information": @{
+    // ...
+  @}
+  "challenge_feedback": @{
+    "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
+      "state" : "solved"
+    @}
+  @}
+@}
+@end example
+
+Challenges feedback for a challenge can have many different @code{state} values
+that applications must all handle. States other than @code{solved} are:
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{payment}: Here, the user must pay for a challenge. An example would be:
+
+@example
+@{
+  "backup_state": "CHALLENGE_PAYING",
+  "selected_challenge_uuid": 
"80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
+  "challenge_feedback": @{
+    "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
+     "state" : "payment",
+     "taler_pay_uri" : "taler://pay/...",
+     "provider" : "https://localhost:8080/";,
+     "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+    @}
+  @}
+@}
+@end example
+@end itemize
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{body}: Here, the server provided an HTTP reply for
+how to solve the challenge, but the reducer could not parse
+them into a known format. A mime-type may be provided and may
+help parse the details.
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SOLVING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "body",
+      "body": "CROCKFORDBASE32ENCODEDBODY",
+      "http_status": 403,
+      "mime_type" : "anything/possible"
+    @}
+  @}
+@}
+@end example
+
+@item
+@strong{hint}: Here, the server provided human-readable hint for
+how to solve the challenge.  Note that the @code{hint} provided this
+time is from the Anastasis provider and may differ from the @code{instructions}
+for the challenge under @code{recovery_information}:
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SOLVING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "hint",
+      "hint": "Recovery TAN send to email mail@@DOMAIN",
+      "http_status": 403
+    @}
+  @}
+@}
+@end example
+
+@item
+@strong{details}: Here, the server provided a detailed JSON status response
+related to solving the challenge:
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SOLVING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "details",
+      "details": @{
+        "code": 8111,
+        "hint": "The client's response to the challenge was invalid.",
+        "detail" : null
+      @},
+      "http_status": 403
+    @}
+  @}
+@}
+@end example
+@end itemize
+
+@quotation
+
+
+@itemize -
+
+@item
+@strong{redirect}: To solve the challenge, the user must visit the indicated
+Web site at @code{redirect_url}, for example to perform video authentication:
+@end itemize
+
+@quotation
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SOLVING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "redirect",
+      "redirect_url": "https://videoconf.example.com/";,
+      "http_status": 303
+    @}
+  @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{server-failure}: This indicates that the Anastasis provider encountered
+a failure and recovery using this challenge cannot proceed at this time.
+Examples for failures might be that the provider is unable to send SMS
+messages at this time due to an outage.  The body includes details about
+the failure. The user may try again later or continue with other challenges.
+@end itemize
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SELECTING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "server-failure",
+      "http_status": "500",
+      "error_code": 52
+    @}
+  @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{truth-unknown}: This indicates that the Anastasis provider is unaware 
of
+the specified challenge. This is typically a permanent failure, and user
+interfaces should not allow users to re-try this challenge.
+@end itemize
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SELECTING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "truth-unknown",
+      "error_code": 8108
+    @}
+  @}
+@}
+@end example
+
+
+@itemize -
+
+@item
+@strong{rate-limit-exceeded}:
+@end itemize
+
+@example
+@{
+  "recovery_state": "CHALLENGE_SELECTING",
+  "recovery_information": @{
+    // ...
+  @}
+  "selected_challenge_uuid": 
"TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
+  "challenge_feedback": @{
+    "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
+      "state": "rate-limit-exceeded",
+      "error_code": 8121
+    @}
+  @}
+@}
+@end example
+@end quotation
+@end quotation
+@end quotation
+@end quotation
+
+@strong{pay:}
+
+With a @code{pay} transition, the application indicates to the reducer that
+a payment may have been made. Here, it is again possible to specify an
+optional @code{timeout} argument for long-polling, for example:
+
+@example
+@{
+    "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
+    "timeout" : @{ "d_ms" : 5000 @},
+@}
+@end example
+
+Depending on the type of the challenge and the result of the operation, the
+new state may be @code{CHALLENGE_SOLVING} (if say the SMS was now sent to the
+user), @code{CHALLENGE_SELECTING} (if the answer to the security question was
+correct), @code{RECOVERY_FINISHED} (if this was the last challenge that needed 
to
+be solved) or still @code{CHALLENGE_PAYING} (if the challenge was not actually
+paid for).  For sample messages, see the different types of
+@code{challenge_feedback} in the section about @code{select_challenge}.
+
+@strong{solve_challenge:}
+
+Solving a challenge takes various formats, depending on the type of the
+challenge and what is known about the answer.  The different supported
+formats are:
+
+@example
+@{
+    "answer": "answer to security question"
+@}
+@end example
+
+@example
+@{
+    "pin": 1234
+@}
+@end example
+
+@example
+@{
+    "hash": "SOMEBASE32ENCODEDHASHVALUE"
+@}
+@end example
+
+@node Authentication Methods,,Anastasis Reducer API,Top
+@anchor{anastasis anastasis-auth-methods}@anchor{30}@anchor{anastasis 
authentication-methods}@anchor{31}
+@chapter Authentication Methods
+
+
+This section describes the supported authentication methods in detail.  We
+note that the server implements rate limiting for all authentication methods
+to ensure that malicious strong attackers cannot guess the values by
+brute-force. Typically, a user is given three attempts per hour to enter the
+correct code from 2^63 possible values.  Transmitted codes also come with an
+expiration date. If the user re-requests a challenge to be sent, the same
+challenge may be transmitted (with the three attempts counter not increasing!)
+for a limited period of time (depending on the authentication method) before
+the service eventually rotates to a fresh random code with a fresh retry
+counter. Given the default value range and time intervals (which providers are
+at liberty to adjust), brute-force attacks against this are expected to
+succeed with a 50% probability after about 200000 years of attempts at the
+maximum permissible frequency.
+
+@menu
+* SMS (sms): SMS sms.
+* Email verification (email): Email verification email.
+* Video identification (vid): Video identification vid.
+* Security question (qa): Security question qa.
+* Snail mail verification (post): Snail mail verification post.
+
+@end menu
+
+@node SMS sms,Email verification email,,Authentication Methods
+@anchor{anastasis sms-sms}@anchor{32}
+@section SMS (sms)
+
+
+Sends an SMS with a code (prefixed with @code{A-}) to the user’s phone, 
including
+a UUID which identifies the challenge the code is for.  The user must send
+this code back with his request (see @code{$RESPONSE} under @ref{1e,,Managing 
truth}).
+If the transmitted code is correct, the server responses with the requested
+encrypted key share.
+
+@node Email verification email,Video identification vid,SMS sms,Authentication 
Methods
+@anchor{anastasis email-verification-email}@anchor{33}
+@section Email verification (email)
+
+
+Sends an email with a code (prefixed with @code{A-}) to the user’s mail 
address,
+including a UUID which identifies the challenge the code is for.  The user
+must send this code back with his request (see @code{$RESPONSE} under 
@ref{1e,,Managing truth}).  If the transmitted code is correct, the server 
responses with the
+requested encrypted key share.
+
+@node Video identification vid,Security question qa,Email verification 
email,Authentication Methods
+@anchor{anastasis video-identification-vid}@anchor{34}
+@section Video identification (vid)
+
+
+Requires the user to identify via video-call.  In the video-call, the
+user is told the code (prefixed with @code{A-}) needed to authenticate.
+
+The user is expected to delete all metadata revealing information about per
+from the images before uploading them. Since the respective images must be
+passed on to the video identification service in the event of password
+recovery, it should be ensured that no further information about the user can
+be derived from them.
+
+Video identification will typically result in the Anastasis provider
+requesting the user to be redirected to a Web site (or other URL) for the
+video-call.
+
+@node Security question qa,Snail mail verification post,Video identification 
vid,Authentication Methods
+@anchor{anastasis security-question-qa}@anchor{35}
+@section Security question (qa)
+
+
+Asks the user a security question.  The user sends back a @strong{salted}
+hash over the answer.  The @strong{question-salt} is stored encrypted as
+part of the recovery document and never revealed to the providers. This
+ensures that providers cannot derive the answer from the hash value.
+Furthermore, the security question itself is also only in the recovery
+document and never given to the Anastasis provider.  A moderately expensive
+hash function is used to further limit strong attackers that have obtained
+the recovery document from brute-forcing the answer.
+
+If the hash value matches with the one the server is expecting, the server
+answers with the requested encrypted key share.  However, unlike other
+encrypted key shares, the encrypted key share of a security question uses a
+special variation of the Anastasis encryption: Here, a different hash function
+over the security answer is used to provide an additional @strong{key-salt} 
for the
+decryption of the (encrypted) @strong{key share}.  This ensures that the key 
share
+remains irrecoverable without the answer even if the Anastasis provider
+storing the security question is malicious.
+
+@node Snail mail verification post,,Security question qa,Authentication Methods
+@anchor{anastasis snail-mail-verification-post}@anchor{36}
+@section Snail mail verification (post)
+
+
+Sends physical mail (snail mail) with a code (prefixed with @code{A-}) to the
+user’s mail address, including a UUID which identifies the challenge the code
+is for.  The user must send this code back with their request (see
+@code{$RESPONSE} under @ref{1e,,Managing truth}).  If the transmitted code is 
correct,
+the server responds with the requested encrypted key share.
+
+@c %**end of body
+@bye
diff --git a/doc/configuration-format.texi b/doc/configuration-format.texi
deleted file mode 100644
index 6453ba6..0000000
--- a/doc/configuration-format.texi
+++ /dev/null
@@ -1,73 +0,0 @@
-@c This file is used both in the exchange and merchant
-@c manuals. Edits should be propagated to both Gits!
-
-@node Configuration format
-@section Configuration format
-@cindex configuration
-
-In Taler realm, any component obeys to the same pattern to get configuration
-values.  According to this pattern, once the component has been installed, the
-installation deploys default values in 
@cite{$@{prefix@}/share/taler/config.d/}, in
-@cite{.conf} files.  In order to override these defaults, the user can write a 
custom
-@cite{.conf} file and either pass it to the component at execution time, or 
name it
-@cite{taler.conf} and place it under @cite{$HOME/.config/}.
-
-
-A config file is a text file containing @cite{sections}, and each section 
contains
-its @cite{values}. The right format follows:
-
-@example
-[section1]
-value1 = string
-value2 = 23
-
-[section2]
-value21 = string
-value22 = /path22
-@end example
-
-Throughout any configuration file, it is possible to use @code{$}-prefixed 
variables,
-like @code{$VAR}, especially when they represent filesystem paths.
-It is also possible to provide defaults values for those variables that are 
unset,
-by using the following syntax: @code{$@{VAR:-default@}}.
-However, there are two ways a user can set @code{$}-prefixable variables:
-
-by defining them under a @code{[paths]} section, see example below,
-
-@example
-[paths]
-TALER_DEPLOYMENT_SHARED = $@{HOME@}/shared-data
-..
-[section-x]
-path-x = $@{TALER_DEPLOYMENT_SHARED@}/x
-@end example
-
-or by setting them in the environment:
-
-@example
-$ export VAR=/x
-@end example
-
-The configuration loader will give precedence to variables set under 
@code{[path]},
-though.
-
-The utility @code{taler-config}, which gets installed along with the exchange, 
serves
-to get and set configuration values without directly editing the @cite{.conf}.
-The option @code{-f} is particularly useful to resolve pathnames, when they use
-several levels of @code{$}-expanded variables. See @code{taler-config --help}.
-
-Note that, in this stage of development, the file 
@code{$HOME/.config/taler.conf}
-can contain sections for @emph{all} the component. For example, both an 
exchange and
-a bank can read values from it.
-
-The repository @code{git://taler.net/deployment} contains examples of 
configuration
-file used in our demos. See under @code{deployment/config}.
-
-@cartouche
-@quotation Note
-Expectably, some components will not work just by using default values, as 
their
-work is often interdependent. For example, a merchant needs to know an exchange
-URL, or a database name.
-@end quotation
-@end cartouche
-
diff --git a/doc/ledger-sme-legal-check.txt b/doc/ledger-sme-legal-check.txt
deleted file mode 100644
index 534bb18..0000000
--- a/doc/ledger-sme-legal-check.txt
+++ /dev/null
@@ -1,214 +0,0 @@
-General Information
-1. Winner ID:  => see e-mail from LEDGER (not put here, because Git is public)
-2. Project name/title: Anastasis
-3. Your project team includes the following entities (chose one of the options 
below):
-       Legal persons only - SME, Research organisation, Higher educational 
institution X
-       Legal and natural persons
-4. Please list all team members (in case of a legal person, please enter the 
whole name of the company/research institution/university):
-5. People from your entity engaged in the project:
-   --- Everyone (maybe provide full list, including Berna and Nana)
-6. Is your entity a team leader?
-   --- I don't understand the question.
-7. Contact person
-   --- Vaish, I hope.
-8. Phone (eg. 0048111222333)
-9. E-mail
-
-Bank account info
-=> Leon has this.
-
-1. Bank account holder
-2. Bank name
-3. IBAN/account number (eg. PL12345678901234567890123456)
-4. Currency
-5. BIC/SWIFT code
-6. Bank address
-
-
-Legal data of entrepreneur
-=> See data from Leon.
-1. Company name (according to the registration document)
-2. Legal form
-3. Country (of the registered office)
-4. City (of the registered office)
-5. Zip code (of the registered office)
-6. Address, i.e. Street and number (of the registered office)
-7. Main registration number (according to the registration document)
-=> Will NOT be available on time.
-8. VAT number
-=> Will NOT be available on time.
-9. Organization type:
-       profit X
-       non-profit
-10. Date of main registration: (DD.MM.YYYY, according to the registration 
document).
-=> Will NOT be available on time, use Notary date for now.
-11. Name and position of all persons, being authorised to represent the entity 
according to the registration document (please indicate all persons authorized 
to represent your company and put the information about the way of 
representation – eg. sole representation, acting jointly).
-       for each:
-       1. Name and surname of the person, being authorised to represent the 
entity according to the registration document
-       2. Position of the person, being authorised to represent the entity 
according to the registration document
-       3. The way of representing the company: (sole representation, acting 
jointly)
-11.1. Please indicate a person authorised to sign the `Sub-grant Agreement’ 
(if a mentioned person is different from person indicated in point 11, please 
attach her/his power of attorney to sign the agreement, in section 7 - 
Attachments):
-
-=> All of the 12.x are zero.
-12.1. Applicant enterprise data – from 1st January 2019 to 31st December 2019 
(Please provide data contained in the last closed annual accounts, if not 
applicable, enter data up to the date):
-       1. Staff Headcount (in annual working unit AWU) – Before completing 
this point, please read point 8 of the Frequently Asked Questions (FAQ)
-       2. Annual turnover (in EUR; indicate the number OF thousands instead of 
the number IN thousands e.g. for 50.000 EUR enter 50)
-       3. Annual balance sheet total (in EUR; indicate the number OF thousands 
instead of the number IN thousands e.g. for 50.000 EUR enter 50)
-
-12.2. Applicant enterprise data – from 1st January 2018 to 31st December 2018 
(data contained in the approved annual accounts for 2018, if not applicable, 
enter n/a):
-       1. Staff Headcount (in annual working unit AWU) – Before completing 
this point, please read point 8 of the Frequently Asked Questions (FAQ)
-       2. Annual turnover (in EUR; indicate the number OF thousands instead of 
the number IN thousands e.g. for 50.000 EUR enter 50)
-       3. Annual balance sheet total (in EUR; indicate the number OF thousands 
instead of the number IN thousands e.g. for 50.000 EUR enter 50)
-
-12.3. Applicant enterprise data – from 1st January 2017 to 31st December 2017 
(data contained in the approved annual accounts for 2017, if not applicable, 
enter n/a):
-       1. Staff Headcount (in annual working unit AWU) – Before completing 
this point, please read point 8 of the Frequently Asked Questions (FAQ)
-       2. Annual turnover (in EUR; indicate the number OF thousands instead of 
the number IN thousands e.g. for 50.000 EUR enter 50)
-       3. Annual balance sheet total (in EUR; indicate the number OF thousands 
instead of the number IN thousands e.g. for 50.000 EUR enter 50)
-
-13. Has your entity already received any funding under the European Union’s 
Horizon 2020 Research and Innovation Programme?
-       Yes
-       No  X
-14. Does your entity participate or is going to participate in another 
Acceleration Programme?
-       Yes
-       No  X (we have no concrete plans, obviously we cannot answer for the 
distant future here)
-15.  Does your entity or any natural person related to your entity have any 
actual conflict of interest or might have any potential conflict of interest 
with one or more of the following Consortium partners: 1) FUNDINGBOX 
ACCELERATOR SP. Z O.O. (Poland), 2) STICHTING DYNE. ORG (Netherlands), 3) 
BLUMORPHO SAS (France)?
-        NO
-
-
-SME check - relations with other enterprises (direct or indirect)
-1. Does the Applicant enterprise own 25%-50% of stock/shares/voting rights in 
another enterprise?
-     NO
-
-2. Does another enterprise own 25%-50% of stock/shares/voting rights in the 
Applicant enterprise?
-     NO
-
-If yes, please indicate the names of all the entities and the % of 
stock/shares/voting rights owned AND enter the data in the section SME check – 
Partner enterprise data.
-3. Do any public bodies (e.g. public companies, research institutes, local 
government units with the annual budget over EUR 10 million and a population 
above 5,000) own 25% of stock/shares/voting rights or more in the Applicant 
enterprise?
-       Yes
-       No   X
-4. Do any public investors (e.g. public investment corporations, venture 
capital companies, business angels, universities, non-profit research centres, 
institutional investors, including regional development funds and/or local 
government units with the annual budget of less than EUR 10 million and fewer 
than 5 000 inhabitants) own 25% of stock/shares/voting rights or more in the 
Applicant enterprise?
-       Yes
-       No   X
-5. Does natural person/any other enterprise/public investor hold the right to 
vote as a shareholder/stockholder/partner in the Applicant enterprise?
-       Yes   X  (natural persons hold right to vote, as does TSYS)
-       No
-6. Does the Applicant enterprise own more than 50% of stock/shares/voting 
rights in another enterprise?
-       Yes
-       No    X
-7. Does any other enterprise own more than 50% of stock/shares/voting rights 
in the Applicant enterprise?
-       Yes
-       No    X
-8. Is the Applicant enterprise entitled to appoint or dismiss the majority of 
members of administrative, management or supervisory bodies in another 
enterprise?
-       Yes
-       No    X
-9. Is another enterprise entitled to appoint or dismiss the majority of 
members of administrative, management or supervisory bodies in the Applicant 
enterprise?
-       Yes
-       No    X
-10. Does the Applicant enterprise have a dominant influence on another 
enterprise, under an agreement with that enterprise or pursuant to the 
provision in the company statute or articles of association?
-       Yes
-       No    X
-11. Does another enterprise have a dominant influence on the Applicant 
enterprise, under an agreement with the Applicant enterprise or pursuant to the 
company statute or articles of association?
-       Yes
-       No    X
-12. If a shareholder or partner in another enterprise, does the Applicant 
enterprise, under a relevant agreement, exercise sole control over the majority 
of shareholders’ or partners’ voting rights in that enterprise?
-       Yes
-       No    X
-13. If a shareholder or partner in the Applicant enterprise, does another 
enterprise, under a relevant agreement, exercise sole control over the majority 
of shareholders’ or partners’ voting rights in the Applicant enterprise?
-       Yes
-       No    X
-14. Does the Applicant enterprise remain in the relationship mentioned in 
points 6-13 above (e.g. owns stock/shares/voting rights/has influence) acting 
through one or more individuals (natural persons acting jointly) if they 
operate on the same or adjacent market?
-       Yes   X  [market segregation does not matter]
-       No
-15. Are the ones entitled to represent the Applicant enterprise (shareholders, 
board members, proxies, individuals holding the power of attorney) members of 
management bodies in another enterprise or do they own stock/shares/righting 
votes in another enterprise?
-       Yes    X (likely, if Leon or Christian are entitled to represent; if 
only Dennis or Vaish, maybe 'no')
-       No
-16. Does the shareholder being a natural person and owning 25% of 
stock/shares/voting rights or more in the Applicant enterprise own 
stock/shares/voting rights in the another enterprise?
-       Yes    X  ["the shareholder" -> "a shareholder"], not sure about "in 
*the* another", confusing, bad English.
-       No
-17. Does the management team member or shareholder owning 25% of 
stock/shares/voting rights or more in the Applicant enterprise run their own 
business?
-       Yes    X  [not sure, depends on the definition of "own business" => 
Leon, any idea what this means?]
-       No
-18. Does the Applicant enterprise prepare consolidated financial statements or 
is included in consolidated financial statements of another enterprise?
-       Yes
-       No     X
-
-
-SMEs check - Partner enterprise data (25-50% of shares/capital/votes)
-=> None.
-Partner enterprise data (accounts and other data of the partner enterprise)
-1. Name:
-2. Address (of the registered office):
-3. Enter % of stock/shares/voting rights owned by the Applicant enterprise in 
the partner enterprise:
-4. Enter % of stock/shares/voting rights owned by the partner enterprise in 
the Applicant enterprise:
-5. The holding structure of the partner enterprise (you can add a graphic in 
the section 'Attachements')
-6. Information about enterprises linked with the partner enterprise (name and 
nature of the relationship):
-7.1. Staff Headcount (in annual working units) in 2019. If not applicable, 
enter data up to the date.
-7.2. Annual turnover in 2019 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). Please provide data 
contained in the last closed annual accounts, if not applicable, enter data up 
to the date).
-7.3. Annual balance sheet total in 2019 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). 
Please provide data contained in the last closed annual accounts, if not 
applicable, enter data up to the date).
-8.1. Staff Headcount (in annual working units) in 2018. If not applicapble, 
enter '0'.
-8.2. Annual turnover in 2018 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). If not applicapble, 
enter '0'.
-8.3. Annual balance sheet total in 2018 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). If 
not applicapble, enter '0'.
-9.1. Staff Headcount (in annual working units) in 2017. If not applicapble, 
enter '0'.
-9.2. Annual turnover in 2017 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). If not applicapble, 
enter '0'.
-9.3. Annual balance sheet total in 2017 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). If 
not applicapble, enter '0'.
-
-SMEs check - Linked enterprise data (over 50% of shares/capital/votes)
-=> None.
-Linked enterprise data (accounts and other data of the linked enterprise)
-1. Name of the linked enterprise:
-2. Address (of the registered office) of the linked enterprise:
-3. The holding structure of the linked enterprise (you can add a graphic in 
the section 'Attachments')
-4. Information about partner and linked enterprises of linked enterprise (name 
and nature of the relationship):
-5.1. Staff Headcount (in annual working units) in 2019. If not applicable, 
enter data up to the date.
-5.2. Annual turnover in 2019 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). Please provide data 
contained in the last closed annual accounts, if not applicable, enter data up 
to the date).
-5.3. Annual balance sheet total in 2019 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). 
Please provide data contained in the last closed annual accounts, if not 
applicable, enter data up to the date).
-6.1. Staff Headcount (in annual working units) in 2018. If not applicapble, 
enter '0'.
-6.2. Annual turnover in 2018 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). If not applicapble, 
enter '0'.
-6.3. Annual balance sheet total in 2018 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). If 
not applicapble, enter '0'.
-7.1. Staff Headcount (in annual working units) in 2017. If not applicapble, 
enter '0'.
-7.2. Annual turnover in 2017 (in EUR; indicate the number OF thousands instead 
of the number IN thousands e.g. for 50.000 EUR enter 50). If not applicapble, 
enter '0'.
-7.3. Annual balance sheet total in 2017 (in EUR; indicate the number OF 
thousands instead of the number IN thousands e.g. for 50.000 EUR enter 50). If 
not applicapble, enter '0'.
-
-Attachments
-
-Please include here all required documents.
-
-Be aware that the documents should have been established recently and in any 
case, no more than 6 months ago.
-
-Remember, that the provided documents must be in English. The translation 
doesn`t have to be certified, a simple one will be enough. The translation does 
not have to refer to the whole document, just the most important information 
that confirms what is requested in the application form.
-
-1. Official, valid and current registration document of the Applicant 
enterprise (Max. 10MB)
-
-=> Leon, likely not yet available.
-
-2. Document showing the holding structure of the Applicant enterprise (Max. 
10MB)
-
-=> See presentation slide on shareholdings; needs to be completed based on 
Vaish...
-
-3. VAT Registration - copy of an official and valid document proving your VAT 
registration. To confirm VAT number you can also provide the confirmation from 
the VAT Information Exchange System (VIES) - 
http://ec.europa.eu/taxation_customs/vies/vatRequest.html (max. 10MB
-
-=> Leon, likely not yet available.
-
-4. Bank Identification form (if the bank account dedicated to the needs of the 
project belong to your entity - Max. 10MB)
-
-=> Leon.
-
-5. Financial statements of the Applicant enterprise (for the last 3 years or, 
if not applicable, for the period starting at the registration date – PDF Max. 
10MB)
-
-=> not applicable. even from starting date. Maybe we can provide the notary 
fee?
-
-6. Business plan – declaration of newly established Applicant enterprise that 
have not closed their first accounting year made over the course of the 
financial year regarding the headcount/turnover/balance sheet total – 
Declaration should cover the entire period (financial years) until the entity 
will generate turnover (if applicable; PDF – Max. 10MB)
-
-=> See slide deck 'finances'
-
-7. Consolidated financial statement (for the last 3 years or, if not 
applicable, for the period starting at the registration date – PDF Max. 10MB)
-
-=> not applicable
-
-8. Additional documentation of the Applicant (Max. 10MB)
-
-=> not applicable, unless you want to add a rant from me about impossible 
deadlines.
-
-9. Additional documentation of partner and linked entreprises (the holding 
structure of the partner/linked enterprise, financial statements confirming 
data in the application form - max. 10MB)
-
-=> not applicable
diff --git a/doc/manual.texi b/doc/manual.texi
deleted file mode 100644
index 07f27ed..0000000
--- a/doc/manual.texi
+++ /dev/null
@@ -1,1296 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@c Too generic, should be renamed to avoid system conflicts.
-@c probably: manual.info -> taler-merchant.info
-@setfilename manual.info
-@include version-manual.texi
-@settitle The GNU Taler merchant backend operator tutorial @value{VERSION}
-
-@include syntax.texi
-
-@c Define a new index for options.
-@defcodeindex op
-@c Combine everything into one index (arbitrarily chosen to be the
-@c concept index).
-@syncodeindex op cp
-@c %**end of header
-
-@copying
-This manual is for the GNU Taler merchant backend (version @value{VERSION}, 
@value{UPDATED}),
-
-Copyright @copyright{} 2016, 2017, 2019 Taler Systems SA
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
-Texts.  A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-@end quotation
-@end copying
-@c If your manual is published on paper by the FSF, it should include
-@c The standard FSF Front-Cover and Back-Cover Texts, as given in
-@c maintain.texi.
-@c
-@c Titlepage
-@c
-@titlepage
-@title The GNU Taler merchant backend operator tutorial
-@subtitle Version @value{VERSION}
-@subtitle @value{UPDATED}
-@author Marcello Stanisci (@email{marcello.stanisci@@inria.fr})
-@author Christian Grothoff (@email{christian.grothoff@@inria.fr})
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@summarycontents
-@contents
-
-@ifnottex
-@node Top
-@top The GNU Taler manual for Web shops
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction::            Whom this manual is addressed to
-* Installation::            Installing the Merchant backend
-* Configuration::           How to set up the Merchant backend
-* Testing::                 How to test the installed Merchant backend
-* Advanced topics::         Detailed solutions to specific issues
-
-
-Appendices
-
-* GNU-LGPL::                The GNU Lesser General Public License says how you
-                            can use the code of libtalermerchant.so in your 
own projects.
-* GNU Affero GPL::          The Affero GNU General Public License says how you
-                            can copy and share the Taler merchant backend.
-* GNU-FDL::                 The GNU Free Documentation License says how you
-                            can copy and share the documentation of GNU Taler.
-
-Indices
-
-* Concept Index::           Index of concepts and programs.
-
-@detailmenu
- --- The Detailed Node Listing ---
-
-Introduction
-
-* About GNU Taler::
-* About this manual::
-* Architecture overview::
-
-Installation
-
-* Installing Taler using Docker::
-* Generic instructions::
-* Installing Taler on Debian GNU/Linux::
-
-Configuration
-
-* Backend options::
-* Sample backend configuration::
-* Launching the backend::
-
-Testing
-
-Advanced topics
-
-* Configuration format::
-* Using taler-config::
-* Merchant key management::
-* SEPA configuration::
-* Tipping visitors::
-* Generate payments::
-
-@end detailmenu
-@end menu
-
-
-@node Introduction
-@chapter Introduction
-
-@menu
-* About GNU Taler::
-* About this manual::
-* Architecture overview::
-@end menu
-
-@node About GNU Taler
-@section About GNU Taler
-
-GNU Taler is an open protocol for an electronic payment system with a
-free software reference implementation.  GNU Taler offers secure, fast
-and easy payment processing using well understood cryptographic
-techniques.  GNU Taler allows customers to remain anonymous, while
-ensuring that merchants can be held accountable by governments.
-Hence, GNU Taler is compatible with anti-money-laundering (AML) and
-know-your-customer (KYC) regulation, as well as data protection
-regulation (such as GDPR).
-
-GNU Taler is not yet production-ready, after following this manual
-you will have a backend that can process payments in ``KUDOS'', but
-not regular currencies.  This is not so much because of limitations
-in the backend, but because we are not aware of a Taler exchange
-operator offering regular currencies today.
-
-@node About this manual
-@section About this manual
-
-This tutorial targets system administrators who want to
-install a GNU Taler merchant @emph{backend}.
-
-We expect some moderate familiarity with the compilation and installation
-of free software packages. An understanding of cryptography
-is not required.
-
-This first chapter of the tutorial will give a brief overview of
-the overall Taler architecture, describing the environment in which
-the Taler backend operates.
-The second chapter then explains how to install the software,
-including key dependencies.  The third chapter will explain how to
-configure the backend, including in particular the configuration of the
-bank account details of the merchant.
-
-@c The fourth chapter will explain how to test that the setup worked correctly.
-
-The last chapter gives some additional information about advanced topics
-which will be useful for system administrators but are not necessary for
-operating a basic backend.
-
-@node Architecture overview
-@section Architecture overview
-
-@cindex crypto-currency
-@cindex KUDOS
-Taler is a pure payment system, not a new crypto-currency. As such, it
-operates in a traditional banking context.  In particular, this means
-that in order to receive funds via Taler, the merchant must have a
-regular bank account, and payments can be executed in ordinary
-currencies such as USD or EUR.  For testing purposes, Taler uses a
-special currency ``KUDOS'' and includes its own special bank.
-
-The Taler software stack for a merchant consists of four main components:
-
-@itemize
-@cindex frontend
-@item A frontend which interacts with the customer's browser. The
-  frontend enables the customer to build a shopping cart and place
-  an order.  Upon payment, it triggers the respective business logic
-  to satisfy the order.  This component is not included with Taler,
-  but rather assumed to exist at the merchant. This manual
-  describes how to integrate Taler with Web shop frontends.
-@cindex back office
-@item A back office application that enables the shop operators to
-  view customer orders, match them to financial transfers, and possibly
-  approve refunds if an order cannot be satisfied.  This component is
-  again not included with Taler, but rather assumed to exist at the
-  merchant. This manual will describe how to integrate such a component
-  to handle payments managed by Taler.
-@cindex backend
-@item A Taler-specific payment backend which makes it easy for the
-  frontend to process financial transactions with Taler.  The
-  next two chapters will describe how to install and configure
-  this backend.
-@cindex DBMS
-@cindex Postgres
-@item A DBMS which stores the transaction history for the Taler backend.
-  For now, the GNU Taler reference implementation only supports Postgres,
-  but the code could be easily extended to support another DBMS.
-@end itemize
-
-The following image illustrates the various interactions of these
-key components:
-
-@center @image{arch, 3in}
-
-@cindex RESTful
-Basically, the backend provides the cryptographic protocol support,
-stores Taler-specific financial information in a DBMS and communicates
-with the GNU Taler exchange over the Internet.  The frontend accesses
-the backend via a RESTful API.  As a result, the frontend never has to
-directly communicate with the exchange, and also does not deal with
-sensitive data.  In particular, the merchant's signing keys and bank
-account information is encapsulated within the Taler backend.
-
-
-@node Installation
-@chapter Installation
-
-@menu
-* Installing Taler using Docker::
-* Generic instructions::
-* Installing Taler on Debian GNU/Linux::
-@c * Installing Taler with GNU Guix:: Installing Taler with GNU Guix
-@c * Installing Taler on Arch Linux:: Installing Taler on Arch Linux
-@c * Installing Taler on Windows:: Installing Taler on Windows
-@c * Installing Taler on OS X:: Installing Taler on OS X
-@end menu
-
-This chapter describes how to install the GNU Taler merchant backend.
-
-@node Installing Taler using Docker
-@section Installing Taler using Docker
-
-This section provides instructions for the merchant backend
-installation using `Docker`.
-
-For security reasons, we run Docker against a VirtualBox instance,
-so the @code{docker} command should connect to a @code{docker-machine}
-instance that uses the VirtualBox driver.
-
-Therefore, the needed tools are: ``docker``, ``docker-machine``, and
-``docker-compose``.  Please refer to Docker's official
-@footnote{https://docs.docker.com/}documentation in order
-to get those components installed, as that is not in this manual's scope.
-
-Before starting to build the merchant's image, make sure a
-``docker-machine`` instance is up and running.
-
-Because all of the Docker source file are kept in our ``deployment``
-repository, we start by checking out the
-@code{git://taler.net/deployment} codebase:
-
-@smallexample
-$ git clone git://taler.net/deployment
-@end smallexample
-
-Now we actually build the merchant's image.  From the same
-directory as above:
-
-@smallexample
-$ cd deployment/docker/merchant/
-$ docker-compose build
-@end smallexample
-
-If everything worked as expected, the merchant is ready to be
-launched.  From the same directory as the previous step:
-
-@smallexample
-# Recall: the docker-machine should be up and running.
-$ docker-compose up
-@end smallexample
-
-You should see some live logging from all the involved containers.
-At this stage of development, you should also ignore some (harmless)
-error message from postresql about already existing roles and databases.
-
-To test if everything worked as expected, it suffices to issue a
-simple request to the merchant, as:
-
-@smallexample
-$ curl http://$(docker-machine ip)/
-# A greeting message should be returned by the merchant.
-@end smallexample
-
-
-@node Generic instructions
-@section Generic instructions
-
-This section provides generic instructions for the merchant backend
-installation independent of any particular operating system.
-Operating system specific instructions are provided in the following
-sections.  You should follow the operating system specific
-instructions if those are available, and only consult the generic
-instructions if no system-specific instructions are provided for your
-specific operating system.
-
-@menu
-* Installation of dependencies::
-* Installing libgnunetutil::
-* Installing the GNU Taler exchange::
-* Installing the GNU Taler merchant backend::
-@end menu
-
-@node Installation of dependencies
-@subsection Installation of dependencies
-
-The following packages need to be installed before we can compile the
-backend:
-
-@itemize
-@item autoconf >= 2.69
-@item automake >= 1.14
-@item libtool >= 2.4
-@item autopoint >= 0.19
-@item libltdl >= 2.4
-@item libunistring >= 0.9.3
-@item libcurl >= 7.26 (or libgnurl >= 7.26)
-@item GNU libmicrohttpd >= 0.9.39
-@item GNU libgcrypt >= 1.6
-@item libjansson >= 2.7
-@item Postgres >= 9.4, including libpq
-@item libgnunetutil (from Git)
-@item GNU Taler exchange (from Git)
-@end itemize
-
-Except for the last two, these are available in most GNU/Linux
-distributions and should just be installed using the respective
-package manager.
-
-The following sections will provide detailed instructions for
-installing the libgnunetutil and GNU Taler exchange dependencies.
-
-@node Installing libgnunetutil
-@subsection Installing libgnunetutil
-
-@cindex GNUnet
-Before you install libgnunetutil, you must download and install the
-dependencies mentioned in the previous section, otherwise the build
-may succeed but fail to export some of the tooling required by Taler.
-
-To download and install libgnunetutil, proceed as follows:
-
-@example
-$ git clone https://gnunet.org/git/gnunet/
-$ cd gnunet/
-$ ./bootstrap
-$ ./configure [--prefix=GNUNETPFX]
-$ # Each dependency can be fetched from non standard locations via
-$ # the '--with-<LIBNAME>' option. See './configure --help'.
-$ make
-# make install
-@end example
-
-If you did not specify a prefix, GNUnet will install to
-@code{/usr/local}, which requires you to run the last step as
-@code{root}.
-
-@node Installing the GNU Taler exchange
-@subsection Installing the GNU Taler exchange
-
-@cindex exchange
-After installing GNUnet, you can download and install
-the exchange as follows:
-
-@example
-$ git clone git://taler.net/exchange
-$ cd exchange
-$ ./bootstrap
-$ ./configure [--prefix=EXCHANGEPFX] \
-              [--with-gnunet=GNUNETPFX]
-$ # Each dependency can be fetched from non standard locations via
-$ # the '--with-<LIBNAME>' option. See './configure --help'.
-$ make
-# make install
-@end example
-
-If you did not specify a prefix, the exchange will install to
-@code{/usr/local}, which requires you to run the last step as
-@code{root}.  Note that you have to specify
-@code{--with-gnunet=/usr/local} if you installed GNUnet to
-@code{/usr/local} in the previous step.
-
-@node Installing the GNU Taler merchant backend
-@subsection Installing the GNU Taler merchant backend
-
-@cindex backend
-The following steps assume all dependencies are installed.
-
-Use the following commands to download and install the
-merchant backend:
-
-@example
-$ git clone git://taler.net/merchant
-$ cd merchant
-$ ./bootstrap
-$ ./configure [--prefix=PFX] \
-              [--with-gnunet=GNUNETPFX] \
-              [--with-exchange=EXCHANGEPFX]
-$ # Each dependency can be fetched from non standard locations via
-$ # the '--with-<LIBNAME>' option. See './configure --help'.
-$ make
-$ make install
-@end example
-
-Note that you have to specify @code{--with-exchange=/usr/local} and/or
-@code{--with-exchange=/usr/local} if you installed the exchange and/or
-GNUnet to @code{/usr/local} in the previous steps.
-
-@c @node Installing Taler with GNU Guix
-@c @section Installing Taler with GNU Guix
-
-@c This section has not yet been written.
-
-
-
-
-@node Installing Taler on Debian GNU/Linux
-@section Installing Taler on Debian GNU/Linux
-
-@cindex Wheezy
-@cindex Debian
-Debian wheezy is too old and lacks most of the packages required.
-
-On Debian jessie, only GNU libmicrohttpd needs to be compiled from
-source.  To install dependencies on Debian jesse, run the following
-commands:
-
-@example
-# apt-get install \
-  autoconf \
-  automake \
-  autopoint \
-  libtool \
-  libltdl-dev \
-  libunistring-dev \
-  libcurl4-gnutls-dev \
-  libgcrypt20-dev \
-  libjansson-dev \
-  libpq-dev \
-  postgresql-9.4
-# wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz
-# wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz.sig
-# gpg -v libmicrohttpd-latest.tar.gz # Should show signed by 939E6BE1E29FC3CC
-# tar xf libmicrohttpd-latest.tar.gz
-# cd libmicrohttpd-0*
-# ./configure
-# make install
-@end example
-
-For more recent versions of Debian, you should instead run:
-
-@example
-# apt-get install \
-  autoconf \
-  automake \
-  autopoint \
-  libtool \
-  libltdl-dev \
-  libunistring-dev \
-  libcurl4-gnutls-dev \
-  libgcrypt20-dev \
-  libjansson-dev \
-  libpq-dev \
-  postgresql-9.5 \
-  libmicrohttpd-dev
-@end example
-
-For the rest of the installation, follow the
-generic installation instructions starting with the installation of
-libgnunetutil.  Note that if you used the Debian wheezy instructions
-above, you need to pass
-@code{--with-microhttpd=/usr/local/} to all @code{configure} invocations.
-
-
-
-@c @node Installing Taler on Arch Linux
-@c @section Installing Taler on Arch Linux
-
-@c This section has not yet been written.
-
-
-@c @node Installing Taler on Windows
-@c @section Installing Taler on Windows
-
-@c This section has not yet been written.
-
-
-@c @node Installing Taler on OS X
-@c @section Installing Taler on OS X
-
-@c This section has not yet been written.
-
-
-@node Configuration
-@chapter How to configure the merchant's backend
-
-@cindex taler-config
-@cindex taler.conf
-The installation already provides reasonable defaults for most of the
-configuration options. However, some must be provided, in particular
-the database account and bank account that the backend should use.  By
-default, the file @code{$HOME/.config/taler.conf} is where the Web
-shop administrator specifies configuration values that augment or
-override the defaults.  The format of the configuration file is
-the well-known INI file format.  You can edit the file by hand, or
-use the @code{taler-config} commands given as examples.
-For more information on @code{taler-config}, @pxref{Using taler-config}.
-
-@menu
-* Backend options::
-* Sample backend configuration::
-* Launching the backend::
-@end menu
-
-@node Backend options
-@section Backend options
-
-The following table describes the options that commonly need to
-be modified.
-Here, the notation @code{[$section]/$option} denotes the option
-@code{$option} under the section @code{[$section]} in the
-configuration file.
-
-
-@table @asis
-
-@item Service address
-The following option sets the transport layer address used by the merchant 
backend:
-
-@cindex UNIX domain socket
-@cindex TCP
-@example
-[MERCHANT]/SERVE = TCP | UNIX
-@end example
-
-If given,
-@itemize
-@item @code{TCP}, then we need to set the TCP port in @code{[MERCHANT]/PORT}
-@item @code{UNIX}, then we need to set the unix domain socket path and mode in
-@code{[MERCHANT]/UNIXPATH} and @code{[MERCHANT]/UNIXPATH_MODE}. The latter 
takes
-the usual permission mask given as a number, e.g. 660 for user/group 
read-write access.
-@end itemize
-
-The frontend can then connect to the backend over HTTP using the specified 
address.
-If frontend and backend run within the same operating system, the use of
-a UNIX domain socket is recommended to avoid accidentally exposing the backend
-to the network.
-
-@c FIXME: we should offer an option to bind the TCP socket to a particular IP 
address (#4752)
-
-@cindex port
-To run the Taler backend on TCP port 8888, use:
-@example
-$ taler-config -s MERCHANT -o SERVE -V TCP
-$ taler-config -s MERCHANT -o PORT -V 8888
-@end example
-
-
-@item Currency
-Which currency the Web shop deals in, i.e. ``EUR'' or ``USD'', is specified 
using the option
-
-@cindex currency
-@cindex KUDOS
-@example
-[TALER]/CURRENCY
-@end example
-
-For testing purposes, the currency MUST match ``KUDOS'' so that tests will work
-with the Taler demonstration exchange at 
@url{https://exchange.demo.taler.net/}:
-
-@example
-$ taler-config -s TALER -o CURRENCY -V KUDOS
-@end example
-
-
-@item Database
-@cindex DBMS
-In principle is possible for the backend to support different DBMSs.
-The option
-
-@example
-[MERCHANT]/DB
-@end example
-
-specifies which DBMS is to be used. However, currently only the value 
"postgres" is supported. This is also
-the default.
-
-In addition to selecting the DBMS software, the backend requires DBMS-specific 
options to access the database.
-
-For postgres, you need to provide:
-
-@example
-[merchantdb-postgres]/config
-@end example
-@cindex Postgres
-
-This option specifies a postgres access path using the format
-@code{postgres:///$DBNAME}, where @code{$DBNAME} is the name of the Postgres
-database you want to use.  Suppose @code{$USER} is the name of the
-user who will run the backend process.  Then, you need to first run
-
-@example
-$ sudu -u postgres createuser -d $USER
-@end example
-
-as the Postgres database administrator (usually @code{postgres}) to
-grant @code{$USER} the ability to create new databases.  Next, you
-should as @code{$USER} run:
-
-@example
-$ createdb $DBNAME
-@end example
-
-to create the backend's database.  Here, @code{$DBNAME} must match the 
database name
-given in the configuration file.
-
-To configure the Taler backend to use this database, run:
-@example
-$ taler-config -s MERCHANTDB-postgres -o CONFIG \
-  -V postgres:///$DBNAME
-@end example
-
-
-@item Exchange
-@cindex exchange
-To add an exchange to the list of trusted payment service providers,
-you create a section with a name that starts with ``exchange-''.
-In that section, the following options need to be configured:
-
-@itemize
-
-@item
-The ``url'' option specifies the exchange's base URL.  For example,
-to use the Taler demonstrator use:
-
-@example
-$ taler-config -s EXCHANGE-demo -o URL \
-  -V https://exchange.demo.taler.net/
-@end example
-
-@item
-@cindex master key
-The ``master_key'' option specifies the exchange's master public key in base32 
encoding.
-For the Taler demonstrator, use:
-
-@example
-$ taler-config -s EXCHANGE-demo -o master_key \
-  -V CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00
-@end example
-
-Note that multiple exchanges can be added to the system by using different
-tokens in place of @code{demo} in the example above.  Note that all
-of the exchanges must use the same currency.  If you need to support
-multiple currencies, you need to configure a backend per currency.
-
-@end itemize
-
-@c FIXME: In the future, we need to describe specifying auditors here.
-@c @item Auditors
-
-
-@item Instances
-@cindex instance
-The backend allows the user to run multiple instances of shops with
-distinct business entities against a single backend.  Each instance
-uses its own bank accounts and key for signing contracts.  It is
-mandatory to configure a "default" instance.
-
-@itemize
-
-@item
-The ``KEYFILE'' option specifies the file containing the instance's
-private signing key.  For example, use:
-
-@example
-$ taler-config -s INSTANCE-default -o KEYFILE \
-  -V '$@{TALER_CONFIG_HOME@}/merchant/instance/default.key'
-@end example
-
-@item
-The ``NAME'' option specifies a human-readable name for the instance.
-For example, use:
-
-@example
-$ taler-config -s INSTANCE-default -o NAME \
-  -V 'Kudos Inc.'
-@end example
-
-
-@item
-The optional ``TIP_EXCHANGE'' and ``TIP_EXCHANGE_PRIV_FILENAME''
-options are discussed in @cite{Tipping visitors}
-@end itemize
-
-
-
-@item Accounts
-@cindex wire format
-In order to receive payments, the merchant backend needs to communicate bank
-account details to the exchange.  For this, the configuration must
-include one or more sections named ``ACCOUNT-name'' where @code{name} can be
-replaced by some human-readable word identifying the account.  For
-each section, the following options should be provided:
-
-
-@itemize
-@item
-The ``URL'' option specifies a @code{payto://}-URL for the account of
-the merchant.  For example, use:
-
-@example
-$ taler-config -s ACCOUNT-bank -o NAME \
-  -V 'payto://x-taler-bank/bank.demo.taler.net/4'
-@end example
-
-@item
-The ``WIRE_RESPONSE'' option specifies where Taler should store the
-(salted) JSON encoding of the wire account.  The file given will be
-created if it does not exist.  For example, use:
-
-@example
-$ taler-config -s ACCOUNT-bank -o WIRE_RESPONSE \
-  -V '@{$TALER_CONFIG_HOME@}/merchant/bank.json'
-@end example
-
-
-@item
-The ``PLUGIN'' option specifies which wire plugin should be used for
-this account.  The plugin must support the wire method used by the
-URL.  For example, use:
-
-@example
-$ taler-config -s ACCOUNT-bank -o PLUGIN \
-  -V taler_bank
-@end example
-
-@item
-For each @code{instance} that should use this account, you should set
-@code{HONOR_instance} and @code{ACTIVE_instance} to YES.  The first
-option will cause the instance to accept payments to the account (for
-existing contracts), while the second will cause the backend to
-include the account as a possible option for new contracts.
-
-For example, use:
-
-@example
-$ taler-config -s ACCOUNT-bank -o HONOR_default \
-  -V YES
-$ taler-config -s ACCOUNT-bank -o ACTIVE_default \
-  -V YES
-@end example
-
-to use ``account-bank'' for the ``default'' instance.
-
-@end itemize
-
-Depending on which PLUGIN you configured, you may additionally specfiy
-authentication options to enable the plugin to use the account.
-
-For example, with @code{taler_bank} plugin, use:
-
-@example
-$ taler-config -s ACCOUNT-bank -o TALER_BANK_AUTH_METHOD \
-  -V basic
-$ taler-config -s ACCOUNT-bank -o USERNAME \
-  -V user42
-$ taler-config -s ACCOUNT-bank -o PASSWORD \
-  -V pass42
-@end example
-
-
-
-@c Document EBICS here once supported.
-
-Note that additional instances can be specified using different tokens
-in the section name instead of @code{default}.
-
-@end table
-
-@node Sample backend configuration
-@section Sample backend configuration
-
-@cindex configuration
-The following is an example for a complete backend configuration:
-
-@smallexample
-[TALER]
-CURRENCY = KUDOS
-
-[MERCHANT]
-SERVE = TCP
-PORT = 8888
-DATABASE = postgres
-
-[MERCHANTDB-postgres]
-CONFIG = postgres:///donations
-
-[INSTANCE-default]
-KEYFILE = $DATADIR/key.priv
-NAME = "Kudos Inc."
-
-[ACCOUNT-bank]
-URL = payto://x-taler-bank/bank.demo.taler.net/4
-WIRE_RESPONSE = $DATADIR/bank.json
-PLUGIN = taler_bank
-HONOR_default = YES
-ACTIVE_default = YES
-TALER_BANK_AUTH_METHOD = basic
-USERNAME = my_user
-PASSWORD = 1234pass
-
-[EXCHANGE-trusted]
-URL = https://exchange.demo.taler.net/
-MASTER_KEY = CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00
-CURRENCY = KUDOS
-
-@end smallexample
-
-
-Given the above configuration, the backend will use a database named
-@code{donations} within Postgres.
-
-The backend will deposit the coins it receives to the exchange at
-@url{https://exchange.demo.taler.net/}, which has the master key @*
-"CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00".
-
-Please note that @code{doc/config.sh} will walk you through all
-configuration steps, showing how to invoke @code{taler-config}
-for each of them.
-
-@node Launching the backend
-@section Launching the backend
-
-@cindex backend
-@cindex taler-merchant-httpd
-Assuming you have configured everything correctly, you can launch the
-merchant backend using:
-
-@example
-$ taler-merchant-httpd
-@end example
-
-When launched for the first time, this command will print a message
-about generating your private key. If everything worked as expected,
-the command
-
-@example
-$ curl http://localhost:8888/
-@end example
-
-should return the message
-
-@smallexample
-Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.
-@end smallexample
-
-Please note that your backend is right now likely globally
-reachable.  Production systems should be configured to bind
-to a UNIX domain socket or properly restrict access to the
-port.
-
-
-@node Testing
-@chapter Testing
-
-The tool @code{taler-merchant-generate-payments} can be used to test
-the merchant backend installation.  It implements all the payment's steps
-in a programmatically way, relying on the backend you give it as input.
-Note that this tool gets installed along all the
-merchant backend's binaries.
-
-This tool gets configured by a config file, that must have the following
-layout:
-
-@example
-[PAYMENTS-GENERATOR]
-
-# The exchange used during the test: make sure the merchant backend
-# being tested accepts this exchange.
-# If the sysadmin wants, she can also install a local exchange
-# and test against it.
-EXCHANGE = https://exchange.demo.taler.net/
-
-# This value must indicate some URL where the backend
-# to be tested is listening; it doesn't have to be the
-# "official" one, though.
-MERCHANT = http://localbackend/
-
-# This value is used when the tool tries to withdraw coins,
-# and must match the bank used by the exchange. If the test is
-# done against the exchange at https://exchange.demo.taler.net/,
-# then this value can be "https://bank.demo.taler.net/";.
-BANK = https://bank.demo.taler.net/
-
-# The merchant instance in charge of serving the payment.
-# Make sure this instance has a bank account at the same bank
-# indicated by the 'bank' option above.
-INSTANCE = default
-
-# The currency used during the test. Must match the one used
-# by merchant backend and exchange.
-CURRENCY = KUDOS
-@end example
-@c FIXME: the last option should be removed and [taler]/CURRENCY used instead!
-
-Run the test in the following way:
-
-@example
-$ taler-merchant-generate-payments [-c config] [-e EURL] [-m MURL]
-@end example
-
-The argument @code{config} given to @code{-c} points to the configuration
-file and is optional -- @code{~/.config/taler.conf} will be checked by
-default.
-By default, the tool forks two processes: one for the merchant backend,
-and one for the exchange.
-The option @code{-e} (@code{-m}) avoids any exchange (merchant backend)
-fork, and just runs the generator against the exchange (merchant backend)
-running at @code{EURL} (@code{MURL}).
-
-Please NOTE that the generator contains @emph{hardcoded} values, as for
-deposit fees of the coins it uses.
-In order to work against the used exchange, those values MUST match the
-ones used by the exchange.
-
-The following example shows how the generator "sets" a deposit fee
-of EUR:0.01 for the 5 EURO coin.
-
-@example
-// from <merchant_repository>/src/sample/generate_payments.c
-@{ .oc = OC_PAY,
-  .label = "deposit-simple",
-  .expected_response_code = MHD_HTTP_OK,
-  .details.pay.contract_ref = "create-proposal-1",
-  .details.pay.coin_ref = "withdraw-coin-1",
-  .details.pay.amount_with_fee = concat_amount (currency, "5"),
-  .details.pay.amount_without_fee = concat_amount (currency, "4.99") @},
-@end example
-
-The logic calculates the deposit fee according to the subtraction:
-@code{amount_with_fee - amount_without_fee}.
-
-The following example shows a 5 EURO coin configuration - needed by the
-used exchange - which is compatible with the hardcoded example above.
-
-@example
-[COIN_eur_5]
-value = EUR:5
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.00
-fee_deposit = EUR:0.01 # important bit
-fee_refresh = EUR:0.00
-fee_refund = EUR:0.00
-rsa_keysize = 1024
-@end example
-
-If the command terminates with no errors, then the merchant backend
-is correctly installed.
-
-After this operation is done, the merchant database will have some dummy
-data in it, so it may be convenient to clean all the tables; to this
-purpose, issue the following command:
-
-@example
-$ taler-merchant-dbinit -r
-@end example
-
-
-@node Advanced topics
-@chapter Advanced topics
-
-@menu
-* Configuration format::    Configuration file format
-* Using taler-config::      Introduction to the taler-config tool
-* Merchant key management:: Managing the merchant's cryptographic keys
-* SEPA configuration::      Configuring a SEPA bank account
-* Tipping visitors::        Giving money to Web site visitors with Taler
-* Generate payments::       Generate fake payments for testing purposes
-@end menu
-
-@include configuration-format.texi
-@include taler-config.texi
-
-
-@node Merchant key management
-@section Merchant key management
-@cindex merchant key
-@cindex KEYFILE
-
-The option ``KEYFILE'' in the section ``INSTANCE-default''
-specifies the path to the instance's private key.  You do not need to
-create a key manually, the backend will generate it automatically if
-it is missing.  While generally unnecessary, it is possible to display
-the corresponding public key using the @code{gnunet-ecc} command-line
-tool:
-
-@example
-$ gnunet-ecc -p                                  \
-  $(taler-config -f -s INSTANCE-default \
-                 -o KEYFILE)
-@end example
-
-@c Add more on how to add that key to X.509 CSRs once we can do that.
-
-@node SEPA configuration
-@section Using the SEPA wire transfer method
-@cindex SEPA
-@cindex EBICS
-
-The following is a sample configuration for the SEPA wire transfer
-method:@footnote{Supporting SEPA is still
-work in progress; the backend will accept this configuration, but the
-exchange will not work with SEPA today.}.
-
-Then, to configure the  EBICS backend for SEPA payments in EUR,
-the following configuration
-options need to be set:
-
-@example
-$ taler-config -s TALER -o CURRENCY -V EUR
-$ taler-config -s ACCOUNT-e -o PLUGIN -V ebics
-$ taler-config -s ACCOUNT-e -o URL \
- -V payto://sepa/XY00111122223333444455556666
-$ taler-config -s ACCOUNT-e -o WIRE_RESPONSE
- -V '$@{DATADIR@}/b.json'
-@end example
-
-Please note that you will also have to configure an exchange and/or
-auditors that support SEPA.  However, we cannot explain how to do this
-yet as such entities do not yet exist.  Once such entities do exist,
-we expect future versions of the Taler backend to ship with
-pre-configured exchanges and auditors for common denominations.
-
-
-@node Tipping visitors
-@section Tipping visitors
-@cindex tipping
-
-Taler can also be used to tip Web site visitors.  For example, you may
-be running an online survey, and you want to reward those people that have
-dutifully completed the survey.  If they have installed a Taler wallet,
-you can provide them with a tip for their deeds.  This section describes
-how to setup the Taler merchant backend for tipping.
-
-There are four basic steps that must happen to tip a visitor.
-
-@menu
-* Configure a reserve and exchange for tipping::
-* Fund the reserve::
-* Authorize a tip::
-* Picking up of the tip::
-@end menu
-
-@node Configure a reserve and exchange for tipping
-@subsection Configure a reserve and exchange for tipping
-@cindex gnunet-ecc
-@cindex reserve key
-
-@c TODO: We should probably create a tool that automates the
-@c configuration process and simply outputs the wire transfer
-@c subject of the reserve.
-
-To tip users, you first need to create a reserve.  A reserve is a pool
-of money held in escrow at the Taler exchange.  This is the source of
-the funds for the tips.  Tipping will fail (resulting in disappointed
-visitors) if you do not have enough funds in your reserve!
-
-First, we configure the backend.  You need to enable tipping for each
-instance separately, or you can use an instance only for tipping.  To
-configure the ``default'' instance for tipping, use the following
-configuration:
-
-@example
-[INSTANCE-default]
-# this is NOT the tip.priv
-KEYFILE = signing_key.priv
-# replace the URL with the URL of the exchange you will use
-TIP_EXCHANGE = https://exchange:443/
-# here put the path to the file created with "gnunet-ecc -g1 tip.priv"
-TIP_RESERVE_PRIV_FILENAME = tip.priv
-@end example
-
-Note that the KEYFILE option should have already been present for
-the instance. It has nothing to do with the ``tip.priv'' file we
-created above, and you should probably use a different file here.
-
-Instead of manually editing the configuration, you could also run:
-
-@example
-$ taler-config -s INSTANCE-default \
-    -o TIP_RESERVE_PRIV_FILENAME \
-    -V tip.priv
-$ taler-config -s INSTANCE-default \
-    -o TIP_EXCHANGE \
-    -V https://exchange:443/
-@end example
-
-
-Next, to create the @code{TIP_RESERVE_PRIV_FILENAME} file, use:
-
-@example
-$ gnunet-ecc -g 1   \
-  $(taler-config -f -s INSTANCE-default \
-      -o TIP-RESERVE_PRIV_FILENAME)
-@end example
-
-This will create a file with the private key that will be used to
-identify the reserve.  You need to do this once for each instance that
-is configured to tip.
-
-
-Now you can (re)start the backend with the new configuration.
-
-@node Fund the reserve
-@subsection Fund the reserve
-@cindex reserve
-@cindex close
-
-To fund the reserve, you must first extract the public key
-from ``tip.priv'':
-
-@example
-$ gnunet-ecc --print-public-key \
-  $(taler-config -f -s INSTANCE-default \
-      -o TIP-RESERVE_PRIV_FILENAME)
-@end example
-
-In our example, the output for the public key is:
-
-@example
-QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG
-@end example
-
-You now need to make a wire transfer to the exchange's bank account
-using the public key as the wire transfer subject.  The exchange's
-bank account details can be found in JSON format at
-``https://exchange:443//wire/METHOD'' where METHOD is the respective
-wire method (i.e. ``sepa'').  Depending on the exchange's operator,
-you may also be able to find the bank details in a human-readable
-format on the main page of the exchange.
-
-Make your wire transfer and (optionally) check at
-``https://exchange:443/reserve/status/reserve_pub=QPE24X...''
-whether your transfer has arrived at the exchange.
-@c FIXME: we should create a nicer tool to do this check!
-
-Once the funds have arrived, you can start to use the reserve
-for tipping.
-
-Note that an exchange will typically close a reserve after four weeks,
-wiring all remaining funds back to the sender's account.  Thus, you
-should plan to wire funds corresponding to a campaign of about two
-weeks to the exchange initially. If your campaign runs longer, you
-should wire further funds to the reserve every other week to prevent
-it from expiring.
-
-@node Authorize a tip
-@subsection Authorize a tip
-
-When your frontend has reached the point where a client is supposed
-to receive a tip, it needs to first authorize the tip. For this,
-the frontend must use the ``/tip-authorize'' API of the backend.
-To authorize a tip, the frontend has to provide the following information
-in the body of the POST request:
-
-@itemize @bullet
-@item The amount of the tip
-
-@item The justification (only used internally for the back-office)
-
-@item The URL where the wallet should navigate next after the tip was processed
-
-@item The tip-pickup URL (see next section)
-@end itemize
-
-In response to this request, the backend will return a tip token, an
-expiration time and the exchange URL.
-The expiration time will indicate how long the tip is valid (when the
-reserve expires).  The tip token is an opaque string that contains all
-the information needed by the wallet to process the tip.  The
-frontend must send this tip token to the browser in a
-special ``402 Payment Required'' response inside
-the @code{X-Taler-Tip} header.
-
-The frontend should handle errors returned by the backend, such
-as misconfigured instances or a lack of remaining funds for tipping.
-
-@node Picking up of the tip
-@subsection Picking up of the tip
-
-The wallet will POST a JSON object to the shop's ``/tip-pickup'' handler.
-The frontend must then forward this request to the backend.  The response
-generated by the backend can then be forwarded directly to the wallet.
-
-@node Generate payments
-@section Generate payments
-@cindex testing database
-
-The merchant codebase offers the @code{taler-merchant-benchmark} tool
-to populate the database with fake payments.  This tool is in charge of
-starting a merchant, exchange, and bank processes, and provide them all
-the input to accomplish payments.  Note that each component will use its
-own configuration (as they would do in production).
-
-The tool takes all of the values it needs from the command line, with
-some of them being mandatory.  Among those, we have:
-
-@itemize
-@item @code{--currency=K} Use currency @emph{K}, for example to craft coins to 
withdraw.
-@item @code{--bank-url=URL} Assume that the bank is serving under the base URL 
@emph{URL}.
-This option is only actually used by the tool to check if the bank was well 
launched.
-@item @code{--merchant-url=URL} Reach the merchant through @emph{URL}, for 
downloading
-contracts and sending payments.
-@end itemize
-
-The tool then comes with two operation modes: @emph{ordinary},
-and @emph{corner}.  The first just executes normal payments,
-meaning that it uses the default instance and make sure that
-all payments get aggregated.  The second gives the chance to
-leave some payments unaggregated, and also to use merchant
-instances other than the default (which is, actually, the one
-used by default by the tool).
-
-Note: the ability of driving the aggregation policy is useful
-for testing the backoffice facility.
-
-Any subcommand is also equipped with the canonical @code{--help}
-option, so feel free to issue the following command in order to
-explore all the possibilities.  For example:
-
-@smallexample
-$ taler-merchant-benchmark corner --help
-@end smallexample
-
-will show all the options offered by the @emph{corner} mode.
-Among the most interesting, there are:
-
-@itemize
-@item @code{--two-coins=TC} This option instructs the tool to perform @emph{TC}
-many payments that use two coins, because normally only one coin is spent per 
payment.
-@item @code{--unaggregated-number=UN} This option instructs the tool to 
perform @emph{UN}
-(one coin) payments that will be left unaggregated.
-@item @code{--alt-instance=AI} This option instructs the tool to perform 
payments
-using the merchant instance @emph{AI} (instead of the @emph{default} instance)
-@end itemize
-
-As for the @code{ordinary} subcommand, it is worth explaining the
-following options:
-
-@itemize
-@item @code{--payments-number=PN} Instructs the tool to perform @emph{PN} 
payments.
-@item @code{--tracks-number=TN} Instructs the tool to perform @emph{TN} 
tracking operations.
-Note that the @b{total} amount of operations will be two times @emph{TN}, 
since "one"
-tracking operation accounts for @code{/track/transaction} and 
@code{/track/transfer}.
-This command should only be used to see if the operation ends without 
problems, as
-no actual measurement of performance is provided (despite of the 'benchmark' 
work used
-in the tool's name).
-@end itemize
-
-@c **********************************************************
-@c *******************  Appendices  *************************
-@c **********************************************************
-
-@node GNU-LGPL
-@unnumbered GNU-LGPL
-@cindex license
-@cindex LGPL
-@include lgpl.texi
-
-@node GNU Affero GPL
-@unnumbered GNU Affero GPL
-@cindex license
-@cindex Affero GPL
-@include agpl.texi
-
-@node GNU-FDL
-@unnumbered GNU-FDL
-@cindex license
-@cindex GNU Free Documentation License
-@include fdl-1.3.texi
-
-@node Concept Index
-@unnumbered Concept Index
-
-@printindex cp
-
-@bye
diff --git a/doc/merchant-api.content.texi b/doc/merchant-api.content.texi
deleted file mode 100644
index 7dcbb80..0000000
--- a/doc/merchant-api.content.texi
+++ /dev/null
@@ -1,1068 +0,0 @@
-@c *****************************************
-@c This file is supposed to be included from
-@c the language-specific tutorial.
-@c *****************************************
-
-@c Define a new index for options.
-@defcodeindex op
-@c Combine everything into one index (arbitrarily chosen to be the
-@c concept index).
-@syncodeindex op cp
-@c %**end of header
-
-@copying
-This document is a tutorial for the GNU Taler Merchant API (version 
@value{VERSION}, @value{UPDATED})
-
-Copyright @copyright{} 2018 Taler Systems SA
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
-Texts.  A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-@end quotation
-@end copying
-@c If your tutorial is published on paper by the FSF, it should include
-@c The standard FSF Front-Cover and Back-Cover Texts, as given in
-@c maintain.texi.
-@c
-@c Titlepage
-@c
-@titlepage
-@title The GNU Taler Merchant API tutorial
-@subtitle Version @value{VERSION}
-@subtitle @value{UPDATED}
-@author Christian Grothoff (@email{christian@@grothoff.org})
-@author Marcello Stanisci (@email{marcello.stanisci@@inria.fr})
-@author Florian Dold (@email{florian.dold@@inria.fr})
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@summarycontents
-@contents
-
-@ifnottex
-@node Top
-@top The GNU Taler Merchant API Tutorial (Version for @value{LANGNAME})
-@insertcopying
-@end ifnottex
-
-
-@menu
-* Introduction::                                  What this tutorial is about
-* Accepting a Simple Payment::                    How to accept simple payments
-* Giving Refunds::                                How to give refunds to 
customers
-* Giving Customers Tips::                         How to reward customers with 
tips
-* Advanced topics::                               Detailed solutions to 
specific issues
-
-
-Appendices
-
-* GNU-LGPL::                     The GNU Lesser General Public License says 
how you
-                                 can use the code of libtalermerchant.so in 
your own projects.
-* GNU-FDL::                      The GNU Free Documentation License says how 
you
-                                 can copy and share the documentation of GNU 
Taler.
-
-Indices
-
-* Concept Index::               Index of concepts and programs.
-@end menu
-
-
-@node Introduction
-@chapter Introduction
-
-@section About GNU Taler
-
-GNU Taler is an open protocol for an electronic payment system with a free
-software reference implementation.  GNU Taler offers secure, fast and easy
-payment processing using well understood cryptographic techniques.  GNU Taler
-allows customers to remain anonymous, while ensuring that merchants can be held
-accountable by governments.  Hence, GNU Taler is compatible with
-anti-money-laundering (AML) and know-your-customer (KYC) regulation, as well as
-data protection regulation (such as GDPR).
-
-
-@section About this tutorial
-
-This tutorial addresses how to process payments using the GNU Taler merchant
-Backend. This chapter explains some basic concepts.  In the second chapter, you
-will learn how to do basic payments.
-
-@clear GOT_LANG
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-This version of the tutorial has examples for Python3.
-It uses the requests library for HTTP requests.
-@end ifset
-@ifset LANG_CURL
-@set GOT_LANG 1
-This version of the tutorial has examples for the
-command line with cURL.
-@end ifset
-@ifset LANG_PHP
-This version of the tutorial has examples for PHP,
-using libcurl.
-@end ifset
-@c
-Versions for other languages/environments are available as well.
-
-@cindex examples
-@cindex git
-If you want to look at some simple, running examples, check out these:
-@itemize
-@item
-The @url{https://git.taler.net/blog.git/tree/talerblog/blog/blog.py, essay 
merchant} that
-sells single chapters of a book.
-@item
-The 
@url{https://git.taler.net/donations.git/tree/talerdonations/donations/donations.py,
 donation page} that
-accepts donations for software projects and gives donation receipts.
-@item
-The 
@url{https://git.taler.net/survey.git/tree/talersurvey/survey/survey.py,survey} 
that
-gives users who answer a question a small reward.
-@end itemize
-
-@section Architecture overview
-
-The Taler software stack for a merchant consists of the following
-main components:
-
-@itemize
-@cindex frontend
-@item A frontend which interacts with the customer's browser. The
-  frontend enables the customer to build a shopping cart and place
-  an order.  Upon payment, it triggers the respective business logic
-  to satisfy the order.  This component is not included with Taler,
-  but rather assumed to exist at the merchant. This tutorial
-  describes how to develop a Taler frontend.
-@cindex backend
-@item A Taler-specific payment backend which makes it easy for the
-  frontend to process financial transactions with Taler.  For this
-  tutorial, you will use a public sandbox backend.  For production
-  use, you must either set up your own backend or ask another person
-  to do so for you.
-@end itemize
-
-The following image illustrates the various interactions of these
-key components:
-
-@image{arch-api, 3in}
-
-The backend provides the cryptographic protocol support, stores Taler-specific
-financial information and communicates with the GNU Taler exchange over the
-Internet.  The frontend accesses the backend via a RESTful API.  As a result,
-the frontend never has to directly communicate with the exchange, and also does
-not deal with sensitive data.  In particular, the merchant's signing keys and
-bank account information are encapsulated within the Taler backend.
-
-Some functionality of the backend (the ``public interface``) is also exposed 
to the
-customer's browser directly.  In the HTTP API, all public endpoints are 
prefixed with @code{/public/}.
-
-@section Public Sandbox Backend and Authentication
-@cindex sandbox
-@cindex authorization
-
-How the frontend authenticates to the Taler backend depends on the 
configuration. @xref{Top,,, manual, Taler Merchant Operating Manual}.
-
-The public sandbox backend @url{https://backend.demo.taler.net/} uses an API 
key
-in the @code{Authorization} header.  The value of this header must be
-@code{ApiKey sandbox} for the public sandbox backend.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-curl -i 'https://backend.demo.taler.net/' \
-  --header "Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> requests.get("https://backend.demo.taler.net";,
-...              headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = curl_init("https://backend.demo.taler.net/";);
-php >  $options = array(CURLOPT_RETURNTRANSFER => true,
-php (                   CURLOPT_CUSTOMREQUEST => "GET",
-php (                   CURLOPT_HTTPHEADER => array("Authorization: ApiKey 
sandbox"));
-php > curl_setopt_array ($c, $options);
-php > $r = curl_exec ($c);
-php > echo curl_getinfo ($c, CURLINFO_HTTP_CODE);
-200
-php > echo $r;
-Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-If an HTTP status code other than 200 is returned, something went wrong. You
-should figure out what the problem is before continuing with this tutorial.
-
-The sandbox backend @url{https://backend.demo.taler.net/} uses @code{KUDOS} as
-an imaginary currency.  Coins denominated in @code{KUDOS} can be withdrawn
-from @url{https://bank.demo.taler.net/}.
-
-@section Merchant Instances
-@cindex instance
-
-The same Taler merchant backend server can be used by multiple separate
-merchants that are separate business entities.  Each of these separate business
-entities is called a @emph{merchant instance}, and is identified by an
-alphanumeric @emph{instance id}.  If the instance is omitted, the instance id
-@code{default} is assumed.
-
-The following merchant instances are configured on 
@url{https://backend.demo.taler.net/}:
-@itemize
-@item @code{GNUnet} (The GNUnet project)
-@item @code{FSF} (The Free Software Foundation)
-@item @code{Tor} (The Tor Project)
-@item @code{default} (Kudos Inc.)
-@end itemize
-
-Note that these are fictional merchants used for our demonstrators and
-not affiliated with or officially approved by the respective projects.
-
-
-@node Accepting a Simple Payment
-@chapter Accepting a Simple Payment
-
-@section Creating an Order for a Payment
-@cindex order
-
-Payments in Taler revolve around an @emph{order}, which is a machine-readable
-description of the business transaction for which the payment is to be made.
-Before accepting a Taler payment as a merchant
-you must create such an order.
-
-This is done by posting a JSON object to the backend's @code{/order} API 
endpoint.  At least the
-following fields must be given:
-
-@itemize
-@item @var{amount}: The amount to be paid, as a string in the format
-@code{CURRENCY:DECIMAL_VALUE}, for example @code{EUR:10} for 10 Euros or
-@code{KUDOS:1.5} for 1.5 KUDOS.
-
-@item @var{summary}:  A human-readable summary for what the payment is about.
-The summary should be short enough to fit into titles, though no
-hard limit is enforced.
-
-@item @var{fulfillment_url}:  A URL that will be displayed once the payment is
-completed.  For digital goods, this should be a page that displays the product
-that was purchased.  On successful payment, the wallet automatically appends
-the @code{order_id} as a query parameter, as well as the @code{session_sig} for
-session-bound payments (discussed later).
-@end itemize
-
-Orders can have many more fields, see @ref{The Taler Order Format}.
-
-After successfully @code{POST}ing to @code{/order}, an @code{order_id} will be
-returned.  Together with the merchant @code{instance}, the order id uniquely
-identifies the order within a merchant backend.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-ORDER='
-{"order": {
-  "amount": "KUDOS:10",
-  "summary": "Donation",
-  "fulfillment_url": "https://example.com/thanks.html"}}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/order' \
-     --header "Authorization: ApiKey sandbox" -d "$ORDER"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-#   "order_id": "2018.058.21.46.06-024C85K189H8P"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> order = dict(order=dict(amount="KUDOS:10",
-...                         summary="Donation",
-...                         fulfillment_url="https://example.com/thanks.html";))
->>> order_resp = requests.post("https://backend.demo.taler.net/order";, 
json=order,
-...               headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = curl_init("https://backend.demo.taler.net/order";);
-php > $json = array("order"=>
-php (   array("amount"=>"KUDOS:1",
-php (         "fulfillent_url"=>"https://example.com/thanks.html";, 
-php (         "summary"=>"nice product"));
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php (                  CURLOPT_CUSTOMREQUEST=>"POST",
-php (                  CURLOPT_POSTFIELDS=>json_encode($json),
-php (                  CURLOPT_HTTPHEADER=>array("Authorization: ApiKey 
sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200
-php > echo $r;
-{
-  "order_id": "2018.072.12.48.51-014DKDKBMHPDP"
-}
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-The backend will fill in some details missing in the order, such as the address
-of the merchant instance.  The full details are called the @emph{contract
-terms}.
-@cindex contract
-@cindex terms
-
-@section Checking Payment Status and Prompting for Payment
-The status of a payment can be checked with the @code{/check-payment} 
endpoint.  If the payment
-is yet to be completed by the customer, @code{/check-payment} will give the 
frontend a URL (the @var{payment_redirect_url})
-that will trigger the customer's wallet to execute the payment.
-
-Note that the only way to obtain the @var{payment_redirect_url} is to check 
the status of the payment,
-even if you know that the user did not pay yet.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-ORDER_ID="2018.058.21.46.06-024C85K189H8P"
-curl -i "https://backend.demo.taler.net/check-payment?order_id=$ORDER_ID"; \
-  --header "Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-#   "payment_redirect_url":
-#      "https://backend.demo.taler.net/public/trigger-pay?[...]";,
-#   "paid": false
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> r = requests.get("https://backend.demo.taler.net/check-payment";,
-...                  params=dict(order_id=order_resp.json()["order_id"]),
-...                  headers={"Authorization": "ApiKey sandbox"})
->>> print(r.json())
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $ORDER_ID = "2018.072.12.48.51-014DKDKBMHPDP";
-php > curl_init 
("https://backend.demo.taler.net/check-payment?order_id=$ORDER_ID";);
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php (                   CURLOPT_CUSTOMREQUEST=>"GET",
-php (                   CURLOPT_HTTPHEADER=>array(
-php (                     "Authorization: ApiKey sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo $r;
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-If the @var{paid} field in the response is @code{true}, the other
-fields in the response will be different. Once the payment was
-completed by the user, the response will contain the following fields:
-
-@itemize
-@item @var{paid}: Set to @var{true}.
-@item @var{contract_terms}:  The full contract terms of the order.
-@item @var{refunded}: @code{true} if a (possibly partial) refund was granted 
for this purchase.
-@item @var{refunded_amount}:  Amount that was refunded
-@item @var{last_session_id}:  Last session ID used by the customer's wallet. 
@xref{Session-Bound Payments}.
-@end itemize
-
-Once the frontend has confirmed that the payment was successful, it
-usually needs to trigger the business logic for the merchant to
-fulfill the merchant's obligations under the contract.
-
-
-@node Giving Refunds
-@chapter Giving Refunds
-@cindex refunds
-
-A refund in GNU Taler is a way to ``undo'' a payment.  It needs to be
-authorized by the merchant.  Refunds can be for any fraction of the
-original amount paid, but they cannot exceed the original payment.
-Refunds are
-time-limited and can only happen while the exchange holds funds for a
-particular payment in escrow.  The time during which a refund is possible
-can be controlled by setting the @code{refund_deadline} in an order.  The 
default
-value for this refund deadline is specified in the configuration of the
-merchant's backend.
-
-The frontend can instruct the merchant backend to authorize a refund
-by @code{POST}ing to the @code{/refund} endpoint.
-
-The refund request JSON object has the following fields:
-@itemize
-@item @var{order_id}: Identifies for which order a customer should be refunded.
-@c NOTE: the merchant does NOT default to instance "default".
-@item @var{instance}: Merchant instance to use.
-@item @var{refund}:  Amount to be refunded.  If a previous refund was
-authorized for the same order, the new amount must be higher, otherwise
-the operation has no effect. The value indicates the
-total amount to be refunded, @emph{not} an increase in the refund.
-@item @var{reason}:  Human-readable justification for the refund. The reason 
is only used by the Back Office and is not exposed to the customer.
-@end itemize
-
-If the request is successful (indicated by HTTP status code 200), the response
-includes a @code{refund_redirect_url}.  The frontend must redirect the
-customer's browser to that URL to allow the refund to be processed by the 
wallet.
-
-This code snipped illustrates giving a refund:
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-REFUND_REQ='
-{"order_id": "2018.058.21.46.06-024C85K189H8P",
- "refund": "KUDOS:10",
- "instance": "default",
- "reason": "Customer did not like the product"}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/refund' \
-     --header "Authorization: ApiKey sandbox" -d "$REFUND_REQ"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-#   [...]
-#   "refund_redirect_url": "[...]"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> refund_req = dict(order_id="2018.058.21.46.06-024C85K189H8P",
-...                   refund="KUDOS:10",
-...                   instance="default",
-...                   reason="Customer did not like the product")
->>> requests.post("https://backend.demo.taler.net/refund";, json=refund_req,
-...              headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $REFUND_REQ = array("order_id"=>$ORDER_ID,
-php (                     "refund"=>"KUDOS:0.5",
-php (                     "instance"=>"default",
-php (                     "reason"=>"Customer did not like product");
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php (                  CURLOPT_CUSTOMREQUEST=>"POST",
-php (                  CURLOPT_HTTPHEADER=>array(
-php (                    "Authorization: ApiKey sandbox"),
-php (                  CURLOPT_POSTFIELDS=>json_encode($REFUND_REQ));
-php > $c = curl_init("https://backend.demo.taler.net/refund";);
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo $r;
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200 # Make sure you paid first!
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-@node Giving Customers Tips
-@chapter Giving Customers Tips
-@cindex tips
-
-@c NOTE: Terminology should not be merchant/customer here, as
-@c the relationship is completely different. So I use
-@c ``site'' and ``visitor'', as that is right now the proper
-@c context. We may want to use more payment-ish terminology
-@c in the future, but ``donor'' and ``grantee'' sound excessive
-@c in the context of ``tips''.
-
-GNU Taler allows Web sites to grant small amounts directly to the
-visitor.  The idea is that some sites may want incentivize actions
-such as filling out a survey or trying a new feature.  It is important
-to note that tips are not enforceable for the visitor, as there is no
-contract. It is simply a voluntary gesture of appreciation of the site
-to its visitor.  However, once a tip has been granted, the visitor
-obtains full control over the funds provided by the site.
-
-The ``merchant'' backend of the site must be properly configured for
-tipping, and sufficient funds must be made available for tipping @xref{Top,,, 
manual,
-Taler Merchant Operating Manual}.
-
-To check if tipping is configured properly and if there are
-sufficient funds available for tipping, query the @code{/tip-query} endpoint:
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-curl -i 'https://backend.demo.taler.net/tip-query?instance=default' --header 
"Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-#  [...]
-#  "amount_available": "KUDOS:153.47",
-#  "amount_authorized": "KUDOS:10"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> requests.get("https://backend.demo.taler.net/tip-query?instance=default";,
-...              headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = 
curl_init("https://backend.demo.taler.net/tip-query?instance=default";);
-php >  $options = array(CURLOPT_RETURNTRANSFER=>true,
-php (                   CURLOPT_CUSTOMREQUEST=>"GET",
-php (                   CURLOPT_HTTPHEADER=>array(
-php (                     "Authorization: ApiKey sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-@cindex authorize tip
-To authorize a tip, @code{POST} to @code{/tip-authorize}.  The following 
fields are recognized in the JSON
-request object:
-
-@itemize
-@item @var{amount}: Amount that should be given to the visitor as a tip.
-@item @var{instance}: Merchant instance that grants the tip (each instance may 
have its own independent tipping funds configured).
-@item @var{justification}: Description of why the tip was granted.  
Human-readable text not exposed to the customer, but used by the Back Office.
-@item @var{next_url}: The URL that the user's browser should be redirected to 
by the wallet, once the tip has been processed.
-@end itemize
-
-The response from the backend contains a @code{tip_redirect_url}. The 
customer's browser must be
-redirected to this URL for the wallet to pick up the tip.
-@cindex pick up tip
-
-This code snipped illustrates giving a tip:
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-TIP_REQ='
-{"amount": "KUDOS:0.5",
- "instance": "default",
- "justification": "User filled out survey",
- "next_url": "https://merchant.com/thanks.html"}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/tip-authorize' \
-     --header "Authorization: ApiKey sandbox" -d "$TIP_REQ"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-#   [...]
-#   "tip_redirect_url": "[...]"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> tip_req = dict(amount="KUDOS:0.5",
-...                instance="default",
-...                justification="User filled out survey",
-...                next_url="https://merchant.com/thanks.html";)
->>> requests.post("https://backend.demo.taler.net/tip-authorize";, json=tip_req,
-...              headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $TIP_REQ = array(
-php (   "amount"=>"KUDOS:1",
-php (   "instance"=>"default",
-php (   "justification"=>"surveying",
-php (   "next_url"=>"https://example.com/survey-thanks.html";);
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php (                  CURLOPT_CUSTOMREQUEST=>"POST",
-php (                  CURLOPT_POSTFIELDS=>json_encode($TIP_REQ),
-php (                  CURLOPT_HTTPHEADER=>array("Authorization: ApiKey 
sandbox"));
-php > $c = curl_init("https://backend.demo.taler.net/tip-authorize";);
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE); 
-200
-@end verbatim
-@end example
-@end ifset
-
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-
-@node Advanced topics
-@chapter Advanced topics
-
-@menu
-* Detecting the Presence of the Taler Wallet::  Detecting the Presence of the 
Taler Wallet
-* Integration with the Back Office::            Integration with the Back 
Office
-* Session-Bound Payments::                      Session-bound payments for 
digital goods
-* Product Identification::                      Product Identification
-* The Taler Order Format::                      The Taler Order Format
-@end menu
-
-@node Detecting the Presence of the Taler Wallet
-@section Detecting the Presence of the Taler Wallet
-@cindex wallet
-
-Taler offers ways to detect whether a user has the wallet installed in
-their browser. This allows Web sites to adapt accordingly.  Note that
-not all platforms can do presence detection reliably.  Some platforms
-might have a Taler wallet installed as a separate App instead of using
-a Web extension.  In these cases, presence detection will fail. Thus,
-sites may want to allow users to request Taler payments even if a
-wallet could not be detected, especially for visitors using mobiles.
-
-@subsection Presence detection without JavaScript
-Presence detection without JavaScript is based on CSS classes.  You can hide or
-show elements selectively depending on whether the wallet is detected or not.
-
-In order to work correctly, a special fallback stylesheet must be included that
-will be used when the wallet is not present.  The stylesheet can be put into
-any file, but must be included via a @code{link} tag with the @code{id}
-attribute set to @code{taler-presence-stylesheet}.  If a wallet is present, it
-will ``hijack'' this stylesheet to change how elements with the following
-classes are rendered:
-
-The following CSS classes can be used:
-@table @code
-@item taler-installed-hide
-A CSS rule will set the @code{display} property for this class to @code{none} 
once the Taler wallet is installed and enabled.
-If the wallet is not installed, @code{display} will be @code{inherit}.
-
-@item taler-installed-show
-A CSS rule will set the @code{display} property for this class to 
@code{inherit} once the Taler wallet is installed and enabled.
-If the wallet is not installed, @code{display} will be @code{none}.
-
-@end table
-
-The following is a complete example:
-
-@smallexample
-<!DOCTYPE html>
-<html data-taler-nojs="true">
-  <head>
-    <title>Tutorial</title>
-    <link rel="stylesheet"
-          type="text/css"
-          href="/web-common/taler-fallback.css"
-          id="taler-presence-stylesheet" />
-  </head>
-  <body>
-    <p class="taler-installed-hide">
-      No wallet found.
-    </p>
-    <p class="taler-installed-show">
-      Wallet found!
-    </p>
-  </body>
-</html>
-@end smallexample
-
-The @code{taler-fallback.css} is part of the Taler's @emph{web-common} 
repository,
-available at 
@url{https://git.taler.net/web-common.git/tree/taler-fallback.css}.
-You may have to adjust the @code{href} attribute in the HTML code above to 
point
-to the correct location of the @code{taler-fallback.css} file on your Web site.
-
-@subsection Detection with JavaScript
-
-The following functions are defined in the @code{taler} namespace of the 
@code{taler-wallet-lib} helper library
-available at 
@url{https://git.taler.net/web-common.git/tree/taler-wallet-lib.js}.
-
-@table @code
-@item onPresent(callback: () => void)
-Adds a callback to be called when support for Taler payments is detected.
-
-@item onAbsent(callback: () => void)
-Adds a callback to be called when support for Taler payments is disabled.
-
-@end table
-
-Note that the registered callbacks may be called more than once. This may
-happen if a user disables or enables the wallet in the browser's extension
-settings while a shop's frontend page is open.
-
-@c FIXME: include full example of Web site including taler-wallet-lib.js
-@c and using JS detection actions.  (alert()?)
-
-@node Integration with the Back Office
-@section Integration with the Back Office
-
-Taler ships a Back Office application as a stand-alone Web application.
-The Back Office has its own documentation at 
@url{https://docs.taler.net/backoffice/html/manual.html}.
-
-Developers wishing to tightly integrate back office support for
-Taler-based payments into an existing back office application should
-focus on the wire transfer tracking and transaction history sections
-of the Taler Backend API specification at
-@url{https://docs.taler.net/api/api-merchant.html}
-
-@node Session-Bound Payments
-@section Session-Bound Payments
-@cindex session
-
-Sometimes checking if an order has been paid for is not enough. For
-example, when selling access to online media, the publisher may want
-to be paid for exactly the same product by each customer.  Taler
-supports this model by allowing the mechant to check whether the
-``payment receipt'' is available on the user's current device.  This
-prevents users from easily sharing media access by transmitting a link
-to the fulfillment page.  Of course sophisticated users could share
-payment receipts as well, but this is not as easy as sharing a link,
-and in this case they are more likely to just share the media
-directly.
-
-To use this feature, the merchant must first assign the user's current browser
-an ephemeral @code{session_id}, usually via a session cookie.  When executing
-or re-playing a payment, the wallet will receive an additional signature
-(@code{session_sig}).  This signature certifies that the wallet
-showed a payment receipt for the respective order in the current session.
-@cindex cookie
-
-Session-bound payments are triggered by passing the @code{session_id} parameter
-to the @code{/check-payment} endpoint.  The wallet will then redirect to the
-fulfillment page, but include an additional @code{session_sig} parameter.  The
-frontend can query @code{/check-payment} with both the @code{session_id} and
-the @code{session_sig} to verify that the signature is correct.
-
-The last session ID that was successfully used to prove that the payment
-receipt is in the user's wallet is also available as @code{last_session_id} in
-the response to @code{/check-payment}.
-@c FIXME: used for what?
-
-@node Product Identification
-@section Product Identification
-@cindex resource url
-
-In some situations the user may have paid for some digital good, but the 
frontend
-does not know the exact order ID, and thus cannot instruct the wallet to reveil
-the existing payment receipt.  This is common for simple shops without a login
-system.  In this case, the user would be prompted for payment again, even
-though they already purchased the product.
-
-To allow the wallet to instead find the existing payment receipt, the
-shop must use a unique fulfillment URL for each product.  Then, the
-frontend must provide an additional @code{resource_url} parameter to
-to @code{/check-payment}.  It should identify this unique fulfillment
-URL for the product.  The wallet will then check whether it has paid
-for a contract with the same @code{resource_url} before, and if so
-replay the previous payment.
-@c FIXME: design question (!): why do we not simply set a flag (``unique 
fulfillment url'')
-@c instead of passing the fulfillment URL a *second* time to the backend?
-@c (and having to worry about it being the same as in the order on /order)?
-
-
-@c Section describing the format of Taler contracts/proposals in detail
-
-@node The Taler Order Format
-@section The Taler Order Format
-@cindex contract
-@cindex terms
-@cindex order
-
-A Taler order can specify many details about the payment.
-This section describes each of the fields in depth.
-
-Financial amounts are always specified as a string in the format 
@code{"CURRENCY:DECIMAL_VALUE"}.
-
-@table @var
-@item amount
-@cindex amount
-Specifies the total amount to be paid to the merchant by the customer.
-
-@item max_fee
-@cindex fees
-@cindex maximum deposit fee
-This is the maximum total amount of deposit fees that the merchant is
-willing to pay.  If the deposit fees for the coins exceed this amount,
-the customer has to include it in the payment total.  The fee is
-specified using the same triplet used for @var{amount}.
-
-
-@item max_wire_fee
-@cindex fees
-@cindex maximum wire fee
-Maximum wire fee accepted by the merchant (customer share to be
-divided by the 'wire_fee_amortization' factor, and further reduced
-if deposit fees are below 'max_fee').  Default if missing is zero.
-
-
-@item wire_fee_amortization
-@cindex fees
-@cindex maximum fee amortization
-Over how many customer transactions does the merchant expect to
-amortize wire fees on average?  If the exchange's wire fee is
-above 'max_wire_fee', the difference is divided by this number
-to compute the expected customer's contribution to the wire fee.
-The customer's contribution may further be reduced by the difference
-between the 'max_fee' and the sum of the actual deposit fees.
-Optional, default value if missing is 1.  0 and negative values are
-invalid and also interpreted as 1.
-
-@item pay_url
-@cindex pay_url
-Which URL accepts payments. This is the URL where the wallet will POST
-coins.
-
-@item fulfillment_url
-@cindex fulfillment URL
-Which URL should the wallet go to for obtaining the fulfillment,
-for example the HTML or PDF of an article that was bought, or an
-order tracking system for shipments, or a simple human-readable
-Web page indicating the status of the contract.
-
-@item order_id
-@cindex order ID
-Alphanumeric identifier, freely definable by the merchant.
-Used by the merchant to uniquely identify the transaction.
-
-@item summary
-@cindex summary
-Short, human-readable summary of the contract. To be used when
-displaying the contract in just one line, for example in the
-transaction history of the customer.
-
-@item timestamp
-Time at which the offer was generated.
-@c FIXME: describe time format in detail here
-
-@item pay_deadline
-@cindex payment deadline
-Timestamp of the time by which the merchant wants the exchange
-to definitively wire the money due from this contract.  Once
-this deadline expires, the exchange will aggregate all
-deposits where the contracts are past the @var{refund_deadline}
-and execute one large wire payment for them.  Amounts will be
-rounded down to the wire transfer unit; if the total amount is
-still below the wire transfer unit, it will not be disbursed.
-
-@item refund_deadline
-@cindex refund deadline
-Timestamp until which the merchant willing (and able) to give refunds
-for the contract using Taler.  Note that the Taler exchange will hold
-the payment in escrow at least until this deadline.  Until this time,
-the merchant will be able to sign a message to trigger a refund to the
-customer.  After this time, it will no longer be possible to refund
-the customer.  Must be smaller than the @var{pay_deadline}.
-
-@item products
-@cindex product description
-Array of products that are being sold to the customer.  Each
-entry contains a tuple with the following values:
-
-@table @var
-@item description
-Description of the product.
-@item quantity
-Quantity of the items to be shipped. May specify a unit (@code{1 kg})
-or just the count.
-@item price
-Price for @var{quantity} units of this product shipped to the
-given @var{delivery_location}. Note that usually the sum of all
-of the prices should add up to the total amount of the contract,
-but it may be different due to discounts or because individual
-prices are unavailable.
-@item product_id
-Unique ID of the product in the merchant's catalog.  Can generally
-be chosen freely as it only has meaning for the merchant, but
-should be a number in the range @math{[0,2^{51})}.
-@item taxes
-Map of applicable taxes to be paid by the merchant.  The label is the
-name of the tax, i.e. @var{VAT}, @var{sales tax} or @var{income tax},
-and the value is the applicable tax amount.  Note that arbitrary
-labels are permitted, as long as they are used to identify the
-applicable tax regime.  Details may be specified by the regulator.
-This is used to declare to the customer which taxes the merchant
-intends to pay, and can be used by the customer as a receipt.
-@c FIXME: a receipt not including the item's price?
-The information is also likely to be used by tax audits of the merchant.
-@item delivery_date
-Time by which the product is to be delivered to the
-@var{delivery_location}.
-@item delivery_location
-This should give a label in the @var{locations} map, specifying
-where the item is to be delivered.
-@end table
-Values can be omitted if they are not applicable. For example, if a
-purchase is about a bundle of products that have no individual prices
-or product IDs, the @var{product_id} or @var{price} may not be
-specified in the contract.  Similarly, for virtual products delivered
-directly via the fulfillment URI, there is no delivery location.
-
-@item merchant
-@table @var
-@item address
-This should give a label in the @var{locations} map, specifying
-where the merchant is located.
-@item name
-This should give a human-readable name for the merchant's business.
-@item jurisdiction
-This should give a label in the @var{locations} map, specifying
-the jurisdiction under which this contract is to be arbitrated.
-@end table
-
-@item locations
-@cindex location
-Associative map of locations used in the contract. Labels for
-locations in this map can be freely chosen and used whenever
-a location is required in other parts of the contract.  This way,
-if the same location is required many times (such as the business
-address of the customer or the merchant), it only needs to be
-listed (and transmitted) once, and can otherwise be referred to
-via the label.  A non-exhaustive list of location attributes
-is the following:
-@table @var
-@item country
-Name of the country for delivery, as found on a postal package, i.e. 
``France''.
-@item state
-Name of the state for delivery, as found on a postal package, i.e. ``NY''.
-@item region
-Name of the region for delivery, as found on a postal package.
-@item province
-Name of the province for delivery, as found on a postal package.
-@item city
-Name of the city for delivery, as found on a postal package.
-@item ZIP code
-ZIP code for delivery, as found on a postal package.
-@item street
-Street name for delivery, as found on a postal package.
-@item street number
-Street number (number of the house) for delivery, as found on a postal package.
-@item name receiver name for delivery, either business or person name.
-
-@end table
-
-Note that locations are not required to specify all of these fields,
-and they is also allowed to have additional fields.  Contract renderers
-must render at least the fields listed above, and should render fields
-that they do not understand as a key-value list.
-
-@end table
-
-
-@c **********************************************************
-@c *******************  Appendices  *************************
-@c **********************************************************
-
-@node GNU-LGPL
-@unnumbered GNU-LGPL
-@cindex license
-@cindex LGPL
-@include lgpl.texi
-
-@node GNU-FDL
-@unnumbered GNU-FDL
-@cindex license
-@cindex GNU Free Documentation License
-@include fdl-1.3.texi
-
-@node Concept Index
-@unnumbered Concept Index
-
-@printindex cp
diff --git a/doc/next_steps.txt b/doc/next_steps.txt
deleted file mode 100644
index e5f477d..0000000
--- a/doc/next_steps.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-NEXT STEPS:
-===========
-
-- Bridge (1w) ->17.02. - 20.02.
-- Video for Bachelorthesis
-- Acknowledgements
-
-- Abstract (1d) ->14.02.
-
-- Thesis:
-       - Motivation (1d) ->14.02.
-       - Related work (1w) ->14.02.
-       - Task schedule (1d) ->14.02.
-       - Reflection
-       - Design (Architecture) (1d) ->14.02.
-       - Crypto (formulas) (3d) 
-       - Implementation (C, libraries used, testing) (2-3d)
-       - Evaluation (UX?)
-       - Conclusion (1d)
-       - Business model (1-2d) ->14.02.
-
-- Client REST API, tests running (2d) 
-       ->14.02. (just compiling) 
-       ->17.02. - 20.02. (tests running)
-- Crypto API + Implementation (7 -14d) 
-       ->17.02. - 20.02. (Crypto API Design) 
-       ->24.02. - 27.02. (Crypto Implementation + tests)
-- Implementation Client (lib) (7d)
-- Authentication backends (7d/backend)
-       - password/security question
-       - email
-       - SMS
-- System integration (CLI) (7d)
-
-=> Sum: 10W
-
-
-
diff --git a/doc/taler-config.texi b/doc/taler-config.texi
deleted file mode 100644
index efca5a2..0000000
--- a/doc/taler-config.texi
+++ /dev/null
@@ -1,47 +0,0 @@
-@c This file is used both in the exchange and merchant
-@c manuals. Edits should be propagated to both Gits!
-
-@node Using taler-config
-@section Using taler-config
-@cindex taler-config
-
-The tool @code{taler-config} can be used to
-extract or manipulate configuration values; however, the configuration
-use the well-known INI file format and can also be edited by hand.
-
-Run
-@example
-$ taler-config -s $SECTION
-@end example
-to list all of the configuration values in section @code{$SECTION}.
-
-Run
-@example
-$ taler-config -s $section -o $option
-@end example
-to extract the respective configuration value for option @code{$option}
-in section @code{$section}.
-
-Finally, to change a setting, run
-@example
-$ taler-config -s $section -o $option -V $value
-@end example
-to set the respective configuration value to @code{$value}. Note that you have 
to
-manually restart the Taler backend after you change the configuration to
-make the new configuration go into effect.
-
-Some default options will use $-variables, such as @code{$DATADIR}
-within their value.  To expand the @code{$DATADIR} or other $-variables
-in the configuration, pass the @code{-f} option to
-@code{taler-config}.  For example, compare:
-@example
-$ taler-config -s ACCOUNT-bank \
-               -o WIRE_RESPONSE
-$ taler-config -f -s ACCOUNT-bank \
-               -o WIRE_RESPONSE
-@end example
-
-While the configuration file is typically located at
-@code{$HOME/.config/taler.conf}, an alternative location can be
-specified to @code{taler-merchant-httpd} and @code{taler-config} using
-the @code{-c} option.

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]