summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--anastasis-db.pngbin38801 -> 0 bytes
-rw-r--r--anastasis.rst2705
-rw-r--r--anastasis_challenge_payment.pngbin20331 -> 0 bytes
-rw-r--r--anastasis_challengecode.pngbin17678 -> 0 bytes
-rw-r--r--anastasis_reducer_backup.drawio1
-rw-r--r--anastasis_reducer_backup.pngbin59981 -> 0 bytes
-rw-r--r--anastasis_reducer_backup.svg3
-rw-r--r--anastasis_reducer_recovery.drawio1
-rw-r--r--anastasis_reducer_recovery.pngbin52610 -> 0 bytes
-rw-r--r--anastasis_reducer_recovery.svg3
-rw-r--r--anastasis_truth.pngbin19493 -> 0 bytes
-rw-r--r--anastasis_truth_payment.pngbin13430 -> 0 bytes
-rw-r--r--conf.py4
-rw-r--r--core/api-auditor.rst6
-rw-r--r--core/api-bank-access.rst6
-rw-r--r--core/api-bank-integration.rst6
-rw-r--r--core/api-bank-merchant.rst6
-rw-r--r--core/api-common.rst9
-rw-r--r--core/api-error.rst6
-rw-r--r--core/api-exchange.rst6
-rw-r--r--core/api-merchant.rst6
-rw-r--r--core/api-sync.rst6
-rw-r--r--core/api-wire.rst6
-rw-r--r--core/index.rst6
-rw-r--r--design-documents/006-anastasis-ux.rst318
-rw-r--r--design-documents/index.rst1
-rw-r--r--fdl-1.3.rst4
-rw-r--r--index.rst8
-rw-r--r--taler-auditor-manual.rst6
-rw-r--r--taler-developer-manual.rst8
-rw-r--r--taler-exchange-manual.rst6
-rw-r--r--taler-mcig.rst6
-rw-r--r--taler-merchant-api-tutorial.rst6
-rw-r--r--taler-merchant-pos-terminal.rst6
34 files changed, 60 insertions, 3095 deletions
diff --git a/anastasis-db.png b/anastasis-db.png
deleted file mode 100644
index 03eed9da..00000000
--- a/anastasis-db.png
+++ /dev/null
Binary files differ
diff --git a/anastasis.rst b/anastasis.rst
deleted file mode 100644
index 0cca44b6..00000000
--- a/anastasis.rst
+++ /dev/null
@@ -1,2705 +0,0 @@
-..
- This file is part of Anastasis
- Copyright (C) 2019-2021 Anastasis SARL
-
- Anastasis is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2.1, or (at your option) any later version.
-
- Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License along with
- Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-
- @author Christian Grothoff
- @author Dominik Meister
- @author Dennis Neufeld
-
-=========
-Anastasis
-=========
-
-Anastasis is a service that allows the user to securely deposit a
-**core secret** with an open set of escrow providers and recover it if the secret is
-lost. The **core secret** itself is protected from the escrow providers by
-encrypting it with a **master key**. The main objective of Anastasis is to
-ensure that the user can reliably recover the **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" **identifier** is used. This
-identifier should be difficult to guess for anybody but the user. However, the
-**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 **identifier**, and strong
-adversaries which somehow do know a user's **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
-**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 **recovery document** includes all of the information a user needs to
-recover access to their core secret. It specifies a set of **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 **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 **recovery document** also specifies **policies**, which
-describe the combination(s) of the escrow methods that suffice to obtain
-access to the core secret. For example, a **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
-**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 **recovery document** (except for its length, which
-may be exposed to an adversary which monitors the user's network traffic).
-
-----------------------
-Anastasis Installation
-----------------------
-
-Please install the following packages before proceeding with the
-exchange compilation.
-
-.. include:: frags/list-of-dependencies.rst
-
-- GNU Taler exchange
-
-- GNU Taler merchant backend
-
-Except for the last two, these are available in most GNU/Linux distributions
-and should just be installed using the respective package manager.
-
-
-Installing from source
-----------------------
-
-The following instructions will show how to install libgnunetutil and
-the GNU Taler exchange from source.
-
-Installing GNUnet
-^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-gnunet.rst
-
-Installing the Taler Exchange
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-taler-exchange.rst
-
-Installing the Taler Merchant
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-taler-merchant.rst
-
-Installing Anastasis
-^^^^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-anastasis.rst
-
-Installing GNUnet-gtk
-^^^^^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-gnunet-gtk.rst
-
-Installing Anastasis-gtk
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. include:: frags/installing-anastasis-gtk.rst
-
-
-
-Installing Anastasis binary packages on Debian
-----------------------------------------------
-
-.. include:: frags/installing-debian.rst
-
-
-Installing the graphical front-end
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To install the Anastasis front-end, you can now simply run:
-
-.. code-block:: console
-
- # apt install -t sid anastasis-gtk
-
-To use ``anastasis-gtk``, you can simply run:
-
-.. code-block:: console
-
- $ anastasis-gtk
-
-Installing the backend
-^^^^^^^^^^^^^^^^^^^^^^
-
-If you want to install the Anastasis backend-end (which normal users do not
-need), you should run:
-
-.. code-block:: console
-
- # apt install -t sid anastasis-httpd
-
-Note that the latter package does not perform all of the configuration work.
-It does setup the user users and the systemd service scripts, but you still
-must configure the database backup, HTTP reverse proxy (typically with TLS
-certificates), Taler merchant backend for payments, authentication services,
-prices and the terms of service.
-
-Sample configuration files for the HTTP reverse proxy can be found in
-``/etc/anastasis.conf``.
-
-
-Installing Anastasis binary packages on Ubuntu
-----------------------------------------------
-
-.. include:: frags/installing-ubuntu.rst
-
-Installing the graphical front-end
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To install the Anastasis front-end, you can now simply run:
-
-.. code-block:: console
-
- # apt install -t focal-fossa anastasis-gtk
-
-To use ``anastasis-gtk``, you can simply run:
-
-.. code-block:: console
-
- $ anastasis-gtk
-
-Installing the backend
-^^^^^^^^^^^^^^^^^^^^^^
-
-If you want to install the Anastasis backend-end (which normal users do not
-need), you should run:
-
-.. code-block:: console
-
- # apt install -t focal-fossa anastasis-httpd
-
-Note that the latter package does not perform all of the configuration work.
-It does setup the user users and the systemd service scripts, but you still
-must configure the database backup, HTTP reverse proxy (typically with TLS
-certificates), Taler merchant backend for payments, authentication services,
-prices and the terms of service.
-
-Sample configuration files for the HTTP reverse proxy can be found in
-``/etc/anastasis.conf``.
-
-
-----------------------
-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 **identifier** using
-different HKDFs. These HKDFs are salted using the respective escrow
-provider's **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 **account key** to identify the account of
-the user. The account private key is derived from the user's **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 **identifier** and a high-entropy **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 **core secret** of the user is (AES) encrypted using a symmetric **master
-key**. Recovering this master key requires the user to satisfy a particular
-**policy**. Policies specify a set of **escrow methods**, each of which leads
-the user to a **key share**. Combining those key shares (by hashing) allows
-the user to obtain a **policy key**, which can be used to decrypt the **master
-key**. There can be many policies, satisfying any of these will allow the
-user to recover the master key. A **recovery document** contains the
-encrypted **core secret**, a set of escrow methods and a set of policies.
-
-
-
-
-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
-**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 **identifier**.
-
-This identifier will be first hashed with Argon2, to provide a **kdf_id**
-which will be used to derive other keys later. The Hash must also include the
-respective **server_salt**. This also ensures that the **kdf_id** is different
-on each server. The use of Argon2 and the respective **server_salt** is intended
-to make it difficult to brute-force **kdf_id** values and help protect the user's
-privacy. Also this ensures that the **kdf_id**\ s on every server differs. However,
-we do not assume that the **identifier** or the **kdf_id** cannot be
-determined by an adversary performing a targeted attack, as a user's
-**identifier** is likely to always be known to state actors and may
-likely also be available to other actors.
-
-
-.. code-block:: none
-
- kdf_id := Argon2( identifier, server_salt, keysize )
-
-**identifier**: The secret defined from the user beforehand.
-
-**server_salt**: The salt from the Server.
-
-**keysize**: The desired output size of the KDF, here 32 bytes.
-
-
-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 **kdf_id**, decrypt) the user's policy (but
-not the core secret), or upload a new version of the
-**encrypted recovery document** (but not delete an existing version).
-
-For the generation of the private key we use the **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
-**kdf_id**.
-
-.. code-block:: none
-
- ver_secret := HKDF(kdf_id, "ver", keysize)
- eddsa_priv := eddsa_d_to_a(ver_secret)
- eddsa_pub := get_EdDSA_Pub(eddsa_priv)
-
-
-**HKDF()**: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
-
-**kdf_id**: Hashed identifier.
-
-**key_size**: Size of the output, here 32 bytes.
-
-**ver_secret**: Derived key from the ``kdf_id``, serves as intermediate step for the generation of the private key.
-
-**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:
-
-.. code-block:: c
-
- digest[0] = (digest[0] & 0x7f) | 0x40;
- digest[31] &= 0xf8;
-
-**eddsa_priv**: The generated EdDSA private key.
-
-**eddsa_pub**: The generated EdDSA public key.
-
-
-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``.
-
-.. code-block:: none
-
- (iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)
-
-**HKDF()**: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
-
-**kdf_id**: Hashed identifier.
-
-**keysize**: Size of the AES symmetric key, here 32 bytes.
-
-**ivsize**: Size of the AES GCM IV, here 12 bytes.
-
-**prekey**: Original key material.
-
-**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).
-
-**key**: Symmetric key which is later used to encrypt the documents with AES256-GCM.
-
-**iv**: IV which will be used for AES-GCM.
-
-
-
-Key Usage
-^^^^^^^^^
-
-The keys we have generated are then used to encrypt the **recovery document** and
-the **key_share** of the user.
-
-
-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 **recovery document** and
-the **key_share**. To ensure that the key derivation for the encryption
-of the **recovery document** differs fundamentally from that of an
-individual **key share**, we use different salts ("erd" and "eks", respectively).
-
-.. code-block:: none
-
- (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)
-
-**encrypted_recovery_document**: The encrypted **recovery document** which contains the escrow methods, policies
-and the encrypted **core secret**.
-
-**nonce0**: Nonce which is used to generate *key0* and *iv0* which are used for the encryption of the *recovery document*.
-Nonce must contain the string "ERD".
-
-**optional data**: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider.
-
-**encrypted_key_share_i**: The encrypted **key_share** which the escrow provider must release upon successful authentication.
-Here, **i** must be a positive number used to iterate over the various **key shares** used for the various **escrow methods**
-at the various providers.
-
-**nonce_i**: Nonce which is used to generate *key_i* and *iv_i* which are used for the encryption of the **key share**. **i** must be
-the same number as specified above for *encrypted_key_share_i*. Nonce must contain the string "EKS" plus the according *i*.
-
-As a special rule, when a **security question** is used to authorize access to an
-**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:
-
-.. code-block:: none
-
- 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)
-
-
-**qsalt**: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing.
-
-**answer**: Answer to the security question, in UTF-8, as entered by the user.
-
-**powh**: Result of the (expensive, proof-of-work) hash algorithm.
-
-**uuid**: UUID of the challenge associated with the security question and the encrypted key share.
-
-**ekss**: Replacement salt to be used instead of "eks" when deriving the key to encrypt/decrypt the key share.
-
-
-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 **Anastasis-Policy-Signature**.
-
-.. code-block:: none
-
- (anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv)
- ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)
-
-**anastasis-account-signature**: Signature over the SHA-512 hash of the body using the purpose code ``TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD`` (1400) (see GNUnet EdDSA signature API for the use of purpose).
-
-**h_body**: The hashed body.
-
-**ver_res**: A boolean value. True: Signature verification passed, False: Signature verification failed.
-
-
-When requesting policy downloads, the client must also provide a signature:
-
-.. code-block:: none
-
- (anastasis-account-signature) := eddsa_sign(version, eddsa_priv)
- ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)
-
-**anastasis-account-signature**: Signature over the SHA-512 hash of the body using the purpose code ``TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD`` (1401) (see GNUnet EdDSA signature API for the use of purpose).
-
-**version**: The version requested as a 64-bit integer, 2^64-1 for the "latest version".
-
-**ver_res**: A boolean value. True: Signature verification passed, False: Signature verification failed.
-
-
-
-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 **payment identifier** from a payment
-made by the user. Thus, a policy upload requires both knowledge of the
-**identity** and making a payment. This effectively prevents an adversary
-from using the append-only policy storage from exhausting Anastasis server
-capacity.
-
-
-
-------------------
-Anastasis REST API
-------------------
-
-.. _salt:
-.. _config:
-
-Receiving Configuration
-^^^^^^^^^^^^^^^^^^^^^^^
-
-.. http:get:: /config
-
- Obtain the configuration details of the escrow provider.
-
- **Response:**
-
- Returns an `EscrowConfigurationResponse`_.
-
-
- .. _EscrowConfigurationResponse:
- .. ts:def:: EscrowConfigurationResponse
-
- 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;
-
- // 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;
-
- }
-
- .. _AuthorizationMethodConfig:
- .. ts:def:: AuthorizationMethodConfig
-
- interface AuthorizationMethodConfig {
- // Name of the authorization method.
- type: string;
-
- // Fee for accessing key share using this method.
- cost: Amount;
-
- }
-
-.. _terms:
-
-Receiving Terms of Service
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. http:get:: /terms
-
- Obtain the terms of service provided by the escrow provider.
-
- **Response:**
-
- Returns the terms of service of the provider, in the best language
- and format available based on the client's request.
-
-.. http:get:: /privacy
-
- Obtain the privacy policy of the service provided by the escrow provider.
-
- **Response:**
-
- Returns the privacy policy of the provider, in the best language
- and format available based on the client's request.
-
-
-.. _manage-policy:
-
-
-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 ``$ACCOUNT_PUB``, which
-should be kept secret from third parties. ``$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`_.
-
-.. _`RFC 4122`: https://tools.ietf.org/html/rfc4122
-
-.. http: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:
-
- * the escrow policy
- * the separately encrypted master public key
-
- 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 **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.
-
- **Response**:
-
- :http:statuscode:`200 OK`:
- The escrow provider responds with an EncryptedRecoveryDocument_ object.
- :http:statuscode:`304 Not modified`:
- The client requested the same resource it already knows.
- :http:statuscode:`400 Bad request`:
- The ``$ACCOUNT_PUB`` is not an EdDSA public key.
- :http:statuscode:`402 Payment Required`:
- The account's balance is too low for the specified operation.
- See the Taler payment protocol specification for how to pay.
- :http:statuscode:`403 Forbidden`:
- The required account signature was invalid.
- :http:statuscode:`404 Not found`:
- The requested resource was not found.
-
- *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 EncryptedRecoveryDocument_.
-
- *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``.
-
- *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.
-
- *Anastasis-Account-Signature*: The client must provide Base-32 encoded EdDSA signature over hash of body with ``$ACCOUNT_PRIV``, affirming desire to download the requested encrypted recovery document. The purpose used MUST be ``TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD`` (1401).
-
-.. http: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.
-
- **Request**:
-
- :query storage_duration=YEARS:
- For how many years from now would the client like us to
- store the recovery document? Defaults to 0 (that is, do
- not extend / prolong existing storage contract).
- The server will respond with a ``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 ``304 Not modified``
- case.
- :query timeout_ms=NUMBER: *Optional.* If specified, the Anastasis server will
- wait up to ``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.
-
- *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.
-
- *Anastasis-Policy-Signature*: The client must provide Base-32 encoded EdDSA signature over hash of body with ``$ACCOUNT_PRIV``, affirming desire to upload an encrypted recovery document.
-
- *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 **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 return a ``402`` response. When making payments, the server must include a fresh, randomly-generated payment-identifier in the payment request.
-
- **Response**:
-
- :http:statuscode:`204 No content`:
- 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.
- :http:statuscode:`304 Not modified`:
- The same encrypted recovery document was previously accepted and stored. ``Anastasis-Version`` header
- indicates what version was previously assigned to this encrypted recovery document.
- :http:statuscode:`400 Bad request`:
- The ``$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.
- :http:statuscode:`402 Payment required`:
- 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.
- :http:statuscode:`403 Forbidden`:
- The required account signature was invalid. The response body may elaborate on the error.
- :http:statuscode:`413 Request entity too large`:
- The upload is too large *or* too small. The response body may elaborate on the error.
-
- **Details:**
-
- .. _EncryptedRecoveryDocument:
- .. ts:def:: EncryptedRecoveryDocument
-
- 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
-
- }
-
- .. _RecoveryDocument:
- .. ts:def:: RecoveryDocument
-
- 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[];
-
- }
-
- .. _EscrowMethod:
- .. ts:def:: EscrowMethod
-
- 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
-
- }
-
- .. _DecryptionPolicy:
- .. ts:def:: DecryptionPolicy
-
- 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[];
-
- }
-
-.. _Truth:
-
-Managing truth
-^^^^^^^^^^^^^^
-
-This API is used by the Anastasis client to deposit **truth** or request a (encrypted) **key share** with
-the escrow provider.
-
-An **escrow method** specifies an Anastasis provider and how the user should
-authorize themself. The **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.
-
-.. http:post:: /truth/$UUID
-
- Upload a `TruthUploadRequest`_-Object according to the policy the client created before (see `RecoveryDocument`_).
- If request has been seen before, the server should do nothing, and otherwise store the new object.
-
- **Request:**
-
- :query timeout_ms=NUMBER: *Optional.* If specified, the Anastasis server will
- wait up to ``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.
-
- **Response:**
-
- :http:statuscode:`204 No content`:
- Truth stored successfully.
- :http:statuscode:`304 Not modified`:
- 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.
- :http:statuscode:`402 Payment required`:
- 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.
- :http:statuscode:`409 Conflict`:
- The server already has some truth stored under this UUID. The client should check that it
- is generating UUIDs with enough entropy.
- :http:statuscode:`412 Precondition failed`:
- The selected authentication method is not supported on this provider.
-
-
- **Details:**
-
- .. _TruthUploadRequest:
- .. ts:def:: TruthUploadRequest
-
- 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;
-
- // For how many years from now would the client like us to
- // store the truth?
- storage_duration_years: integer;
-
- }
-
-.. http:get:: /truth/$UUID[?response=$H_RESPONSE]
-
- Get the stored encrypted key share. If ``$H_RESPONSE`` is specified by the client, the server checks
- if ``$H_RESPONSE`` matches the expected response specified before within the `TruthUploadRequest`_ (see ``encrypted_truth``).
- Also, the user has to provide the correct *truth_encryption_key* with every get request (see below).
- When ``$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.
-
- **Response**:
-
- :http:statuscode:`200 OK`:
- `EncryptedKeyShare`_ is returned in body (in binary).
- :http:statuscode:`202 Accepted`:
- The escrow provider will respond out-of-band (i.e. SMS).
- The body may contain human-readable instructions on next steps.
- :http:statuscode:`208 Already Reported`:
- An authentication challenge was recently send, client should
- simply respond to the pending challenge.
- :http:statuscode:`303 See other`:
- 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.
- :http:statuscode:`402 Payment required`:
- 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.
- :http:statuscode:`403 Forbidden`:
- The server requires a valid "response" to the challenge associated with the UUID.
- :http:statuscode:`404 Not found`:
- The server does not know any truth under the given UUID.
- :http:statuscode:`410 Gone`:
- The server has not (recently) issued a challenge under the given UUID,
- but a reply was provided. (This does not apply for secure question.)
- :http:statuscode:`417 Expectation Failed`:
- 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.
- :http:statuscode:`503 Service Unavailable`:
- Server is out of Service.
-
- *Truth-Decryption-Key*: Key used to encrypt the **truth** (see encrypted_truth within `TruthUploadRequest`_) and which has to provided by the user. The key is stored with
- the according `EscrowMethod`_. The server needs this key to get the info out of `TruthUploadRequest`_ needed to verify the ``$RESPONSE``.
-
- **Details:**
-
- .. _EncryptedKeyShare:
- .. ts:def:: EncryptedKeyShare
-
- 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
-
- }
-
- .. _KeyShare:
- .. ts:def:: KeyShare
-
- 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;
-
- }
-
-
----------------------
-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 state_ in JSON syntax and returns the new state in JSON syntax.
-
-For example a **state** may take the following structure:
-
-.. code-block:: json
-
- {
- "backup_state": "CONTINENT_SELECTING",
- "continents": [
- "Europe",
- "North_America"
- ]
- }
-
-The new state depends on the previous one and on the transition action_ with its
-arguments given to the reducer. A **transition argument** also is a statement in JSON syntax:
-
-.. code-block:: json
-
- {
- "continent": "Europe"
- }
-
-The new state returned by the reducer with the state and transition argument defined
-above would look like following for the transition action_ ``select_continent``:
-
-.. code-block:: json
-
- {
- "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"
- }
- ]
- }
-
-States
-^^^^^^
-
-Overall, the reducer knows the following states:
-
- - **ERROR**: The transition led to an error. No further transitions are possible from
- this state, but the client may want to continue from a previous state.
- - **CONTINENT_SELECTING**: The user should specify the continent where they are living,
- so that we can show a list of countries to choose from.
- - **COUNTRY_SELECTING**: The user should specify the country where they are living,
- so that we can determine appropriate attributes, currencies and Anastasis
- providers.
- - **USER_ATTRIBUTES_COLLECTING**: The user should provide the country-specific personal
- attributes.
- - **AUTHENTICATIONS_EDITING**: The user should add authentication methods to be used
- during recovery.
- - **POLICIES_REVIEWING**: The user should review the recovery policies.
- - **SECRET_EDITING**: The user should edit the secret to be backed up.
- - **TRUTHS_PAYING**: The user needs to pay for one or more uploads of data associated
- with an authentication method.
- - **POLICIES_PAYING**: The user needs to pay for storing the recovery policy document.
- - **BACKUP_FINISHED**: A backup has been successfully generated.
- - **SECRET_SELECTING**: The user needs to select a recovery policy document with
- the secret that is to be recovered.
- - **CHALLENGE_SELECTING**: The user needs to select an authorization challenge to
- proceed with recovery.
- - **CHALLENGE_PAYING**: The user needs to pay to proceed with the authorization challenge.
- - **CHALLENGE_SOLVING**: The user needs to solve the authorization challenge.
- - **RECOVERY_FINISHED**: The secret of the user has been recovered.
-
-State names:
-
- - 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).
- - In COLLECTING-states, the user has to give certain values.
- - In EDITING-states, the user is free to choose which values he wants to give.
- - In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something.
- - in PAYING-states, the user must make a payment.
- - in FINISHED-states, the operation has definitively concluded.
-
-
-Backup Reducer
-^^^^^^^^^^^^^^
-.. _state:
-.. _action:
-.. figure:: anastasis_reducer_backup.png
- :name: fig-anastasis_reducer_backup
- :alt: fig-anastasis_reducer_backup
- :scale: 75 %
- :align: center
-
- Backup states and their transitions.
-
-
-The illustration above shows the different states the reducer can have during a backup
-process.
-
-
-Recovery Reducer
-^^^^^^^^^^^^^^^^
-.. figure:: anastasis_reducer_recovery.png
- :name: fig-anastasis_reducer_recovery
- :alt: fig-anastasis_reducer_recovery
- :scale: 75 %
- :align: center
-
- Recovery states and their transitions.
-
-
-The illustration above shows the different states the reducer can have during a recovery
-process.
-
-
-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.
-
-
-Initial state
--------------
-
-The initial states for backup and recovery processes are:
-
-**Initial backup state:**
-
-.. code-block:: json
-
- {
- "backup_state": "CONTINENT_SELECTING",
- "continents": [
- "Europe",
- "North America"
- ]
- }
-
-
-**Initial recovery state:**
-
-.. code-block:: json
-
- {
- "recovery_state": "CONTINENT_SELECTING",
- "continents": [
- "Europe",
- "North America"
- ]
- }
-
-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:
-
-.. code-block:: json
-
- {
- "recovery_state": "CONTINENT_SELECTING",
- "continents": [
- "Europe",
- "North America"
- ]
- "continents_i18n":
- {
- "de_DE" : [
- "Europa",
- "Nordamerika"
- ],
- "de_CH" : [
- "Europa",
- "Nordamerika"
- ]
- }
- }
-
-Translations must be given in the same order as the main English array.
-
-
-Common transitions
-------------------
-
-**select_continent:**
-
-Here the user specifies the continent they live on. Arguments (example):
-
-.. code-block:: json
-
- {
- "continent": "Europe"
- }
-
-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:
-
-.. code-block:: json
-
- {
- "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"
- }
- ]
- }
-
-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 **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.
-
-
-**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):
-
-.. code-block:: json
-
- {
- "country_code": "de",
- "currency": "EUR"
- }
-
-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:
-
-.. code-block:: json
-
- {
- "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"
- }
- }
- }
-
-The array of ``required_attributes`` contains attributes about the user
-that must be provided includes:
-
- - **type**: The type of the attribute, for now only ``string`` and ``date`` are
- supported.
- - **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.
- - **label**: A human-readable description of the attribute in English.
- Translated descriptions may be provided under **label_i18n**.
- - **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 **name**,
- only the **uuid** will be identical if the semantics is identical.
- - **widget**: An optional name of a widget that is known to nicely render
- the attribute entry in user interfaces where named widgets are
- supported.
- - **validation-regex**: An optional extended POSIX regular expression
- that is to be used to validate (string) inputs to ensure they are
- well-formed.
- - **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).
- - **optional**: Optional boolean field that, if ``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.
-
-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:
-
- - **http_status**: HTTP status code, always ``200`` on success.
- - **methods**: Array of authentication methods supported by this
- provider. Includes the **type** of the authentication method
- and the **usage_fee** (how much the user must pay for authorization
- using this method during recovery).
- - **annual_fee**: Fee the provider charges to store the recovery
- policy for one year.
- - **truth_upload_fee**: Fee the provider charges to store a key share.
- - **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.
- - **currency**: Currency in which the provider wants to be paid,
- will match all of the fees.
- - **storage_limit_in_megabytes**: Maximum size of an upload (for
- both recovery document and truth data) in megabytes.
- - **provider_name**: Human-readable name of the provider's business.
- - **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.
-
-If contacting the provider failed, the information returned is:
-
- - **http_status**: HTTP status code (if available, possibly 0 if
- we did not even obtain an HTTP response).
- - **error_code**: Taler error code, never 0.
-
-
-**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:
-
-.. code-block:: json
-
- {
- "urls": [
- "http://localhost:8888/",
- "http://localhost:8089/"
- ]
- }
-
-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:
-
-.. code-block:: json
-
- {
- "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"
- }
- }
- }
-
-
-
-Backup transitions
-------------------
-
-**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 ``null`` or an empty string). Example
-arguments would be:
-
-.. code-block:: json
-
- {
- "identity_attributes": {
- "full_name": "Max Musterman",
- "social_security_number": "123456789",
- "birthdate": "2000-01-01",
- "birthplace": "Earth"
- }
- }
-
-Note that at this stage, the state machines between backup and
-recovery diverge and the ``recovery_state`` will begin to look
-very different from the ``backup_state``.
-
-For backups, if all required attributes are present, the reducer will
-transition to an ``AUTHENTICATIONS_EDITING`` state with the attributes added
-to it:
-
-.. code-block:: json
-
- {
- "backup_state": "AUTHENTICATIONS_EDITING",
- "identity_attributes": {
- "full_name": "Max Musterman",
- "social_security_number": "123456789",
- "birthdate": "2000-01-01",
- "birthplace": "Earth"
- }
- }
-
-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:
-
-.. code-block:: json
-
- {
- "backup_state": "ERROR",
- "code": 8404,
- "hint": "An input did not match the regular expression.",
- "detail": "social_security_number"
- }
-
-Clients may safely repeat this transition to validate the user's inputs
-until they satisfy all of the constraints. This way, the user interface
-does not have to perform the input validation directly.
-
-
-**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 ``type`` and ``instructions`` to
-be given to the user. The ``challenge`` is encrypted and stored at the
-Anastasis provider. The specific semantics of the value depend on the
-``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 ``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 ``mime_type`` field must be provided to give the MIME type
-of the value encoded in ``challenge``.
-
-.. code-block:: json
-
- {
- "authentication_method":
- {
- "type": "question",
- "mime_type" : "text/plain",
- "instructions" : "What is your favorite GNU package?",
- "challenge" : "E1QPPS8A",
- }
- }
-
-If the information provided is valid, the reducer will add the new
-authentication method to the array of authentication methods:
-
-.. code-block:: json
-
- {
- "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"
- }
- ]
- }
-
-
-**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:
-
-.. code-block:: json
-
- {
- "authentication_method": 1
- }
-
-Assuming we begin with the state from the example above, this would
-remove the ``email`` authentication method, resulting in the following
-response:
-
-.. code-block:: json
-
- {
- "backup_state": "AUTHENTICATIONS_EDITING",
- "authentication_methods": [
- {
- "type": "question",
- "mime_type" : "text/plain",
- "instructions" : "What is your favorite GNU package?",
- "challenge" : "gdb",
- }
- ]
- }
-
-If the index is invalid, the reducer will instead
-transition into an ``ERROR`` state.
-
-
-**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:
-
-.. code-block:: json
-
- {
- "providers": [
- "http://localhost:8088/",
- "http://localhost:8089/"
- ]
- }
-
-The resulting state provides the suggested recovery policies in a way suitable
-for presentation to the user:
-
-.. code-block:: javascript
-
- {
- "backup_state": "POLICIES_REVIEWING",
- "policy_providers" : [
- { "provider_url" : "http://localhost:8088/" },
- { "provider_url" : "http://localhost:8089/" }
- ],
- "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/"
- }
- ]
- }
- ]
- }
-
-For each recovery policy, the state includes the specific details of which
-authentication ``methods`` must be solved to recovery the secret using this
-policy. The ``methods`` array specifies the index of the
-``authentication_method`` in the ``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.
-
-
-**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:
-
-.. code-block:: javascript
-
- {
- "policy": [
- {
- "authentication_method": 1,
- "provider": "http://localhost:8088/"
- },
- {
- "authentication_method": 3,
- "provider": "http://localhost:8089/"
- }
- ]
- }
-
-Note that the specified providers must already be in the
-``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:
-
-.. code-block:: json
-
- {
- "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/"
- }
- ]
- }
- ]
- }
-
-If the new policy is invalid, for example because it adds 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.
-
-
-**update_policy**:
-
-Using this transition, the user can modify an existing recovery policy
-in the state.
-The argument format is the same that is used in **add_policy**,
-except there is an additional key ``policy_index`` which
-identifies the policy to modify.
-An example for a possible argument would thus be:
-
-.. code-block:: javascript
-
- {
- "policy_index" : 1,
- "policy": [
- {
- "authentication_method": 1,
- "provider": "http://localhost:8088/"
- },
- {
- "authentication_method": 3,
- "provider": "http://localhost:8089/"
- }
- ]
- }
-
-If the new policy is invalid, for example because it adds 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
-modifying the policy.
-
-
-
-**delete_policy:**
-
-This transition allows the deletion of a recovery policy. The argument
-simply specifies the index of the policy to delete, for example:
-
-.. code-block:: json
-
- {
- "policy_index": 3
- }
-
-Given as input the state from the example above, the expected new state would
-be:
-
-.. code-block:: json
-
- {
- "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/"
- }
- ]
- }
- ]
- }
-
-If the index given is invalid, the reducer will transition into an ``ERROR`` state
-instead of deleting a policy.
-
-
-**delete_challenge:**
-
-This transition allows the deletion of an individual
-challenge from a recovery policy. The argument
-simply specifies the index of the policy and challenge
-to delete, for example:
-
-.. code-block:: json
-
- {
- "policy_index": 1,
- "challenge_index" : 1
- }
-
-Given as input the state from the example above, the expected new state would
-be:
-
-.. code-block:: json
-
- {
- "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/"
- }
- ]
- },
- {
- "methods": [
- {
- "authentication_method": 1,
- "provider": "http://localhost:8089/"
- },
- {
- "authentication_method": 2,
- "provider": "http://localhost:8088/"
- }
- ]
- }
- ]
- }
-
-If the index given is invalid, the reducer will transition into an ``ERROR`` state
-instead of deleting a challenge.
-
-
-**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 ``SECRET_EDITING`` state:
-
-.. code-block:: json
-
- {
- "backup_state": "SECRET_EDITING",
- "upload_fees" : [ "KUDOS:42" ],
- "expiration" : { "t_ms" : 1245362362 }
- }
-
-Here, ``upload_fees`` is an array of applicable upload fees for the
-given policy expiration time. This is an array because fees could
-be in different currencies. The final cost may be lower if the
-user already paid for some of the time.
-
-If the array of ``policies`` is currently empty, the reducer will transition
-into an ``ERROR`` state instead of allowing the user to continue.
-
-
-**enter_secret:**
-
-This transition provides the reducer with the actual core ``secret`` of the user
-that Anastasis is supposed to backup (and possibly recover). The argument is
-simply the Crockford-Base32 encoded ``value`` together with its ``mime`` type, or a ``text`` field with a human-readable secret text.
-For example:
-
-.. code-block:: javascript
-
- {
- "secret": {
- "value": "EDJP6WK5EG50",
- "mime" : "text/plain"
- },
- "expiration" : { "t_ms" : 1245362362 }
- }
-
-If the application is unaware of the format, it set the ``mime`` field to ``null``.
-The ``expiration`` field is optional.
-
-The reducer remains in the ``SECRET_EDITING`` state, but now the secret and
-updated expiration time are part of the state and the cost calculations will
-be updated.
-
-.. code-block:: json
-
- {
- "backup_state": "SECRET_EDITING",
- "core_secret" : {
- "value": "EDJP6WK5EG50",
- "mime" : "text/plain"
- },
- "expiration" : { "t_ms" : 1245362362 },
- "upload_fees" : [ "KUDOS:42" ]
- }
-
-
-**clear_secret:**
-
-This transition removes the core secret from the state. It is simply a
-convenience function to undo ``enter_secret`` without providing a new value
-immediately. The transition takes no arguments. The resuting state will no
-longer have the ``core_secret`` field, and be otherwise unchanged. Calling
-**clear_secret** on a state without a ``core_secret`` will result in an error.
-
-
-**enter_secret_name:**
-
-This transition provides the reducer with a name for the core ``secret`` of the user. This name will be given to the user as a hint when seleting a recovery policy document during recovery, prior to satisfying any of the challenges. The argument simply contains the name for the secret.
-Applications that have build-in support for Anastasis MUST prefix the
-secret name with an underscore and an application-specific identifier
-registered in GANA so that they can use recognize their own backups.
-An example argument would be:
-
-.. code-block:: javascript
-
- {
- "name": "_TALERWALLET_MyPinePhone",
- }
-
-Here, ``MyPinePhone`` might be chosen by the user to identify the
-device that was being backed up.
-
-The reducer remains in the ``SECRET_EDITING`` state, but now the
-secret name is updated:
-
-.. code-block:: json
-
- {
- "secret_name" : "_TALERWALLET_MyPinePhone"
- }
-
-
-**update_expiration:**
-
-This transition asks the reducer to change the desired expiration time
-and to update the associated cost. For example:
-
-.. code-block:: javascript
-
- {
- "expiration" : { "t_ms" : 1245362362 }
- }
-
-The reducer remains in the ``SECRET_EDITING`` state, but the
-expiration time and cost calculation will be updated.
-
-.. code-block:: json
-
- {
- "backup_state": "SECRET_EDITING",
- "expiration" : { "t_ms" : 1245362362 },
- "upload_fees" : [ { "fee": "KUDOS:43" } ]
- }
-
-
-**next** (from ``SECRET_EDITING``):
-
-Using this transition, the user confirms that the secret and expiration
-settings in the current state are acceptable. The transition does not take any
-arguments.
-
-If the secret is currently empty, the reducer will transition into an
-``ERROR`` state instead of allowing the user to continue.
-
-After adding a secret, the reducer may transition into different states
-depending on whether payment(s) are necessary. If payments are needed, the
-``secret`` will be stored in the state under ``core_secret``. Applications
-should be careful when persisting the resulting state, as the ``core_secret``
-is not protected in the ``PAYING`` states. The ``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
-``BACKUP_FINISHED`` state and (if applicable) delete the ``core_secret`` as an
-additional safety measure.
-
-Example results are thus:
-
-.. code-block:: json
-
- {
- "backup_state": "TRUTHS_PAYING",
- "secret_name" : "$NAME",
- "core_secret" : { "$anything":"$anything" },
- "payments": [
- "taler://pay/...",
- "taler://pay/..."
- ]
- }
-
-.. code-block:: json
-
- {
- "backup_state": "POLICIES_PAYING",
- "secret_name" : "$NAME",
- "core_secret" : { "$anything":"$anything" },
- "payments": [
- "taler://pay/...",
- "taler://pay/..."
- ]
- }
-
-.. code-block:: json
-
- {
- "backup_state": "BACKUP_FINISHED",
- }
-
-
-**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 ``timeout`` value that specifies how long the
-reducer may wait (in long polling) for the payment to complete:
-
-.. code-block:: json
-
- {
- "timeout": { "d_ms" : 5000 },
- }
-
-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
-``BACKUP_FINISHED`` state (if all payments have been completed and the backup
-finished), or into an ``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:
-
-.. code-block:: json
-
- {
- "backup_state": "ERROR",
- "http_status" : 500,
- "upload_status" : 52,
- "provider_url" : "https://bad.example.com/",
- }
-
-Here, the fields have the following meaning:
-
- - **http_status** is the HTTP status returned by the Anastasis provider.
- - **upload_status** is the Taler error code return by the provider.
- - **provider_url** is the base URL of the failing provider.
-
-In the above example, 52 would thus imply that the Anastasis provider failed to
-store information into its database.
-
-
-Recovery transitions
---------------------
-
-**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 ``null`` or an empty string). The
-arguments are identical to the **enter_user_attributes** transition from
-the backup process. Example arguments would thus be:
-
-.. code-block:: json
-
- {
- "identity_attributes": {
- "full_name": "Max Musterman",
- "social_security_number": "123456789",
- "birthdate": "2000-01-01",
- "birthplace": "Earth"
- }
- }
-
-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:
-
-.. code-block:: json
-
- {
- "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": {
- "...": "..."
- }
- }
-
-The ``recovery_document`` is an internal representation of the recovery
-information and of no concern to the user interface. The pertinent information
-is in the ``recovery_information``. Here, the ``challenges`` array is a list
-of possible challenges the user could attempt to solve next, while ``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 ``provider_url`` from where the recovery document was
-obtained and its ``version`` are also provided. Each challenge comes with
-four mandatory fields:
-
- - **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.
- - **cost**: This is the amount the Anastasis provider will charge
- to allow the user to pass the challenge.
- - **type**: This is the type of the challenge, as a string.
- - **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 ``type``.
-
-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 ``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:
-
-.. code-block:: json
-
- {
- "recovery_state": "ERROR",
- "error_message": "account unknown to Anastasis server",
- "error_code": 9,
- }
-
-Here, the ``error_code`` is from the ``enum ANASTASIS_RecoveryStatus``
-and describes precisely what failed about the download, while the
-``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.
-
-
-**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 ``change_version`` transition,
-which takes a provider URL and policy version as arguments:
-
-.. code-block:: json
-
- {
- "provider_url": "https://localhost:8080/",
- "version": 2
- }
-
-Note that using a version of 0 implies fetching "the latest version". The
-resulting states are the same as those of the ``enter_user_attributes``
-transition, except that the recovery document version is not necessarily the
-latest available version at the provider.
-
-
-**select_challenge:**
-
-Selecting a challenge takes different, depending on the state of the payment.
-A comprehensive example for ``select_challenge`` would be:
-
-.. code-block:: json
-
- {
- "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
- "timeout" : { "d_ms" : 5000 },
- "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
- }
-
-The ``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 ``payment_secret`` identifies the previous payment request, and
-``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 ``CHALLENGE_SOLVING`` or ``CHALLENGE_PAYING``
-states. In ``CHALLENGE_SOLVING``, the new state will primarily specify
-the selected challenge:
-
-.. code-block:: json
-
- {
- "backup_state": "CHALLENGE_SOLVING",
- "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
- }
-
-In ``CHALLENGE_PAYING``, the new state will include instructions for payment
-in the ``challenge_feedback``. In general, ``challenge_feedback`` includes
-information about attempted challenges, with the final state being ``solved``:
-
-.. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SELECTING",
- "recovery_information": {
- "...": "..."
- }
- "challenge_feedback": {
- "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
- "state" : "solved"
- }
- }
- }
-
-Challenges feedback for a challenge can have many different ``state`` values
-that applications must all handle. States other than ``solved`` are:
-
- - **payment**: Here, the user must pay for a challenge. An example would be:
-
- .. code-block:: json
-
- {
- "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"
- }
- }
- }
-
- - **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.
-
- .. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SOLVING",
- "recovery_information": {
- "...": "..."
- }
- "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
- "challenge_feedback": {
- "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
- "state": "body",
- "body": "CROCKFORDBASE32ENCODEDBODY",
- "http_status": 403,
- "mime_type" : "anything/possible"
- }
- }
- }
-
- - **hint**: Here, the server provided human-readable hint for
- how to solve the challenge. Note that the ``hint`` provided this
- time is from the Anastasis provider and may differ from the ``instructions``
- for the challenge under ``recovery_information``:
-
- .. code-block:: json
-
- {
- "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
- }
- }
- }
-
- - **details**: Here, the server provided a detailed JSON status response
- related to solving the challenge:
-
- .. code-block:: json
-
- {
- "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
- }
- }
- }
-
- - **redirect**: To solve the challenge, the user must visit the indicated
- Web site at ``redirect_url``, for example to perform video authentication:
-
- .. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SOLVING",
- "recovery_information": {
- "...": "..."
- }
- "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
- "challenge_feedback": {
- "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
- "state": "redirect",
- "redirect_url": "https://videoconf.example.com/",
- "http_status": 303
- }
- }
- }
-
- - **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.
-
- .. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SELECTING",
- "recovery_information": {
- "...": "..."
- }
- "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
- "challenge_feedback": {
- "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
- "state": "server-failure",
- "http_status": "500",
- "error_code": 52
- }
- }
- }
-
- - **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.
-
- .. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SELECTING",
- "recovery_information": {
- "...": "..."
- }
- "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
- "challenge_feedback": {
- "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
- "state": "truth-unknown",
- "error_code": 8108
- }
- }
- }
-
- - **rate-limit-exceeded**:
-
- .. code-block:: json
-
- {
- "recovery_state": "CHALLENGE_SELECTING",
- "recovery_information": {
- "...": "..."
- }
- "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
- "challenge_feedback": {
- "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
- "state": "rate-limit-exceeded",
- "error_code": 8121
- }
- }
- }
-
-**pay:**
-
-With a ``pay`` transition, the application indicates to the reducer that
-a payment may have been made. Here, it is again possible to specify an
-optional ``timeout`` argument for long-polling, for example:
-
-.. code-block:: json
-
- {
- "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
- "timeout" : { "d_ms" : 5000 },
- }
-
-Depending on the type of the challenge and the result of the operation, the
-new state may be ``CHALLENGE_SOLVING`` (if say the SMS was now sent to the
-user), ``CHALLENGE_SELECTING`` (if the answer to the security question was
-correct), ``RECOVERY_FINISHED`` (if this was the last challenge that needed to
-be solved) or still ``CHALLENGE_PAYING`` (if the challenge was not actually
-paid for). For sample messages, see the different types of
-``challenge_feedback`` in the section about ``select_challenge``.
-
-
-**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:
-
-.. code-block:: json
-
- {
- "answer": "answer to security question"
- }
-
-.. code-block:: json
-
- {
- "pin": 1234
- }
-
-.. code-block:: json
-
- {
- "hash": "SOMEBASE32ENCODEDHASHVALUE"
- }
-
-
-.. _anastasis-auth-methods:
-
-----------------------
-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.
-
-
-SMS (sms)
-^^^^^^^^^
-
-Sends an SMS with a code (prefixed with ``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 ``$RESPONSE`` under `Managing truth`_).
-If the transmitted code is correct, the server responses with the requested
-encrypted key share.
-
-
-
-Email verification (email)
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Sends an email with a code (prefixed with ``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 ``$RESPONSE`` under `Managing
-truth`_). If the transmitted code is correct, the server responses with the
-requested encrypted key share.
-
-
-Video identification (vid)
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Requires the user to identify via video-call. In the video-call, the
-user is told the code (prefixed with ``A-``) needed to authenticate.
-
-The user is expected to delete all metadata revealing personal information
-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.
-
-
-
-Security question (qa)
-^^^^^^^^^^^^^^^^^^^^^^
-
-Asks the user a security question. The user sends back a **salted**
-hash over the answer. The **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 **key-salt** for the
-decryption of the (encrypted) **key share**. This ensures that the key share
-remains irrecoverable without the answer even if the Anastasis provider
-storing the security question is malicious.
-
-
-Snail mail verification (post)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Sends physical mail (snail mail) with a code (prefixed with ``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
-``$RESPONSE`` under `Managing truth`_). If the transmitted code is correct,
-the server responds with the requested encrypted key share.
-
-
--------------------
-Anastasis DB Schema
--------------------
-.. image:: anastasis-db.png
-.. image:: anastasis_challengecode.png
-.. image:: anastasis_challenge_payment.png
-.. image:: anastasis_truth.png
-.. image:: anastasis_truth_payment.png
diff --git a/anastasis_challenge_payment.png b/anastasis_challenge_payment.png
deleted file mode 100644
index a0593eba..00000000
--- a/anastasis_challenge_payment.png
+++ /dev/null
Binary files differ
diff --git a/anastasis_challengecode.png b/anastasis_challengecode.png
deleted file mode 100644
index fc30f4fe..00000000
--- a/anastasis_challengecode.png
+++ /dev/null
Binary files differ
diff --git a/anastasis_reducer_backup.drawio b/anastasis_reducer_backup.drawio
deleted file mode 100644
index 953dda74..00000000
--- a/anastasis_reducer_backup.drawio
+++ /dev/null
@@ -1 +0,0 @@
-<mxfile host="app.diagrams.net" modified="2021-07-14T13:53:02.181Z" agent="5.0 (X11)" etag="J63_8AyAsuxkJPDq-ZZb" version="14.8.6" type="device"><diagram id="PpkpfZO7TL7CUlFfbbxv" name="Seite-1">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</diagram></mxfile> \ No newline at end of file
diff --git a/anastasis_reducer_backup.png b/anastasis_reducer_backup.png
deleted file mode 100644
index 53daf7c3..00000000
--- a/anastasis_reducer_backup.png
+++ /dev/null
Binary files differ
diff --git a/anastasis_reducer_backup.svg b/anastasis_reducer_backup.svg
deleted file mode 100644
index 9eccbf4a..00000000
--- a/anastasis_reducer_backup.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1201px" height="378px" viewBox="-0.5 -0.5 1201 378" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2021-07-14T13:53:47.157Z&quot; agent=&quot;5.0 (X11)&quot; etag=&quot;5St_YjOKZ-6nHnOHbqXe&quot; version=&quot;14.8.6&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;PpkpfZO7TL7CUlFfbbxv&quot; name=&quot;Seite-1&quot;&gt;7Z1de6I4FMc/TS/LQxJeL1trp+5MO51qd6ZXPlRpZUvFQWztfPoNCkgSRIQEwelc7CovQU6SX/4nOSc9QZ3X5Rffmk2uvbHtnkB5vDxBFycQQqAY+H/hkY/1EVWW1weefWe8PgQ2B/rOHzs6GF+2cMb2nLgw8Dw3cGbkwZE3ndqjgDhm+b73Tl725LnkU2fWs80c6I8slz360xkHk+go0MzNiSvbeZ5Ejzagvj7xasUXR28yn1hj7z11CHVPUMf3vGD96XXZsd3QeLFd1vddbjmb/DDfngZFbnj6+H1z2ztTB9YTGt7MgeFO5qdRKW+Wu4heuPP9ZtC76d4Mhv3ut24Hf/4S/f7gIzaK7y2mYzssF5yg8/eJE9j9mTUKz77jZoCPTYJXNzqNayawnKnt4+8y/s7+7vhH2H5gL1OHovf4YnuvduB/4Evis+r6jqhNQV2VYHToPVVJKpDM9L+oZiap6lJVKbrRihrKc/K0jS3xh8ice5gWZpj2/mZw99BgwyJgkCZTWmBoxBj6vt+9G54NBne98/tBt38CNRf/jPNHH396Dj8NO9+/NbUONAhJa7agChSmCs7uB1cYIr3O2aD3/SarCroXvUba34wJ3miLq4zFb79/63V63f7wrvtvr/uziaYFCmkyQyMsrZh6Ay2tbbf07dlDE82sq3IhuwKYYUgo6aIsqTOWZExnT8dnoWrD30auNZ87I9Ja9tIJfqU+P4RWC19u/fViGVlx9eUj/jLFv/5X+kv6tvD75r7Vt49ddTH3Fv7I3q2rAst/toPdIsEeEyq0sPCBJlOrcd0TlSpvr9HoWbeeg98xeVDYDpSMPhc9GEFA97e1SaJi0jKUKllBMFdiGApd8tqITMmrJpiYqIJOM5lmObdd7EsMw66Je2b0WKKZ4vr6Zj1iX4donZbrPE/DpovvCTv0edhnHexMnEUnXp3xOCzj3Lfnzh/rcVVe2NJm4dut3lc9P1EvCnEht4/RsEg8pOihJ2knJKupncoSkPVIW/m2awXOG+kTFW9NBnmD9/Q0t4XUpcGPMDJBGL0gYQBJGF0cYWBBwoCGEgYZyZAdQwXJzNjTWqogmWmKi2mLuRL3rMpcwcOuYZC1E7fRipSBoXQh5GVd2GFHkKMVNkWxgz6xcxDssBN6CXQW01jEtwM5ca/igBygGWSlx+24InJOAZJ0M7Nk8dQB7BBztGoHFcROU/2pY8cOZJriozV6aRFsks7Ew3GSDYiIGuEjcE41yawNLuxAsj9cysqTUmJIPFyUhsLFUOWcFYMqoDFMg8LWAdjCru+sMDFczPF/rCDwncdFYM/bBJttU7olpM2GNW2iCzteHK10UQrSpake05HThV26bJtyifsSlylfqAqZm8H6SopNXQNe2CGjNF7qmZDZLBnWAxv1EzZ7wAY3FOsjdVnUd7e+BQAq/Sgz7Fq5P5C5SQFK7g2Jz1LyejWSIZvOt35PvnxlF32n9rJNM98JTDiINQQRFVzCha5QRpJKFlzjNBQ7gpaGbT1ajhds1YKw/fQbRcI2WWqLsYbMfAxS1yNd38FloFe8AWiSoRP0FwRbdv27bWI2hgkXMavrkIQip4VGpEkKyiy5BtxyjKJK6dmHNGF3aNsUYR/SJ7fgdrTw35JouPK0LSptm0pbUyGjHSvEUJkmIqOzyFdIBazyFrayjDLNJRZrbLCrNR4PrUUwwa0IAypwvGmbIMczSAvJkKz+RLBWpByQDKoRCYQaz8CtjW58SJ3aCTVIQA18Qq0Q1HRlt9ArijUgY0Fam49Oo4ySdYJQxkaTj23XDuwW04xbaFhIM2BSgRqxIqw8ASmZZH0rklGbjwx5hmpIEJt8A7hwvRmPKHmUI2AVnrm1fQe/0+6kg6I+cOPAdArjmIRktkst7c4CmJsWp5iahMLM1vifGGKZlLdODvuKWsdsHhvpGCqxmec6ozaFlkGe0R7ABLQzqPFhFpTikmpAFI+AjzZKsKKzeE0lnYbhQzxKQ1SjKYw5Be4qqhaUqWYNTqXCDsmREmsfzbiFk4QKTKdmL+M43Kow06U4ID8RYPFwUgPd2BXhfrdz1x00Ng0ZK2FKZBw4OVb7x3d/P8HJw9h4fri2b16GL72M/SPOzzpf72+Hl72bXv+qe9E4u9Lp3Qe36/Wb++t3P/g6+XE2+PnVWHo/3rUMu1YYjFs0yQsLDsawoYMx0sjFJahozFxs8ShvbWdZnMZjRKGZ2kum8gic2cYh08bbkR+X22H/xindTIOISvYviK992FUBVxmh43nj5E5eFQRSxXagQpJSmkKBriiiVJ1aezepgjjxKdk1LB60NTn3d5n514vhGbuGcahIp4LM4rYMJUvA0MjBqupSu3hA8Uja3RLuWTqYvGUcMSi1o5aVOmU5wqstZKRSzqyDTAEU7LrccmNDuWEAqu9CLq2jhrzY7Mrk6DyR0d+iEtBg0dyPtskDYwcfRHdr1sVo+JDMMzMMGAokzM+nW5/StEC1dWyOaR3UrEjhJQr9EEsUGqsO8q47OozU5GXoZvZzhHoNGeHzzZYe/PIhVqsNKikT4sWH5voNgI1G5CQvmrfbT9G10aMVMIf2S9hwsaYLmLh38MiWMpXspKaqCgZR8RpIipViDfjguFlY01Pfs6ZHK8VWfOJjvxUWdlrjUPlARfHBcdMvZl6DU/aPiJCs4XvPgqP+6N+X3tX86vrnP88aytjYPt5Gfey8xfuoD+7uB1ebrajX5/HjUpcw9X3oNXhmXiCerid2p95zQbboenumqbnupdYg17IhRNVkciBX6YosSlRNQ/kFcXIFNSr6hrcrmN0I2YnLxriC+b3m+F3B7PeH/KjBfaY5b0hp2UySTi3nqpCacyyKD/ovI+CCJECVxU+TZbcZdlRveCePG/lfvtaUbRzWQa9HN5ApPVtmhsq7di1biNZoQVlWX+hUzJ0ofaFTm1Boah36go3Jajh64t7VSH2RBGpLGjVNhQxJUwQgyPnxYn9ZvLhvl93Ff9dg+d/ldz3TS9xOoKk3tXdPJpVhDzGttMt7wb/o0gnfc/VtjntVQDFyMHGm8ano0o2nQ2EnA2FbWwKkQoGRlhX+zScamAo7Lk0loO1wn3il5QAKSkloPC8uZbbgrA2kmHmOse0ORxPLde0prvti8xwHCxcuDCyy5W7v33lgE5Z/CMmg8FM6GUwc03iqqrRfVRVruyKJN1gDNNYi8KZ5Ju/BM96JjFsbFKL4qAjLWzSw66UyCTYx4oAmIVnb7HJTkpyKyRYrKImCoqcC+Eq6zI7CKrrFbGw1MImRJxG1gxGR2tVfRORT5hvzCGnc4jFKRhpwq80kTO6UW91PbzqR8nt1mKL05jdsnzXfuodFBWXI5G4hVVJFSUP8MAkpKMEblRobJiUqqrptR4nCKWSKLBF/Emuvp3DiokInY6AawJg5NcuIyhXuhnN75If99u/RlCC/Jwjd1AKQw6SIFPDsd+Y6VXegDS6q4A1CSU79gyTshKXE0mmsasafGC7Ks5Ca298hq2R+CbJ5D+a8YUV2+2W13si1rQ2+jhJUO7WesP0q6N3Va+MUh70Qt2k904DkCkHYkmsWezLmASn2EMznZwWxxzNIDebPxCAq2AsrK4HyUQ/lo8JsOZYE1KyVXTnKKmqeaswum5dWpHpdbFSxZGVDMtPCcDi1Xu0jxauxC6/idCC5hx69oi+Or3tudJazYCLJShplYCfJtmJZJ2QhLre4C77n+slWOLeBsPTUpMClG2qZSNXKLt3oGrGPkK7nlyvI545DmIVyNO5I7GykvZw5fsM2tuXJ0R2ul9BFGjqXAdYG0qx1u5IO9T7Rb6XzoEr500WD5Q4V+qLo5HyKCkgXmSqwdOo2EAMqjcq14L1TS3bLZVP4DptWxZVFSi6LBOaFk0Mm4LDVFP7qe16Qvty3ZpNrbxzWSfd/&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="52" y="35.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 63px; margin-left: 53px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">CONTINENT_SELECTING</div></div></div></foreignObject><text x="128" y="67" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">CONTINENT_SELECTING</text></switch></g><rect x="356" y="35.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 63px; margin-left: 357px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">COUNTRY_SELECTING</div></div></div></foreignObject><text x="432" y="67" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">COUNTRY_SELECTING</text></switch></g><rect x="660" y="35.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 63px; margin-left: 661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">USER_ATTRIBUTES<br />_COLLECTING</div></div></div></foreignObject><text x="736" y="67" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">USER_ATTRIBUTES...</text></switch></g><rect x="964" y="35.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 63px; margin-left: 965px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">AUTHENTICATIONS<br />_EDITING</div></div></div></foreignObject><text x="1040" y="67" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">AUTHENTICATIONS...</text></switch></g><rect x="52" y="257.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 285px; margin-left: 53px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">POLICIES_REVIEWING</div></div></div></foreignObject><text x="128" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">POLICIES_REVIEWING</text></switch></g><rect x="787" y="257.25" width="112" height="52.75" rx="7.91" ry="7.91" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 110px; height: 1px; padding-top: 284px; margin-left: 788px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">POLICIES_PAYING</div></div></div></foreignObject><text x="843" y="287" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">POLICIES_PAYING</text></switch></g><path d="M 204 49.13 L 349.63 49.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 354.88 49.13 L 347.88 52.63 L 349.63 49.13 L 347.88 45.63 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 49px; margin-left: 280px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_continent</div></div></div></foreignObject><text x="280" y="53" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_continent</text></switch></g><path d="M 356 76.88 L 210.37 76.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 205.12 76.88 L 212.12 73.38 L 210.37 76.88 L 212.12 80.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 281px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">unselect_continent</div></div></div></foreignObject><text x="281" y="80" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">unselect_continent</text></switch></g><path d="M 508 49.13 L 653.63 49.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 658.88 49.13 L 651.88 52.63 L 653.63 49.13 L 651.88 45.63 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 49px; margin-left: 584px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_country</div></div></div></foreignObject><text x="584" y="53" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_country</text></switch></g><path d="M 660 76.88 L 514.37 76.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 509.12 76.88 L 516.12 73.38 L 514.37 76.88 L 516.12 80.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 78px; margin-left: 584px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="584" y="82" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 812 49.13 L 957.63 49.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 962.88 49.13 L 955.88 52.63 L 957.63 49.13 L 955.88 45.63 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 49px; margin-left: 888px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">enter_user_attributes</div></div></div></foreignObject><text x="888" y="53" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">enter_user_attributes</text></switch></g><path d="M 964 76.88 L 818.37 76.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 813.12 76.88 L 820.12 73.38 L 818.37 76.88 L 820.12 80.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 888px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="888" y="80" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 1116 49.13 L 1192 49.13 L 1192 174 L 27 174 L 27 271 L 45.63 271.09" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 50.88 271.12 L 43.86 274.58 L 45.63 271.09 L 43.9 267.58 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 174px; margin-left: 612px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="612" y="178" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g><path d="M 52 298.88 L 7 299 L 7 137 L 1154 137 L 1154 76.88 L 1122.37 76.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1117.12 76.88 L 1124.12 73.38 L 1122.37 76.88 L 1124.12 80.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 137px; margin-left: 634px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="634" y="141" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 1002 35.25 Q 1040 -11 1073.96 30.33" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1077.29 34.39 L 1070.14 31.2 L 1073.96 30.33 L 1075.55 26.76 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 11px; margin-left: 1041px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">add_authentication</div></div></div></foreignObject><text x="1041" y="15" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">add_authentication</text></switch></g><path d="M 1078 90.75 Q 1040 137 1006.04 95.67" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1002.71 91.61 L 1009.86 94.8 L 1006.04 95.67 L 1004.45 99.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 118px; margin-left: 1040px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">delete_authentication</div></div></div></foreignObject><text x="1040" y="122" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">delete_authentication</text></switch></g><path d="M 85.14 256.31 Q 128 211 161.91 251.45" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 165.28 255.47 L 158.1 252.35 L 161.91 251.45 L 163.47 247.86 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 232px; margin-left: 129px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">add_policy</div></div></div></foreignObject><text x="129" y="235" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">add_policy</text></switch></g><path d="M 166 312.75 Q 128 359 94.04 317.67" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 90.71 313.61 L 97.86 316.8 L 94.04 317.67 L 92.45 321.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 341px; margin-left: 127px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">delete_policy</div></div></div></foreignObject><text x="127" y="344" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">delete_policy</text></switch></g><rect x="356" y="257.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 285px; margin-left: 357px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">SECRET_EDITING</div></div></div></foreignObject><text x="432" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">SECRET_EDITING</text></switch></g><rect x="964" y="257.25" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 285px; margin-left: 965px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">BACKUP_FINISHED</div></div></div></foreignObject><text x="1040" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">BACKUP_FINISHED</text></switch></g><path d="M 394 35.25 Q 435 -20 466.59 29.87" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 469.4 34.31 L 462.7 30.27 L 466.59 29.87 L 468.61 26.52 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 6px; margin-left: 435px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_continent</div></div></div></foreignObject><text x="435" y="9" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_continent</text></switch></g><path d="M 508 257.25 L 530.86 227.89 Q 537 220 547 220 L 927 220 Q 937 220 942.87 228.1 L 960.26 252.09" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 963.34 256.34 L 956.4 252.73 L 960.26 252.09 L 962.07 248.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 221px; margin-left: 783px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="783" y="225" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g><path d="M 897 285 L 957.63 285" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 962.88 285 L 955.88 288.5 L 957.63 285 L 955.88 281.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 927px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="927" y="289" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 508 285 L 610.63 285" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 615.88 285 L 608.88 288.5 L 610.63 285 L 608.88 281.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 280px; margin-left: 557px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="557" y="284" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g><path d="M 815 310 Q 827 350 866.29 314.28" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 870.17 310.75 L 867.35 318.05 L 866.29 314.28 L 862.64 312.87 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 336px; margin-left: 841px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="841" y="339" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 204 271.13 L 349.63 271.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 354.88 271.13 L 347.88 274.63 L 349.63 271.13 L 347.88 267.63 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 270px; margin-left: 278px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="278" y="274" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g><path d="M 356 298.88 L 210.37 298.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 205.12 298.88 L 212.12 295.38 L 210.37 298.88 L 212.12 302.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 300px; margin-left: 278px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="278" y="304" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><rect x="617" y="260" width="110" height="50" rx="7.5" ry="7.5" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 285px; margin-left: 618px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><div>TRUTHS_PAYING</div></div></div></div></foreignObject><text x="672" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">TRUTHS_PAYING</text></switch></g><path d="M 644 310 Q 656 350 695.29 314.28" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 699.17 310.75 L 696.35 318.05 L 695.29 314.28 L 691.64 312.87 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 336px; margin-left: 670px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="670" y="339" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 727 285 L 780.63 284.36" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 785.88 284.3 L 778.92 287.88 L 780.63 284.36 L 778.84 280.89 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 755px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="755" y="288" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 717 310 Q 767 410 958.45 302" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 963.03 299.42 L 958.65 305.91 L 958.45 302 L 955.21 299.82 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 358px; margin-left: 811px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="811" y="362" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 55.68 315.2 Q 128 417.25 204 310" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 52.65 310.91 L 58.6 315.27 L 55.68 315.2 L 54.79 317.97 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 370px; margin-left: 129px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "><div>del_challenge</div></div></div></div></foreignObject><text x="129" y="374" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">del_challenge</text></switch></g><path d="M 52 257.25 Q 128 170 199.82 252.45" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 203.27 256.41 L 196.03 253.43 L 199.82 252.45 L 201.31 248.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 210px; margin-left: 129px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">update_policy</div></div></div></foreignObject><text x="129" y="214" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">update_policy</text></switch></g><path d="M 397.34 257.25 Q 437 190 474.31 251.79" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 477.02 256.29 L 470.41 252.1 L 474.31 251.79 L 476.4 248.49 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 220px; margin-left: 433px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "><div>enter_secret</div></div></div></div></foreignObject><text x="433" y="223" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">enter_secret</text></switch></g><path d="M 473 312.75 Q 435 359 401.04 317.67" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 397.71 313.61 L 404.86 316.8 L 401.04 317.67 L 399.45 321.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 341px; margin-left: 432px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">clear_secret</div></div></div></foreignObject><text x="432" y="344" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">clear_secret</text></switch></g><path d="M 361.47 255.47 Q 447 130 502.61 251.57" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 504.8 256.34 L 498.7 251.43 L 502.61 251.57 L 505.07 248.52 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 190px; margin-left: 437px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">enter_secret_name</div></div></div></foreignObject><text x="437" y="194" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">enter_secret_name</text></switch></g><path d="M 367.16 319.34 Q 437 400 503.44 315.47" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 363.72 315.37 L 370.07 319.14 L 367.16 319.34 L 366.54 322.19 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 361px; margin-left: 432px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">update_expiration</div></div></div></foreignObject><text x="432" y="364" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">update_expiration</text></switch></g><path d="M 508 270 Q 657 220 781.06 268.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 785.96 270.03 L 778.17 270.76 L 781.06 268.13 L 780.7 264.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 240px; margin-left: 660px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="660" y="244" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg> \ No newline at end of file
diff --git a/anastasis_reducer_recovery.drawio b/anastasis_reducer_recovery.drawio
deleted file mode 100644
index ac1f617b..00000000
--- a/anastasis_reducer_recovery.drawio
+++ /dev/null
@@ -1 +0,0 @@
-<mxfile host="app.diagrams.net" modified="2021-07-14T14:05:15.539Z" agent="5.0 (X11)" etag="RgsPOgrkZ7CacnVb-4wQ" version="14.8.6" type="device"><diagram id="PpkpfZO7TL7CUlFfbbxv" name="Seite-1">7Vxbd6o4FP41PupKwv2xWnuZ6Win2k49Ly6qVDlF8SC29fz6CTUISQBRgmLX6UOXBEhgZ+8v376EmtSafV575mL6jzu2nBoC48+adFlDSIcQ/w8a1psGGcqbholnjzdNMGro2b8t0ghI68oeW0vqQt91Hd9e0I0jdz63Rj7VZnqe+0Ff9uo69KgLc2JxDb2R6fCt/9ljf0paoWpEJ24sezIlQ+tI25yYmeHF5E2WU3PsfsSapHZNanmu629+zT5blhPILpTL5r6rlLPbB/OsuZ/nhtf1r8797YXSN1+lYWcJdWe6rJNe3k1nRV641e30bzvtTn/Ya9+1W/j3NXl+fx0KxXNX87EV9AtrUvNjavtWb2GOgrMfWAtw29SfOeQ0nhnftOeWh48BPuafO3wIy/Otz1gTeY9ry51ZvrfGl5CzEiJKRJQKaaSLj9gUKbBhxP/IvExjk6UoDYWoClGTyXasSJL4BxHmHoJFCYJ97PQfBhUWq4r0qotV4sT62Gs/DC/6/Yfb5mO/3ash1cGP0Xzx8K9J8GvY6t5VVeKGxEiz6vKXebW+ucDi7Vy3K6zYMgCUYGUVnFCw/y6azvDp7g387N74y8HrXxd1tw6lDKkFYnA9f+pO3Lnp3Lnugsjqp+X7a7JomivfpSVpfdr+c+z3IOgKv8Hm6PKT9Px1sA4P5vhtnuMHm7uQEh5H930drXdN09JdeSMrQ6eISH3Tm1jkVqPXb7aMq7eX1tvC/3vdf5t9oK2IrDG1ZPOz7lmO6dvv9Aou3BSUDFO4vxhU0Q5UhbGDkIxVB2A0TqqcFK35+CJgdvho5JjLpT3Ko/aocnof0tmY3mdRiZ1qn0aOkNzQFG6eQ1Wg5hWkzyoZ79618XtuB1NUGKoCGU6CWiA0qp+NKMitcYrK9KbJiH50HXB9bcTF9fWlbFthFOBtBqeAS8vBnsUwsEdsjmRYSiHxzNyZL9jxofTQdOzJPFBSfE9gxc3AUG3sWlyQEzN7PA76aHrW0v5tvnz1F+jUIni7r/dVmjXlMhcYZFoTixBbf4kMWou7JElKVQcNCDQCwLnxNXmWdfoG9/V1aZUyl7o4LAEUlmg5sQTSWKKVhyUoJ5bACmOJasgsliCVXWjOCEokwOnfan7GYBKaU2EwwTOh67RihYpZEFoQwuoZJy9Hwxp+2fi2vCUv1uSl63+wRgDW8IG8LdKs5iExPw+cCU1JAM5AVadnOVTegjiDfdGGZiT2XD7UQH5d+ba8RsqJNVX2kb4d1iBO/17M0dsZIczWgkT4RUBHEjUlYqhMXW0YR0MUfvU4DnuhQ5yFYSKv+UONMaIyzR8CoGUE+QtgAZSZcJ4m5wICPI/mOnYZsav0N4AqPRAiq2rqg7E3SDrIvgEVuz5888guNu8oFvf45NMXhA1XS/zP9H3Pfln51vKcgDAthHwA14pwsGh8CFJzW2c6KBEG+YVtfxg8lCPlhELRXtdxoZABLAUwpDk38oEoBbE/Edob/0DyY6c/HYNmipp5PZI05nolnIN0hJX2G4O/gaTTyoVMPl98blQxxAQhIXSklBP2YhSoDht6Gaj5Y/C47g6vfO/p+XlwO3j/uPedhDzo/qApMvJVnjMq54RgpSAE68oWyUpI2NGqoiCmi7wQrEK6I1ljOhLnhSZWA/BkLAx4TU3HseZY9idAGV65Mm3mcFA5FDGE4kFymYY4PIhhwCAOATvwIEa2BvGTKYAwWnnv26KMw9EB5UQHtB865Kl1FBSnUlgqqB6eyWdLCRP6EsTONMAICFK+Y2Fik6jkvKdwHom9TIsVQXEkgJi4OBTjFWJKw+iPEAhLLMZTEyevRw6jSrx21NoUVq0XC8MXAD24A/Ry4VyitohmQcKr9bKeOrlwtXv3dA7lekrowp2kXC9RrCLIf6TCaK91O1XCOytJ5ZyqmXOJLYhsqk6vlRyTzr3o8uWdJeaGEiWrcvqwME+Se8659BUn4lFNixomxkIiUkw7tusn2AbkyifvpZXf5k0tH6+MJWEdOwOw0NitDCzPPxgsQD7/PZ2ei9ZFvnyzmh5+piEJ4dRILYgl4T4YtSHTuepSkiuJAhFYIEcXrRxSs3J6dvwHVU6EKgnVU6dKSeSEEoH1cADKTKZADLCgBiyj0jZ5AkUEGJOztDtQIRl/dqQpDicoCfvizgBKFJ11Qr4vlPBRwIpDibh6jyCbqbO1iEIUqB5uSgwhSmqE9OcI4MKnlR7are5T+2EwvLrt3PZu2pfc/J46TmQY7PZmo8HnD08cKYJ8BG5/2Ba4oVmIY5mXAhbbz3ykMBRbTXgoB1RZdcwJ3MJsmA9KLl3n3ToLv3FrJkIcRwjo0KKYchMm8380FxLy0cX9ISSKNu+VL9mdAKLSyFEyJ57LgZlIJRRxzoApsgRPMdTjAs7emWakUuOo7BeX2HCLlnl9OZlpyIdwzwj9QgsXU49MFxILcnUNmkUZTECtDKqamKQ+k3kW5nFoaiB5DaiypiNJZgpMFIBnHEiKquiSoSAJpc9rse/08DS2MhkuYaLW2e0VKkgXZ1pEkTaLMjJYXfQDr23PZnd2cV+fvRi/ph0vofys1249tEv+nF2CzLmZSRU3t4/npJ+nSpQqH+ngVb6snRGJpGUf+eJlhQ4pyBA2ZJmTsZgyOu5jY+GGr31pDTIQhrToD7HdYn6vbM8yC5k4HytRH/gwSbXq+nNjIK1H6bqf5WaJ3gFaPkiWFovJFQwvYMocVEKjoWslWTI2QHowLWAgqSaX1645gNBLi48kTj4fHplbnxWqVxVpu/Iu2xX2VSs2zVGe8YqIgpy6wH43BNBhjyyqFw97pF+XwQ6Y/TfbwKf4/Y8MKz44xIopYnZHgiIeCDLjALERjMTp4h1b7NJif3aIgWFpu/PviVTqLqSqeGU9Poy+Zb65PPogvNT+Hw==</diagram></mxfile> \ No newline at end of file
diff --git a/anastasis_reducer_recovery.png b/anastasis_reducer_recovery.png
deleted file mode 100644
index b08c7638..00000000
--- a/anastasis_reducer_recovery.png
+++ /dev/null
Binary files differ
diff --git a/anastasis_reducer_recovery.svg b/anastasis_reducer_recovery.svg
deleted file mode 100644
index 70204989..00000000
--- a/anastasis_reducer_recovery.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1076px" height="398px" viewBox="-0.5 -0.5 1076 398" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2021-07-14T14:05:44.086Z&quot; agent=&quot;5.0 (X11)&quot; etag=&quot;heBcjQYLP05MJ4nWahSj&quot; version=&quot;14.8.6&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;PpkpfZO7TL7CUlFfbbxv&quot; name=&quot;Seite-1&quot;&gt;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&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="231" y="42" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 70px; margin-left: 232px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">CONTINENT_SELECTING</div></div></div></foreignObject><text x="307" y="73" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">CONTINENT_SELECTING</text></switch></g><rect x="535" y="42" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 70px; margin-left: 536px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">COUNTRY_SELECTING</div></div></div></foreignObject><text x="611" y="73" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">COUNTRY_SELECTING</text></switch></g><rect x="839" y="42" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 70px; margin-left: 840px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">USER_ATTRIBUTES<br />_COLLECTING</div></div></div></foreignObject><text x="915" y="73" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">USER_ATTRIBUTES...</text></switch></g><rect x="307" y="231" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 259px; margin-left: 308px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">CHALLENGE_SELECTING</div></div></div></foreignObject><text x="383" y="262" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">CHALLENGE_SELECTING</text></switch></g><path d="M 709 212.75 L 890.78 253" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 895.91 254.13 L 888.32 256.04 L 890.78 253 L 889.83 249.2 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="557" y="185" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 213px; margin-left: 558px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">CHALLENGE_PAYING</div></div></div></foreignObject><text x="633" y="216" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">CHALLENGE_PAYING</text></switch></g><path d="M 383 55.88 L 528.63 55.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 533.88 55.88 L 526.88 59.38 L 528.63 55.88 L 526.88 52.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 56px; margin-left: 459px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_continent</div></div></div></foreignObject><text x="459" y="59" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_continent</text></switch></g><path d="M 535 83.63 L 389.37 83.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 384.12 83.63 L 391.12 80.13 L 389.37 83.63 L 391.12 87.13 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 83px; margin-left: 460px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">unselect_continent</div></div></div></foreignObject><text x="460" y="86" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">unselect_continent</text></switch></g><path d="M 687 55.88 L 832.63 55.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 837.88 55.88 L 830.88 59.38 L 832.63 55.88 L 830.88 52.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 56px; margin-left: 762px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_country</div></div></div></foreignObject><text x="762" y="59" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_country</text></switch></g><path d="M 839 83.63 L 693.37 83.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 688.12 83.63 L 695.12 80.13 L 693.37 83.63 L 695.12 87.13 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 85px; margin-left: 763px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="763" y="88" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 991 55.88 L 1067 56 L 1067 151 L 27 151 L 27 245 L 40.63 245" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 45.88 245 L 38.88 248.5 L 40.63 245 L 38.88 241.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 150px; margin-left: 602px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">enter_user_attributes</div></div></div></foreignObject><text x="602" y="154" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">enter_user_attributes</text></switch></g><path d="M 47 273 L 7 273 L 7 127 L 144 126.75 L 1037 127 L 1037 84 L 997.37 83.68" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 992.12 83.63 L 999.15 80.19 L 997.37 83.68 L 999.09 87.19 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 126px; margin-left: 629px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="629" y="130" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 459 244.88 L 550.95 214.73" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 555.94 213.1 L 550.38 218.6 L 550.95 214.73 L 548.2 211.95 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 229px; margin-left: 508px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_challenge</div></div></div></foreignObject><text x="508" y="232" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_challenge</text></switch></g><path d="M 573 42 Q 611 -19 645.63 36.59" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 648.41 41.05 L 641.74 36.96 L 645.63 36.59 L 647.68 33.26 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 6px; margin-left: 613px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_continent</div></div></div></foreignObject><text x="613" y="10" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_continent</text></switch></g><path d="M 671 301 L 671 246.87" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 671 241.62 L 674.5 248.62 L 671 246.87 L 667.5 248.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="557" y="301" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 329px; margin-left: 558px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">CHALLENGE_SOLVING</div></div></div></foreignObject><text x="633" y="332" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">CHALLENGE_SOLVING</text></switch></g><path d="M 595 241 L 595 294.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 595 299.88 L 591.5 292.88 L 595 294.63 L 598.5 292.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 268px; margin-left: 597px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="597" y="272" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><path d="M 459 272.63 L 551.15 312.35" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 555.97 314.43 L 548.16 314.88 L 551.15 312.35 L 550.93 308.45 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 286px; margin-left: 539px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">select_challenge</div></div></div></foreignObject><text x="539" y="289" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">select_challenge</text></switch></g><path d="M 557 328.75 L 464.85 289.02" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 460.03 286.94 L 467.84 286.5 L 464.85 289.02 L 465.07 292.93 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 306px; margin-left: 510px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="510" y="309" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 557 198.88 L 465.05 229.02" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 460.06 230.65 L 465.62 225.15 L 465.05 229.02 L 467.8 231.8 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 211px; margin-left: 504px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="504" y="214" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><rect x="897" y="240.5" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 268px; margin-left: 898px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">RECOVERY_FINISHED</div></div></div></foreignObject><text x="973" y="272" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">RECOVERY_FINISHED</text></switch></g><path d="M 709 328.75 L 890.94 270.2" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 895.94 268.59 L 890.34 274.07 L 890.94 270.2 L 888.2 267.41 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 308px; margin-left: 791px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">solve_challenge</div></div></div></foreignObject><text x="791" y="312" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">solve_challenge</text></switch></g><path d="M 633 356.5 Q 633.03 391 508.03 391 Q 383.03 391 383 292.87" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 383 287.62 L 386.5 294.62 L 383 292.87 L 379.5 294.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 391px; margin-left: 488px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">solve_challenge</div></div></div></foreignObject><text x="488" y="395" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">solve_challenge</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 271px; margin-left: 677px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">solve_challenge</div></div></div></foreignObject><text x="677" y="275" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">solve_challenge</text></switch></g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 226px; margin-left: 797px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">pay</div></div></div></foreignObject><text x="797" y="230" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">pay</text></switch></g><rect x="47" y="231" width="152" height="55.5" rx="8.32" ry="8.32" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 150px; height: 1px; padding-top: 259px; margin-left: 48px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">SECRET_SELECTING</div></div></div></foreignObject><text x="123" y="262" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">SECRET_SELECTING</text></switch></g><path d="M 307 270 L 205.37 270.3" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 200.12 270.31 L 207.11 266.79 L 205.37 270.3 L 207.13 273.79 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 271px; margin-left: 258px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">back</div></div></div></foreignObject><text x="258" y="275" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">back</text></switch></g><path d="M 199 251 L 300.63 251" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 305.88 251 L 298.88 254.5 L 300.63 251 L 298.88 247.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 251px; margin-left: 257px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">next</div></div></div></foreignObject><text x="257" y="255" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">next</text></switch></g><path d="M 85 231 Q 123 171 157.59 225.62" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 160.4 230.06 L 153.7 226.01 L 157.59 225.62 L 159.61 222.27 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 196px; margin-left: 125px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">change_version</div></div></div></foreignObject><text x="125" y="200" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">change_version</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg> \ No newline at end of file
diff --git a/anastasis_truth.png b/anastasis_truth.png
deleted file mode 100644
index 7f23fa21..00000000
--- a/anastasis_truth.png
+++ /dev/null
Binary files differ
diff --git a/anastasis_truth_payment.png b/anastasis_truth_payment.png
deleted file mode 100644
index 70a6b3df..00000000
--- a/anastasis_truth_payment.png
+++ /dev/null
Binary files differ
diff --git a/conf.py b/conf.py
index 9b8e2e9b..08e94199 100644
--- a/conf.py
+++ b/conf.py
@@ -232,8 +232,6 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- ('anastasis', 'anastasis.tex',
- 'Anastasis Manual', 'Anastasis team', 'manual'),
('taler-auditor-manual', 'taler-auditor-manual.tex',
'GNU Taler Auditor Manual', 'GNU Taler team', 'manual'),
('taler-exchange-manual', 'taler-exchange-manual.tex',
@@ -354,8 +352,6 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ("anastasis", "anastasis", "Anastasis Manual",
- "Anastasis team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
("taler-auditor-manual", "taler-auditor", "Taler Auditor Manual",
"GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"),
("taler-exchange-manual", "taler-exchange", "Taler Exchange Manual",
diff --git a/core/api-auditor.rst b/core/api-auditor.rst
index 11294d0a..cd0071e5 100644
--- a/core/api-auditor.rst
+++ b/core/api-auditor.rst
@@ -3,14 +3,14 @@
Copyright (C) 2018 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/core/api-bank-access.rst b/core/api-bank-access.rst
index fa08c2f4..ddb2ec80 100644
--- a/core/api-bank-access.rst
+++ b/core/api-bank-access.rst
@@ -4,14 +4,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Florian Dold
diff --git a/core/api-bank-integration.rst b/core/api-bank-integration.rst
index 2864fbfd..298e3d75 100644
--- a/core/api-bank-integration.rst
+++ b/core/api-bank-integration.rst
@@ -4,14 +4,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Marcello Stanisci
diff --git a/core/api-bank-merchant.rst b/core/api-bank-merchant.rst
index 790d3f74..2c8f1934 100644
--- a/core/api-bank-merchant.rst
+++ b/core/api-bank-merchant.rst
@@ -3,14 +3,14 @@
Copyright (C) 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
============================
diff --git a/core/api-common.rst b/core/api-common.rst
index 9c23b905..7ee4769f 100644
--- a/core/api-common.rst
+++ b/core/api-common.rst
@@ -1,13 +1,16 @@
..
This file is part of GNU TALER.
Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
+
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/core/api-error.rst b/core/api-error.rst
index 8f87481c..fcd7374b 100644
--- a/core/api-error.rst
+++ b/core/api-error.rst
@@ -2,12 +2,12 @@
This file is part of GNU TALER.
Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Marcello Stanisci
diff --git a/core/api-exchange.rst b/core/api-exchange.rst
index ce482837..fe41cbed 100644
--- a/core/api-exchange.rst
+++ b/core/api-exchange.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
index d8e3c910..b4513704 100644
--- a/core/api-merchant.rst
+++ b/core/api-merchant.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Marcello Stanisci
diff --git a/core/api-sync.rst b/core/api-sync.rst
index f72c3856..a6d65726 100644
--- a/core/api-sync.rst
+++ b/core/api-sync.rst
@@ -3,14 +3,14 @@
Copyright (C) 2018, 2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/core/api-wire.rst b/core/api-wire.rst
index 654d72f3..c471cbf8 100644
--- a/core/api-wire.rst
+++ b/core/api-wire.rst
@@ -3,14 +3,14 @@
Copyright (C) 2019-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
===========================
diff --git a/core/index.rst b/core/index.rst
index 7ead2193..6dd762fd 100644
--- a/core/index.rst
+++ b/core/index.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Florian Dold
diff --git a/design-documents/006-anastasis-ux.rst b/design-documents/006-anastasis-ux.rst
deleted file mode 100644
index 17839bdb..00000000
--- a/design-documents/006-anastasis-ux.rst
+++ /dev/null
@@ -1,318 +0,0 @@
-Design Doc 006: Anastasis User Experience
-#########################################
-
-Summary
-=======
-
-This document describes the recommended way of implementing the user experience
-of setting up and making use of :doc:`../anastasis` account recovery.
-
-Motivation
-==========
-
-Wallet state consisting of digital cash, transaction history etc. should not be lost.
-Taler provides a backup mechanism to prevent that.
-As an additional protection measure Anastasis can be used to provide access to the backup,
-even if all devices and offline secrets have been lost.
-
-Access to the backup key is shared with escrow providers that can be chosen by the user.
-
-Setup Steps
-===========
-
-.. graphviz::
-
- digraph G {
- rankdir=LR;
- nodesep=0.5;
- settings [
- label = "Backup\nSettings";
- shape = oval;
- ];
- backup_is_setup [
- label = "Backup\nsetup?";
- shape = diamond;
- ];
- provide_id [
- label = "Provide\nIdentification";
- shape = rectangle;
- ];
- select_auth [
- label = "Select\nAuthentication Methods";
- shape = rectangle;
- ];
- provide_auth [
- label = "Provide\nAuthentication Data";
- shape = rectangle;
- ];
- select_providers [
- label = "Select\nService Providers";
- shape = rectangle;
- ];
- review_policy [
- label = "Review Recovery Policy";
- shape = rectangle;
- ];
- edit_policy [
- label = "Edit Recovery Policy";
- shape = rectangle;
- ];
- pay [
- label = "Confirm Payment";
- shape = oval;
- ];
- settings -> backup_is_setup;
- backup_is_setup -> provide_id [label="Yes: Setup Recovery"];
- backup_is_setup -> settings [label="No"];
- provide_id -> select_auth;
- select_auth -> provide_auth;
- provide_auth -> select_auth;
- select_auth -> select_providers;
- select_providers -> select_auth;
- select_providers -> review_policy;
- review_policy -> edit_policy;
- edit_policy -> review_policy;
- review_policy -> pay;
- }
-
-Entry point: Settings
----------------------
-
-The app settings should have a section for Anastasis using a different more
-universally understood name like Wallet Recovery.
-
-The section should have an option to setup Anastasis initially. This option
-should be disabled as long as no backup has been set up. The section could
-maybe be integrated into the backup settings.
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/menu.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/settings.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/backupsettings.png
- :width: 800
-
-Providing Identification
-------------------------
-
-Instead of a forgettable freely chosen user name, Anastasis collects various
-static information from the user to generate a unique user identifier from
-that. Examples for such identifier would be a concatenation of the full name
-of the user and their social security or passport number(s).
-
-The information that can reasonably used here various from cultural context
-and jurisdiction. Therefore, one idea is to start by asking for continent and
-then the country of primary legal residence, and then continue from there with
-country-specific attributes (and also offer a stateless person option).
-
-Special care should be taken to avoid that information can later be provided
-ambiguously thus changing the user identifier and not being able to restore
-the user's data. This can be typographic issues like someone providing
-"Seestr." and later "Seestrasse" or "Seestraße" or "seestrasse". But it can
-also be simple typos that we can only prevent in some instances like when
-checking checksums in passport numbers.
-
-The user should be made aware that this data will not leave the app and that
-it is only used to compute a unique identifier that can not be forgotten.
-
-If possible, we should guide the user in the country selection by accessing
-permission-less information such as the currently set language/locale and the
-country of the SIM card. But nothing invasive like the actual GPS location.
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/userid.png
- :width: 800
-
-Add Authentication Methods
---------------------------
-
-After creating a unique identifier, the user can chose one or more
-:ref:`anastasis-auth-methods` supported by Anastasis.
-
-When selecting a method, the user is already asked to provide the information
-required for the recovery with that method. For example, a photo of
-themselves, their phone number or mailing address.
-
-The user interface validates that the inputs are well-formed, and refuses
-inputs that are clearly invalid. Where possible, it pre-fills the fields with
-sane values (phone number, e-mail addresses, country of residence).
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/truth.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addtruth.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addtruthmail.png
- :width: 800
-
-
-Confirm/Change Service Providers
---------------------------------
-
-From the dialog where the user is adding authentication methods, the user can
-optionally jump to a side-action with list of available providers (and their
-status) and possibly add additional providers that are not included in the
-default list provided by the wallet.
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/policy.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addpolicy.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addpolicymethod.png
- :width: 800
-
-
-Defining Recovery Options
--------------------------
-
-After mapping authentication methods to providers, the user needs select which
-combinations are sufficient to recover the secret. Here, the system
-pre-computes a reasonably sane allocation, for small ``n`` the default could
-be ``n-1`` out of ``n``.
-
-We should propose a mapping of authentication methods to providers by
-minimizing cost (tricky: sign-up vs. recovery costs, different currencies) and
-distributing the selected authentication methods across as many providers as
-possible.
-
-The user should be able to change the proposed default selection
-and add more than one provider to each chosen method.
-
-Using Anastatis providers usually is not free. From here on, the UI should
-show estimated recurring costs (yearly) and the cost of recovery. These costs
-should get updated with each user action affecting those costs such as
-when the user reconfigures the policies.
-
-
-Pay for Setup
--------------
-
-As the last step when all information has been properly provided, the user is
-asked to pay for the service with the regular wallet payment confirmation
-screen.
-
-
-Show Service Status After Setup
-===============================
-
-TODO
-
-Recovery Steps
-==============
-
-.. graphviz::
-
- digraph G {
- rankdir=LR;
- nodesep=0.5;
- settings [
- label = "Restore from Backup";
- shape = oval;
- ];
- provide_id [
- label = "Provide\nIdentification";
- shape = rectangle;
- ];
- select_challenge [
- label = "Select\nAuthentication Challenge";
- shape = rectangle;
- ];
- satisfy_challenge [
- label = "Enter\nChallenge Response";
- shape = rectangle;
- ];
- pay [
- label = "Confirm Payment";
- shape = oval;
- ];
- finished [
- label = "Success";
- shape = rectangle;
- ];
- settings -> provide_id;
- provide_id -> settings [label="Back"];
- provide_id -> select_challenge;
- select_challenge -> provide_id [label="Back"];
- select_challenge -> satisfy_challenge;
- select_challenge -> pay;
- satisfy_challenge -> pay;
- pay -> satisfy_challenge;
- satisfy_challenge -> select_challenge;
- pay -> finished;
- satisfy_challenge -> finished;
- }
-
-
-Entry point: Settings
----------------------
-
-Like the backup, the recovery option should be available via
-the App settings.
-
-The section should have an option to recover from backup. If a previous
-recovery was not completed, the interaction should resume from that previous
-checkpoint instead of from the beginning.
-
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/menu.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/settings.png
- :width: 800
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/backupsettings.png
- :width: 800
-
-
-Providing Identification
-------------------------
-
-The first dialog(s) during recovery should be identical to the first dialog
-during backup: the user is asked to select a continent, country of residence
-and then to provide country-specific inputs for identification.
-
-.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/userid.png
- :width: 800
-
-Select Authentication Challenge
--------------------------------
-
-If Anastasis could recover the recovery document via any provider, it should
-show a dialog allowing the user to select one of the open challenges, and
-highlight which challenges still need to be satisfied for the various policies.
-
-Additionally, the specific provider and recovery document version should be shown.
-The user should be able to change the provider or recovery document version,
-resulting in a switch of the recovery document and policies. If the user has
-already satisfied some challenges of the current recovery document, switching to a
-different recovery document should only be done after a confirmation pop-up dialog
-warning the user that the existing progress will be lost.
-
-When selecting a challenge, the user may be asked to confirm making a payment
-for this challenge if the provider requires payment.
-
-
-Payment
--------
-
-Typcially, this would be the canonical wallet payment confirmation dialog.
-
-However, in the case of a security question, the payment confirmation should
-be combined with the dialog where the user enters the security answer (so
-instead of an ``Ok`` button, text showing the amount due and ``Pay`` should be
-used -- except of course if the security question challenge is free of
-charge).
-
-
-Enter Challenge Response
-------------------------
-
-If the challenge was not a security question, the dialog to enter the security
-code (PIN/TAN) should open after payment. The security code field should have
-a prefix ``A-``. However, the user should be able to enter both only the
-numeric code, or the full code with the ``A-`` prefix (or ideally, the user
-cannot delete the pre-filled ``A-`` text).
-
-
-Success
--------
-
-The user is informed about the successful recovery. We may want to do this
-as part of a separate screen, or simply with a notification bar in the
-main wallet screen.
diff --git a/design-documents/index.rst b/design-documents/index.rst
index 7f875095..f5b8a93e 100644
--- a/design-documents/index.rst
+++ b/design-documents/index.rst
@@ -14,7 +14,6 @@ and protocol.
003-tos-rendering
004-wallet-withdrawal-flow
005-wallet-backup-sync
- 006-anastasis-ux
007-payment
008-fees
009-backup
diff --git a/fdl-1.3.rst b/fdl-1.3.rst
index 49bf2d3e..612bd4f3 100644
--- a/fdl-1.3.rst
+++ b/fdl-1.3.rst
@@ -24,7 +24,7 @@ modifications made by others.
This License is a kind of “copyleft”, which means that derivative works
of the document must themselves be free in the same sense. It
-complements the GNU General Public License, which is a copyleft license
+complements the GNU Affero General Public License, which is a copyleft license
designed for free software.
We have designed this License in order to use it for manuals for free
@@ -449,5 +449,5 @@ situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
-software license, such as the GNU General Public License, to permit
+software license, such as the GNU Affero General Public License, to permit
their use in free software.
diff --git a/index.rst b/index.rst
index 43212ce2..6e182011 100644
--- a/index.rst
+++ b/index.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Florian Dold
@@ -44,7 +44,6 @@ components, internal architecture of key components, and how to get them
installed. In addition to this documentation, we have source-level
documentation which you can find converted to HTML at these pages:
- * `Anastasis <https://docs.taler.net/doxygen/anastasis/>`_
* `Exchange <https://docs.taler.net/doxygen/exchange/>`_
* `Merchant <https://docs.taler.net/doxygen/merchant/>`_
* `Wallet-core <https://docs.taler.net/doxygen/wallet-core/>`_
@@ -69,7 +68,6 @@ Documentation Overview
taler-developer-manual
taler-wallet
design-documents/index
- anastasis
libeufin/index
global-licensing
manindex
diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst
index 3eec17f8..6a7a3028 100644
--- a/taler-auditor-manual.rst
+++ b/taler-auditor-manual.rst
@@ -4,14 +4,14 @@
Copyright (C) 2019-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/taler-developer-manual.rst b/taler-developer-manual.rst
index 81c99c27..5f6a4f6a 100644
--- a/taler-developer-manual.rst
+++ b/taler-developer-manual.rst
@@ -4,14 +4,14 @@
Copyright (C) 2014-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
@@ -727,7 +727,7 @@ Under *https://weblate.taler.net/create/component/vcs/*:
* **Merge style** - *Rebase*, in line with GNU Taler development procedures
-* **Translation license** - *GNU General Public License v3.0 or Later*
+* **Translation license** - *GNU Affero General Public License v3.0 or Later*
* **Adding new translation** - Decide how to handle adding new translations
diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst
index c28ddaa2..93ff72ee 100644
--- a/taler-exchange-manual.rst
+++ b/taler-exchange-manual.rst
@@ -4,14 +4,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
diff --git a/taler-mcig.rst b/taler-mcig.rst
index 692c05e0..f93d3d15 100644
--- a/taler-mcig.rst
+++ b/taler-mcig.rst
@@ -3,14 +3,14 @@
Copyright (C) 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Thien-Thi Nguyen
diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst
index e4a9d151..0be0f4e3 100644
--- a/taler-merchant-api-tutorial.rst
+++ b/taler-merchant-api-tutorial.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Marcello Stanisci
diff --git a/taler-merchant-pos-terminal.rst b/taler-merchant-pos-terminal.rst
index 5ccfd5c0..356838fd 100644
--- a/taler-merchant-pos-terminal.rst
+++ b/taler-merchant-pos-terminal.rst
@@ -3,14 +3,14 @@
Copyright (C) 2014-2018 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
+ terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along with
+ You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Torsten Grote