anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

reducer.rst (57674B)


      1 ..
      2   This file is part of Anastasis
      3   Copyright (C) 2019-2022 Anastasis SARL
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 2.1, or (at your option) any later version.
      8 
      9   Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   Anastasis; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 
     16   @author Christian Grothoff
     17   @author Dominik Meister
     18   @author Dennis Neufeld
     19 
     20 -----------
     21 Reducer API
     22 -----------
     23 
     24 This section describes the Anastasis Reducer API which is used by client applications
     25 to store or load the different states the client application can have.
     26 The reducer takes a state_ in JSON syntax and returns the new state in JSON syntax.
     27 
     28 For example a **state** may take the following structure:
     29 
     30 .. code-block:: json
     31 
     32     {
     33       "backup_state": "CONTINENT_SELECTING",
     34       "continents": [
     35         "Europe",
     36         "North_America"
     37       ]
     38     }
     39 
     40 The new state depends on the previous one and on the transition action_ with its
     41 arguments given to the reducer. A **transition argument** also is a statement in JSON syntax:
     42 
     43 .. code-block:: json
     44 
     45     {
     46       "continent": "Europe"
     47     }
     48 
     49 The new state returned by the reducer with the state and transition argument defined
     50 above would look like following for the transition action_ ``select_continent``:
     51 
     52 .. code-block:: json
     53 
     54   {
     55     "backup_state": "COUNTRY_SELECTING",
     56     "continents": [
     57       "Europe",
     58       "North_America"
     59     ],
     60     "selected_continent": "Europe",
     61     "countries": [
     62       {
     63         "code": "ch",
     64         "name": "Switzerland",
     65         "continent": "Europe",
     66         "name_i18n": {
     67           "de_DE": "Schweiz",
     68           "de_CH": "Schwiiz",
     69           "fr": "Suisse",
     70           "en": "Swiss"
     71         },
     72         "currency": "CHF"
     73       },
     74       {
     75         "code": "de",
     76         "name": "Germany",
     77         "continent": "Europe",
     78         "continent_i18n": {
     79           "de": "Europa"
     80         },
     81         "name_i18n": {
     82           "de_DE": "Deutschland",
     83           "de_CH": "Deutschland",
     84           "fr": "Allemagne",
     85           "en": "Germany"
     86         },
     87         "currency": "EUR"
     88       }
     89     ]
     90   }
     91 
     92 An action may also result into an *error response* instead of a new state.
     93 Clients should then render this error response to the user and allow the user
     94 to continue from the old state.  An error response looks like this:
     95 
     96 .. code-block:: json
     97 
     98   {
     99     "code": 123,
    100     "hint": "something went wrong",
    101     "details": "parameter foo failed to frobnify"
    102   }
    103 
    104 States
    105 ^^^^^^
    106 
    107 Overall, the reducer knows the following states:
    108 
    109   - **CONTINENT_SELECTING**: The user should specify the continent where they are living,
    110                so that we can show a list of countries to choose from.
    111   - **COUNTRY_SELECTING**: The user should specify the country where they are living,
    112                so that we can determine appropriate attributes, currencies and Anastasis
    113                providers.
    114   - **USER_ATTRIBUTES_COLLECTING**: The user should provide the country-specific personal
    115                attributes.
    116   - **AUTHENTICATIONS_EDITING**: The user should add authentication methods to be used
    117                during recovery.
    118   - **POLICIES_REVIEWING**: The user should review the recovery policies.
    119   - **SECRET_EDITING**: The user should edit the secret to be backed up.
    120   - **TRUTHS_PAYING**: The user needs to pay for one or more uploads of data associated
    121                with an authentication method.
    122   - **POLICIES_PAYING**: The user needs to pay for storing the recovery policy document.
    123   - **BACKUP_FINISHED**: A backup has been successfully generated.
    124   - **SECRET_SELECTING**: The user needs to select a recovery policy document with
    125                the secret that is to be recovered.
    126   - **CHALLENGE_SELECTING**: The user needs to select an authorization challenge to
    127                proceed with recovery.
    128   - **CHALLENGE_PAYING**: The user needs to pay to proceed with the authorization challenge.
    129   - **CHALLENGE_SOLVING**: The user needs to solve the authorization challenge.
    130   - **RECOVERY_FINISHED**: The secret of the user has been recovered.
    131 
    132 State names:
    133 
    134   - 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).
    135   - In COLLECTING-states, the user has to give certain values.
    136   - In EDITING-states, the user is free to choose which values he wants to give.
    137   - In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something.
    138   - in PAYING-states, the user must make a payment.
    139   - in FINISHED-states, the operation has definitively concluded.
    140 
    141 
    142 Backup Reducer
    143 ^^^^^^^^^^^^^^
    144 .. _state:
    145 .. _action:
    146 .. figure:: anastasis_reducer_backup.png
    147     :name: fig-anastasis_reducer_backup
    148     :alt: fig-anastasis_reducer_backup
    149     :scale: 75 %
    150     :align: center
    151 
    152     Backup states and their transitions.
    153 
    154 
    155 The illustration above shows the different states the reducer can have during a backup
    156 process.
    157 
    158 
    159 Recovery Reducer
    160 ^^^^^^^^^^^^^^^^
    161 .. figure:: anastasis_reducer_recovery.png
    162     :name: fig-anastasis_reducer_recovery
    163     :alt: fig-anastasis_reducer_recovery
    164     :scale: 75 %
    165     :align: center
    166 
    167     Recovery states and their transitions.
    168 
    169 
    170 The illustration above shows the different states the reducer can have during a recovery
    171 process.
    172 
    173 
    174 Reducer transitions
    175 ^^^^^^^^^^^^^^^^^^^
    176 In the following, the individual transitions will be specified in more detail.
    177 Note that we only show fields added by the reducer, typically the previous
    178 state is preserved to enable "back" transitions to function smoothly.
    179 
    180 
    181 Initial state
    182 -------------
    183 
    184 The initial states for backup and recovery processes are:
    185 
    186 **Initial backup state:**
    187 
    188 .. code-block:: json
    189 
    190     {
    191       "backup_state": "CONTINENT_SELECTING",
    192       "continents": [
    193         "Europe",
    194         "North America"
    195       ]
    196     }
    197 
    198 
    199 **Initial recovery state:**
    200 
    201 .. code-block:: json
    202 
    203     {
    204       "recovery_state": "CONTINENT_SELECTING",
    205       "continents": [
    206         "Europe",
    207         "North America"
    208       ]
    209     }
    210 
    211 Here, "continents" is an array of English strings with the names of the
    212 continents which contain countries for which Anastasis could function (based
    213 on having providers that are known to operate and rules being provided for
    214 user attributes from those countries).
    215 
    216 For internationalization, another field ``continents_i18n`` may be present.
    217 This field would be a map of language names to arrays of translated
    218 continent names:
    219 
    220 .. code-block:: json
    221 
    222     {
    223       "recovery_state": "CONTINENT_SELECTING",
    224       "continents": [
    225         "Europe",
    226         "North America"
    227       ]
    228       "continents_i18n":
    229       {
    230         "de_DE" : [
    231           "Europa",
    232           "Nordamerika"
    233           ],
    234         "de_CH" : [
    235           "Europa",
    236           "Nordamerika"
    237           ]
    238       }
    239     }
    240 
    241 Translations must be given in the same order as the main English array.
    242 
    243 
    244 Common transitions
    245 ------------------
    246 
    247 **select_continent:**
    248 
    249 Here the user specifies the continent they live on.  Arguments (example):
    250 
    251 .. code-block:: json
    252 
    253     {
    254       "continent": "Europe"
    255     }
    256 
    257 The continent must be given using the English name from the ``continents`` array.
    258 Using a translated continent name is invalid and may result in failure.
    259 
    260 The reducer returns an updated state with a list of countries to choose from,
    261 for example:
    262 
    263 .. code-block:: json
    264 
    265     {
    266       "backup_state": "COUNTRY_SELECTING",
    267       "selected_continent": "Europe",
    268       "countries": [
    269         {
    270           "code": "ch",
    271           "name": "Switzerland",
    272           "continent": "Europe",
    273           "name_i18n": {
    274             "de_DE": "Schweiz",
    275             "de_CH": "Schwiiz",
    276             "fr": "Suisse",
    277             "en": "Swiss"
    278           },
    279           "currency": "CHF"
    280         },
    281         {
    282           "code": "de",
    283           "name": "Germany",
    284           "continent": "Europe",
    285           "continent_i18n": {
    286             "de": "Europa"
    287           },
    288           "name_i18n": {
    289             "de_DE": "Deutschland",
    290             "de_CH": "Deutschland",
    291             "fr": "Allemagne",
    292             "en": "Germany"
    293           },
    294           "currency": "EUR"
    295         }
    296       ]
    297     }
    298 
    299 Here ``countries`` is an array of countries on the ``selected_continent``.  For
    300 each country, the ``code`` is the ISO 3166-1 alpha-2 country code.  The
    301 ``continent`` is only present because some countries span continents, the
    302 information is redundant and will always match ``selected_continent``.  The
    303 ``name`` is the name of the country in English, internationalizations of the
    304 name may be provided in ``name_i18n``.  The ``currency`` is **an** official
    305 currency of the country, if a country has multiple currencies, it may appear
    306 multiple times in the list.  In this case, the user should select the entry
    307 with the currency they intend to pay with.  It is also possible for users
    308 to select a currency that does not match their country, but user interfaces
    309 should by default try to use currencies that match the user's residence.
    310 
    311 
    312 **select_country:**
    313 
    314 Selects the country (via the country code) and specifies the currency.
    315 The latter is needed as some countries have more than one currency,
    316 and some use-cases may also involve users insisting on paying with
    317 foreign currency.
    318 
    319 Arguments (example):
    320 
    321 .. code-block:: json
    322 
    323     {
    324       "country_code": "de",
    325       "currency": "EUR"
    326     }
    327 
    328 The ``country_code`` must be an ISO 3166-1 alpha-2 country code from
    329 the array of ``countries`` of the reducer's state.  The ``currency``
    330 field must be a valid currency accepted by the Taler payment system.
    331 
    332 The reducer returns a new state with the list of attributes the
    333 user is expected to provide, as well as possible authentication
    334 providers that accept payments in the selected currency:
    335 
    336 .. code-block:: json
    337 
    338     {
    339       "backup_state": "USER_ATTRIBUTES_COLLECTING",
    340       "selected_country": "de",
    341       "currency": "EUR",
    342       "required_attributes": [
    343         {
    344           "type": "string",
    345           "name": "full_name",
    346           "label": "Full name",
    347           "label_i18n": {
    348             "de_DE": "Vollstaendiger Name",
    349             "de_CH": "Vollstaendiger. Name",
    350             "fr": "Nom complet",
    351             "en": "Full name"
    352           },
    353           "widget": "anastasis_gtk_ia_full_name",
    354           "uuid" : "9e8f463f-575f-42cb-85f3-759559997331"
    355         },
    356         {
    357           "type": "date",
    358           "name": "birthdate",
    359           "label": "Birthdate",
    360           "label_i18n": {
    361             "de_DE": "Geburtsdatum",
    362             "de_CH": "Geburtsdatum",
    363             "fr": "Date de naissance",
    364             "en": "Birthdate"
    365           },
    366           "uuid" : "83d655c7-bdb6-484d-904e-80c1058c8854"
    367           "widget": "anastasis_gtk_ia_birthdate"
    368         },
    369  	    {
    370 	       "type": "string",
    371                "name": "tax_number",
    372 	       "label": "Taxpayer identification number",
    373 	       "label_i18n":{
    374 		     "de_DE": "Steuerliche Identifikationsnummer",
    375 	  	     "de_CH": "Steuerliche Identifikationsnummer",
    376 	   	     "en": "German taxpayer identification number"
    377 	       },
    378 	       "widget": "anastasis_gtk_ia_tax_de",
    379                "uuid": "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
    380 	       "validation-regex": "^[0-9]{11}$",
    381 	       "validation-logic": "DE_TIN_check"
    382    	    },
    383         {
    384           "type": "string",
    385           "name": "social_security_number",
    386           "label": "Social security number",
    387           "label_i18n": {
    388             "de_DE": "Sozialversicherungsnummer",
    389             "de_CH": "Sozialversicherungsnummer",
    390             "fr": "Numéro de sécurité sociale",
    391             "en": "Social security number"
    392           },
    393           "widget": "anastasis_gtk_ia_ssn",
    394    	  "validation-regex": "^[0-9]{8}[[:upper:]][0-9]{3}$",
    395 	  "validation-logic": "DE_SVN_check"
    396           "optional" : true
    397       }
    398       ],
    399       "authentication_providers": {
    400         "http://localhost:8089/": {
    401           "http_status": 200,
    402           "methods": [
    403             { "type" : "question",
    404               "usage_fee" : "EUR:0.0" },
    405             { "type" : "sms",
    406               "usage_fee" : "EUR:0.5" }
    407           ],
    408           "annual_fee": "EUR:4.99",
    409           "truth_upload_fee": "EUR:4.99",
    410           "liability_limit": "EUR:1",
    411           "currency": "EUR",
    412           "storage_limit_in_megabytes": 1,
    413           "provider_name": "Anastasis 4",
    414           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    415         },
    416         "http://localhost:8088/": {
    417           "http_status": 200,
    418           "methods": [
    419             { "type" : "question",
    420               "usage_fee" : "EUR:0.01" },
    421             { "type" : "sms",
    422               "usage_fee" : "EUR:0.55" }
    423           ],
    424           "annual_fee": "EUR:0.99",
    425           "truth_upload_fee": "EUR:3.99",
    426           "liability_limit": "EUR:1",
    427           "currency": "EUR",
    428           "storage_limit_in_megabytes": 1,
    429           "provider_name": "Anastasis 4",
    430           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    431         }
    432       }
    433     }
    434 
    435 The array of ``required_attributes`` contains attributes about the user
    436 that must be provided includes:
    437 
    438   - **type**: The type of the attribute, for now only ``string`` and ``date`` are
    439     supported.
    440   - **name**: The name of the attribute, this is the key under which the
    441     attribute value must be provided later. The name must be unique per response.
    442   - **label**: A human-readable description of the attribute in English.
    443     Translated descriptions may be provided under **label_i18n**.
    444   - **uuid**: A UUID that uniquely identifies identical attributes across
    445     different countries. Useful to preserve values should the user enter
    446     some attributes, and then switch to another country.  Note that
    447     attributes must not be preserved if they merely have the same **name**,
    448     only the **uuid** will be identical if the semantics is identical.
    449   - **widget**: An optional name of a widget that is known to nicely render
    450     the attribute entry in user interfaces where named widgets are
    451     supported.
    452   - **validation-regex**: An optional extended POSIX regular expression
    453     that is to be used to validate (string) inputs to ensure they are
    454     well-formed.
    455   - **validation-logic**: Optional name of a function that should be called
    456     to validate the input.  If the function is not known to the particular
    457     client, the respective validation can be skipped (at the expense of
    458     typos by users not being detected, possibly rendering secrets
    459     irrecoverable).
    460   - **optional**: Optional boolean field that, if ``true``, indicates that
    461     this attribute is not actually required but optional and users MAY leave
    462     it blank in case they do not have the requested information. Used for
    463     common fields that apply to some large part of the population but are
    464     not sufficiently universal to be actually required.
    465 
    466 The authentication providers are listed under a key that is the
    467 base URL of the service. For each provider, the following
    468 information is provided if the provider was successfully contacted:
    469 
    470   - **http_status**: HTTP status code, always ``200`` on success.
    471   - **methods**: Array of authentication methods supported by this
    472     provider. Includes the **type** of the authentication method
    473     and the **usage_fee** (how much the user must pay for authorization
    474     using this method during recovery).
    475   - **annual_fee**: Fee the provider charges to store the recovery
    476     policy for one year.
    477   - **truth_upload_fee**: Fee the provider charges to store a key share.
    478   - **liability_limit**: Amount the provider can be held liable for in
    479     case a key share or recovery document cannot be recovered due to
    480     provider failures.
    481   - **currency**: Currency in which the provider wants to be paid,
    482     will match all of the fees.
    483   - **storage_limit_in_megabytes**: Maximum size of an upload (for
    484     both recovery document and truth data) in megabytes.
    485   - **provider_name**: Human-readable name of the provider's business.
    486   - **salt**: Salt value used by the provider, used to derive the
    487     user's identity at this provider. Should be unique per provider,
    488     and must never change for a given provider.  The salt is
    489     base32 encoded.
    490 
    491 If contacting the provider failed, the information returned is:
    492 
    493   - **http_status**: HTTP status code (if available, possibly 0 if
    494     we did not even obtain an HTTP response).
    495   - **error_code**: Taler error code, never 0.
    496 
    497 
    498 **add_provider**:
    499 
    500 This operation can be performed in state ``USER_ATTRIBUTES_COLLECTING``.
    501 It
    502 adds one or more Anastasis providers to the list of providers the reducer
    503 should henceforth consider.  Note that removing providers is not possible at
    504 this time.
    505 
    506 Here, the client must provide an object with the base URLs of the
    507 providers to add or disable. The object maps the
    508 URLs to status information about the provider to
    509 use. For example:
    510 
    511 .. code-block:: json
    512 
    513     {
    514       "http://localhost:8088/" : { "disabled" : false },
    515       "http://localhost:8089/" : { "disabled" : false },
    516       "http://localhost:8090/" : { "disabled" : true }
    517     }
    518 
    519 Note that existing providers will remain in the state they were in.  The following is an
    520 example for an expected new state where the service on port 8089 is
    521 unreachable, the services on port 8088 and 8888 were previously known, and service on
    522 port 8088 was now added, and on 8090 is disabled:
    523 
    524 .. code-block:: json
    525 
    526     {
    527       "backup_state": "USER_ATTRIBUTES_COLLECTING",
    528       "authentication_providers": {
    529         "http://localhost:8089/": {
    530           "disabled": false,
    531           "error_code": 11,
    532           "http_status": 0
    533         },
    534         "http://localhost:8090/": {
    535           "disabled": true
    536         },
    537         "http://localhost:8088/": {
    538           "disabled": false,
    539           "http_status": 200,
    540           "methods": [
    541             { "type" : "question",
    542               "usage_fee" : "EUR:0.01" },
    543             { "type" : "sms",
    544               "usage_fee" : "EUR:0.55" }
    545           ],
    546           "annual_fee": "EUR:0.99",
    547           "truth_upload_fee": "EUR:3.99",
    548           "liability_limit": "EUR:1",
    549           "currency": "EUR",
    550           "storage_limit_in_megabytes": 1,
    551           "provider_name": "Anastasis 4",
    552           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    553         }
    554         "http://localhost:8888/": {
    555           "methods": [
    556             { "type" : "question",
    557               "usage_fee" : "EUR:0.01" },
    558             { "type" : "sms",
    559               "usage_fee" : "EUR:0.55" }
    560           ],
    561           "annual_fee": "EUR:0.99",
    562           "truth_upload_fee": "EUR:3.99",
    563           "liability_limit": "EUR:1",
    564           "currency": "EUR",
    565           "storage_limit_in_megabytes": 1,
    566           "provider_name": "Anastasis 42",
    567           "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
    568         }
    569       }
    570     }
    571 
    572 
    573 
    574 Backup transitions
    575 ------------------
    576 
    577 **enter_user_attributes:**
    578 
    579 This transition provides the user's personal attributes. The specific set of
    580 attributes required depends on the country of residence of the user.  Some
    581 attributes may be optional, in which case they should be omitted entirely
    582 (that is, not simply be set to ``null`` or an empty string).  Example
    583 arguments would be:
    584 
    585 .. code-block:: json
    586 
    587     {
    588       "identity_attributes": {
    589         "full_name": "Max Musterman",
    590         "social_security_number": "123456789",
    591         "birthdate": "2000-01-01",
    592         "birthplace": "Earth"
    593      }
    594     }
    595 
    596 Note that at this stage, the state machines between backup and
    597 recovery diverge and the ``recovery_state`` will begin to look
    598 very different from the ``backup_state``.
    599 
    600 For backups, if all required attributes are present, the reducer will
    601 transition to an ``AUTHENTICATIONS_EDITING`` state with the attributes added
    602 to it:
    603 
    604 .. code-block:: json
    605 
    606     {
    607       "backup_state": "AUTHENTICATIONS_EDITING",
    608       "identity_attributes": {
    609         "full_name": "Max Musterman",
    610         "social_security_number": "123456789",
    611         "birthdate": "2000-01-01",
    612         "birthplace": "Earth"
    613       }
    614     }
    615 
    616 If required attributes are missing, do not match the required regular
    617 expression, or fail the custom validation logic, the reducer SHOULD return an
    618 error response indicating that the transition has failed and what is wrong about
    619 the input and not transition to a new state.  A reducer that does not support
    620 some specific validation logic MAY accept the invalid input and proceed anyway.
    621 The error state will include a Taler error code that is specific to the
    622 failure, and optional details.
    623 
    624 Example:
    625 
    626 .. code-block:: json
    627 
    628     {
    629       "code": 8404,
    630       "hint": "An input did not match the regular expression.",
    631       "detail": "social_security_number"
    632     }
    633 
    634 Clients may safely repeat this transition to validate the user's inputs
    635 until they satisfy all of the constraints.  This way, the user interface
    636 does not have to perform the input validation directly.
    637 
    638 
    639 **add_authentication**:
    640 
    641 This transition adds an authentication method.  The method must be supported
    642 by one or more providers that are included in the current state.  Adding an
    643 authentication method requires specifying the ``type`` and ``instructions`` to
    644 be given to the user.  The ``challenge`` is encrypted and stored at the
    645 Anastasis provider. The specific semantics of the value depend on the
    646 ``type``.  Typical challenges values are a phone number (to send an SMS to),
    647 an e-mail address (to send a PIN code to) or the answer to a security
    648 question.  Note that these challenge values will still be encrypted (and
    649 possibly hashed) before being given to the Anastasis providers.
    650 
    651 Note that the ``challenge`` must be given in Crockford Base32 encoding, as it
    652 MAY include binary data (such as a photograph of the user).  In the latter
    653 case, the optional ``mime_type`` field must be provided to give the MIME type
    654 of the value encoded in ``challenge``.
    655 
    656 .. code-block:: json
    657 
    658     {
    659       "authentication_method":
    660       {
    661         "type": "question",
    662         "mime_type" : "text/plain",
    663         "instructions" : "What is your favorite GNU package?",
    664         "challenge" : "E1QPPS8A",
    665       }
    666     }
    667 
    668 If the information provided is valid, the reducer will add the new
    669 authentication method to the array of authentication methods:
    670 
    671 .. code-block:: json
    672 
    673     {
    674       "backup_state": "AUTHENTICATIONS_EDITING",
    675       "authentication_methods": [
    676         {
    677           "type": "question",
    678           "mime_type" : "text/plain",
    679           "instructions" : "What is your favorite GNU package?",
    680           "challenge" : "E1QPPS8A",
    681         },
    682         {
    683           "type": "email",
    684           "instructions" : "E-mail to user@*le.com",
    685           "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
    686         }
    687       ]
    688     }
    689 
    690 
    691 **delete_authentication**:
    692 
    693 This transition can be used to remove an authentication method from the
    694 array of authentication methods. It simply requires the index of the
    695 authentication method to remove. Note that the array is 0-indexed:
    696 
    697 .. code-block:: json
    698 
    699     {
    700       "authentication_method": 1
    701     }
    702 
    703 Assuming we begin with the state from the example above, this would
    704 remove the ``email`` authentication method, resulting in the following
    705 response:
    706 
    707 .. code-block:: json
    708 
    709     {
    710       "backup_state": "AUTHENTICATIONS_EDITING",
    711       "authentication_methods": [
    712         {
    713           "type": "question",
    714           "mime_type" : "text/plain",
    715           "instructions" : "What is your favorite GNU package?",
    716           "challenge" : "gdb",
    717         }
    718       ]
    719     }
    720 
    721 If the index is invalid, the reducer will return an error
    722 response instead of making a transition.
    723 
    724 
    725 **next** (from ``AUTHENTICATIONS_EDITING``):
    726 
    727 This transition confirms that the user has finished adding (or removing)
    728 authentication methods, and that the system should now automatically compute
    729 a set of reasonable recovery policies.
    730 
    731 This transition does not take any mandatory arguments.  Optional arguments can
    732 be provided to upload the recovery document only to a specific subset of the
    733 providers:
    734 
    735 .. code-block:: json
    736 
    737     {
    738       "providers": [
    739         "http://localhost:8088/",
    740         "http://localhost:8089/"
    741       ]
    742     }
    743 
    744 The resulting state provides the suggested recovery policies in a way suitable
    745 for presentation to the user:
    746 
    747 .. code-block:: javascript
    748 
    749     {
    750       "backup_state": "POLICIES_REVIEWING",
    751       "policy_providers" : [
    752           { "provider_url" : "http://localhost:8088/" },
    753           { "provider_url" : "http://localhost:8089/" }
    754       ],
    755       "policies": [
    756         {
    757           "methods": [
    758             {
    759               "authentication_method": 0,
    760               "provider": "http://localhost:8088/"
    761             },
    762             {
    763               "authentication_method": 1,
    764               "provider": "http://localhost:8089/"
    765             },
    766             {
    767               "authentication_method": 2,
    768               "provider": "http://localhost:8087/"
    769             }
    770           ]
    771         },
    772         {
    773           "methods": [
    774             {
    775               "authentication_method": 0,
    776               "provider": "http://localhost:8088/"
    777             },
    778             {
    779               "authentication_method": 1,
    780               "provider": "http://localhost:8089/"
    781             },
    782             {
    783               "authentication_method": 3,
    784               "provider": "http://localhost:8089/"
    785             }
    786           ]
    787         }
    788       ]
    789     }
    790 
    791 For each recovery policy, the state includes the specific details of which
    792 authentication ``methods`` must be solved to recovery the secret using this
    793 policy.  The ``methods`` array specifies the index of the
    794 ``authentication_method`` in the ``authentication_methods`` array, as well as
    795 the provider that was selected to supervise this authentication.
    796 
    797 If no authentication method was provided, the reducer will
    798 return an error response instead of making a transition.
    799 
    800 
    801 **add_policy**:
    802 
    803 Using this transition, the user can add an additional recovery policy to the
    804 state.  The argument format is the same that is used in the existing state.
    805 An example for a possible argument would thus be:
    806 
    807 .. code-block:: javascript
    808 
    809     {
    810       "policy": [
    811         {
    812           "authentication_method": 1,
    813           "provider": "http://localhost:8088/"
    814         },
    815         {
    816           "authentication_method": 3,
    817           "provider": "http://localhost:8089/"
    818         }
    819       ]
    820     }
    821 
    822 Note that the specified providers must already be in the
    823 ``authentication_providers`` of the state. You cannot add new providers at
    824 this stage.  The reducer will simply attempt to append the suggested policy to
    825 the "policies" array, returning an updated state:
    826 
    827 .. code-block:: json
    828 
    829     {
    830       "backup_state": "POLICIES_REVIEWING",
    831       "policies": [
    832         {
    833           "methods": [
    834             {
    835               "authentication_method": 0,
    836               "provider": "http://localhost:8089/"
    837             },
    838             {
    839               "authentication_method": 1,
    840               "provider": "http://localhost:8088/"
    841             }
    842           ]
    843         },
    844         {
    845           "methods": [
    846             {
    847               "authentication_method": 0,
    848               "provider": "http://localhost:8089/"
    849             },
    850             {
    851               "authentication_method": 2,
    852               "provider": "http://localhost:8088/"
    853             }
    854           ]
    855         },
    856         {
    857           "methods": [
    858             {
    859               "authentication_method": 1,
    860               "provider": "http://localhost:8089/"
    861             },
    862             {
    863               "authentication_method": 2,
    864               "provider": "http://localhost:8088/"
    865             }
    866           ]
    867         },
    868         {
    869           "methods": [
    870             {
    871               "authentication_method": 1,
    872               "provider": "http://localhost:8088/"
    873             },
    874             {
    875               "authentication_method": 3,
    876               "provider": "http://localhost:8089/"
    877             }
    878           ]
    879         }
    880       ]
    881     }
    882 
    883 If the new policy is invalid, for example because it adds an unknown
    884 authentication method, or the selected provider does not support the type of
    885 authentication, the reducer return an error response instead of
    886 adding the new policy.
    887 
    888 
    889 **update_policy**:
    890 
    891 Using this transition, the user can modify an existing recovery policy
    892 in the state.
    893 The argument format is the same that is used in **add_policy**,
    894 except there is an additional key ``policy_index`` which
    895 identifies the policy to modify.
    896 An example for a possible argument would thus be:
    897 
    898 .. code-block:: javascript
    899 
    900     {
    901       "policy_index" : 1,
    902       "policy": [
    903         {
    904           "authentication_method": 1,
    905           "provider": "http://localhost:8088/"
    906         },
    907         {
    908           "authentication_method": 3,
    909           "provider": "http://localhost:8089/"
    910         }
    911       ]
    912     }
    913 
    914 If the new policy is invalid, for example because it adds an unknown
    915 authentication method, or the selected provider does not support the type of
    916 authentication, the reducer will return an error response instead of
    917 modifying the policy.
    918 
    919 
    920 
    921 **delete_policy:**
    922 
    923 This transition allows the deletion of a recovery policy. The argument
    924 simply specifies the index of the policy to delete, for example:
    925 
    926 .. code-block:: json
    927 
    928     {
    929       "policy_index": 3
    930     }
    931 
    932 Given as input the state from the example above, the expected new state would
    933 be:
    934 
    935 .. code-block:: json
    936 
    937     {
    938       "backup_state": "POLICIES_REVIEWING",
    939       "policies": [
    940         {
    941           "methods": [
    942             {
    943               "authentication_method": 0,
    944               "provider": "http://localhost:8089/"
    945             },
    946             {
    947               "authentication_method": 1,
    948               "provider": "http://localhost:8088/"
    949             }
    950           ]
    951         },
    952         {
    953           "methods": [
    954             {
    955               "authentication_method": 0,
    956               "provider": "http://localhost:8089/"
    957             },
    958             {
    959               "authentication_method": 2,
    960               "provider": "http://localhost:8088/"
    961             }
    962           ]
    963         },
    964         {
    965           "methods": [
    966             {
    967               "authentication_method": 1,
    968               "provider": "http://localhost:8089/"
    969             },
    970             {
    971               "authentication_method": 2,
    972               "provider": "http://localhost:8088/"
    973             }
    974           ]
    975         }
    976       ]
    977     }
    978 
    979 If the index given is invalid, the reducer will return an error response
    980 instead of deleting a policy.
    981 
    982 
    983 **delete_challenge:**
    984 
    985 This transition allows the deletion of an individual
    986 challenge from a recovery policy. The argument
    987 simply specifies the index of the policy and challenge
    988 to delete, for example:
    989 
    990 .. code-block:: json
    991 
    992     {
    993       "policy_index": 1,
    994       "challenge_index" : 1
    995     }
    996 
    997 Given as input the state from the example above, the expected new state would
    998 be:
    999 
   1000 .. code-block:: json
   1001 
   1002     {
   1003       "backup_state": "POLICIES_REVIEWING",
   1004       "policies": [
   1005         {
   1006           "methods": [
   1007             {
   1008               "authentication_method": 0,
   1009               "provider": "http://localhost:8089/"
   1010             },
   1011             {
   1012               "authentication_method": 1,
   1013               "provider": "http://localhost:8088/"
   1014             }
   1015           ]
   1016         },
   1017         {
   1018           "methods": [
   1019             {
   1020               "authentication_method": 0,
   1021               "provider": "http://localhost:8089/"
   1022             }
   1023           ]
   1024         },
   1025         {
   1026           "methods": [
   1027             {
   1028               "authentication_method": 1,
   1029               "provider": "http://localhost:8089/"
   1030             },
   1031             {
   1032               "authentication_method": 2,
   1033               "provider": "http://localhost:8088/"
   1034             }
   1035           ]
   1036         }
   1037       ]
   1038     }
   1039 
   1040 If the index given is invalid, the reducer will return an error response
   1041 instead of deleting a challenge.
   1042 
   1043 
   1044 **next** (from ``POLICIES_REVIEWING``):
   1045 
   1046 Using this transition, the user confirms that the policies in the current
   1047 state are acceptable. The transition does not take any arguments.
   1048 
   1049 The reducer will simply transition to the ``SECRET_EDITING`` state:
   1050 
   1051 .. code-block:: json
   1052 
   1053     {
   1054       "backup_state": "SECRET_EDITING",
   1055       "upload_fees" : [ { "fee": "KUDOS:42" } ],
   1056       "expiration" : { "t_ms" : 1245362362 }
   1057     }
   1058 
   1059 Here, ``upload_fees`` is an array of applicable upload fees for the
   1060 given policy expiration time. This is an array because fees could
   1061 be in different currencies.  The final cost may be lower if the
   1062 user already paid for some of the time.
   1063 
   1064 If the array of ``policies`` is currently empty, the reducer will
   1065 return an error response instead of allowing the user to continue.
   1066 
   1067 
   1068 **enter_secret:**
   1069 
   1070 This transition provides the reducer with the actual core ``secret`` of the user
   1071 that Anastasis is supposed to backup (and possibly recover). The argument is
   1072 simply the Crockford-Base32 encoded ``value`` together with its ``mime`` type, or a ``text`` field with a human-readable secret text.
   1073 For example:
   1074 
   1075 .. code-block:: javascript
   1076 
   1077     {
   1078       "secret": {
   1079          "value": "EDJP6WK5EG50",
   1080          "mime" : "text/plain"
   1081       },
   1082       "expiration" : { "t_ms" : 1245362362 }
   1083     }
   1084 
   1085 If the application is unaware of the format, it set the ``mime`` field to ``null``.
   1086 The ``expiration`` field is optional.
   1087 
   1088 The reducer remains in the ``SECRET_EDITING`` state, but now the secret and
   1089 updated expiration time are part of the state and the cost calculations will
   1090 be updated.
   1091 
   1092 .. code-block:: json
   1093 
   1094     {
   1095       "backup_state": "SECRET_EDITING",
   1096       "core_secret" : {
   1097          "value": "EDJP6WK5EG50",
   1098          "mime" : "text/plain"
   1099       },
   1100       "expiration" : { "t_ms" : 1245362362 },
   1101       "upload_fees" : [ { "fee": "KUDOS:42" } ]
   1102     }
   1103 
   1104 
   1105 **clear_secret:**
   1106 
   1107 This transition removes the core secret from the state.  It is simply a
   1108 convenience function to undo ``enter_secret`` without providing a new value
   1109 immediately. The transition takes no arguments.  The resuting state will no
   1110 longer have the ``core_secret`` field, and be otherwise unchanged. Calling
   1111 **clear_secret** on a state without a ``core_secret`` will result in an error.
   1112 
   1113 
   1114 **enter_secret_name:**
   1115 
   1116 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.
   1117 Applications that have built-in support for Anastasis MUST prefix the
   1118 secret name with an underscore and an application-specific identifier
   1119 registered in GANA so that they can use recognize their own backups.
   1120 An example argument would be:
   1121 
   1122 .. code-block:: javascript
   1123 
   1124     {
   1125       "name": "_TALERWALLET_MyPinePhone",
   1126     }
   1127 
   1128 Here, ``MyPinePhone`` might be chosen by the user to identify the
   1129 device that was being backed up.
   1130 
   1131 The reducer remains in the ``SECRET_EDITING`` state, but now the
   1132 secret name is updated:
   1133 
   1134 .. code-block:: json
   1135 
   1136     {
   1137       "secret_name" : "_TALERWALLET_MyPinePhone"
   1138     }
   1139 
   1140 
   1141 **update_expiration:**
   1142 
   1143 This transition asks the reducer to change the desired expiration time
   1144 and to update the associated cost. For example:
   1145 
   1146 .. code-block:: javascript
   1147 
   1148     {
   1149       "expiration" : { "t_ms" : 1245362362 }
   1150     }
   1151 
   1152 The reducer remains in the ``SECRET_EDITING`` state, but the
   1153 expiration time and cost calculation will be updated.
   1154 
   1155 .. code-block:: json
   1156 
   1157     {
   1158       "backup_state": "SECRET_EDITING",
   1159       "expiration" : { "t_ms" : 1245362362 },
   1160       "upload_fees" : [ { "fee": "KUDOS:43" } ]
   1161     }
   1162 
   1163 
   1164 **next** (from ``SECRET_EDITING``):
   1165 
   1166 Using this transition, the user confirms that the secret and expiration
   1167 settings in the current state are acceptable. The transition does not take any
   1168 arguments.
   1169 
   1170 If the secret is currently empty, the reducer will return an
   1171 error response instead of allowing the user to continue.
   1172 
   1173 After adding a secret, the reducer may transition into different states
   1174 depending on whether payment(s) are necessary.  If payments are needed, the
   1175 ``secret`` will be stored in the state under ``core_secret``.  Applications
   1176 should be careful when persisting the resulting state, as the ``core_secret``
   1177 is not protected in the ``PAYING`` states.  The ``PAYING`` states only differ
   1178 in terms of what the payments are for (key shares or the recovery document),
   1179 in all cases the state simply includes an array of Taler URIs that refer to
   1180 payments that need to be made with the Taler wallet.
   1181 
   1182 If all payments are complete, the reducer will transition into the
   1183 ``BACKUP_FINISHED`` state and (if applicable) delete the ``core_secret`` as an
   1184 additional safety measure.
   1185 
   1186 Example results are thus:
   1187 
   1188 .. code-block:: json
   1189 
   1190     {
   1191       "backup_state": "TRUTHS_PAYING",
   1192       "secret_name" : "$NAME",
   1193       "core_secret" : { "$anything":"$anything" },
   1194       "payments": [
   1195         "taler://pay/...",
   1196         "taler://pay/..."
   1197       ]
   1198     }
   1199 
   1200 .. code-block:: json
   1201 
   1202     {
   1203       "backup_state": "POLICIES_PAYING",
   1204       "secret_name" : "$NAME",
   1205       "core_secret" : { "$anything":"$anything" },
   1206       "payments": [
   1207         "taler://pay/...",
   1208         "taler://pay/..."
   1209       ]
   1210     }
   1211 
   1212 .. code-block:: json
   1213 
   1214     {
   1215       "backup_state": "BACKUP_FINISHED",
   1216       "success_details": {
   1217         "http://localhost:8080/" : {
   1218           "policy_version" : 1,
   1219           "policy_expiration" : { "t_ms" : 1245362362000 }
   1220         },
   1221         "http://localhost:8081/" : {
   1222           "policy_version" : 3,
   1223           "policy_expiration" : { "t_ms" : 1245362362000 }
   1224         }
   1225       }
   1226     }
   1227 
   1228 
   1229 **pay:**
   1230 
   1231 This transition suggests to the reducer that a payment may have been made or
   1232 is immanent, and that the reducer should check with the Anastasis service
   1233 provider to see if the operation is now possible.  The operation takes one
   1234 optional argument, which is a ``timeout`` value that specifies how long the
   1235 reducer may wait (in long polling) for the payment to complete:
   1236 
   1237 .. code-block:: json
   1238 
   1239     {
   1240       "timeout":  { "d_ms" : 5000 },
   1241     }
   1242 
   1243 The specified timeout is passed on to the Anastasis service provider(s), which
   1244 will wait this long before giving up.  If no timeout is given, the check is
   1245 done as quickly as possible without additional delays.  The reducer will continue
   1246 to either an updated state with the remaining payment requests, to the
   1247 ``BACKUP_FINISHED`` state (if all payments have been completed and the backup
   1248 finished), or return an error response in case there was an irrecoverable error,
   1249 indicating the specific provider and how it failed.  An example for this
   1250 final error state would be:
   1251 
   1252 .. code-block:: json
   1253 
   1254     {
   1255       "http_status" : 500,
   1256       "upload_status" : 52,
   1257       "provider_url" : "https://bad.example.com/",
   1258     }
   1259 
   1260 Here, the fields have the following meaning:
   1261 
   1262   - **http_status** is the HTTP status returned by the Anastasis provider.
   1263   - **upload_status** is the Taler error code return by the provider.
   1264   - **provider_url** is the base URL of the failing provider.
   1265 
   1266 In the above example, 52 would thus imply that the Anastasis provider failed to
   1267 store information into its database.
   1268 
   1269 
   1270 Recovery transitions
   1271 --------------------
   1272 
   1273 **enter_user_attributes:**
   1274 
   1275 This transition provides the user's personal attributes. The specific set of
   1276 attributes required depends on the country of residence of the user.  Some
   1277 attributes may be optional, in which case they should be omitted entirely
   1278 (that is, not simply be set to ``null`` or an empty string).  The
   1279 arguments are identical to the **enter_user_attributes** transition from
   1280 the backup process.  Example arguments would thus be:
   1281 
   1282 .. code-block:: json
   1283 
   1284     {
   1285       "identity_attributes": {
   1286         "full_name": "Max Musterman",
   1287         "social_security_number": "123456789",
   1288         "birthdate": "2000-01-01",
   1289         "birthplace": "Earth"
   1290       }
   1291     }
   1292 
   1293 Afterwards, the reducer transitions into the ``SECRET_SELECTING`` state:
   1294 
   1295 .. code-block:: json
   1296 
   1297     {
   1298       "recovery_state": "SECRET_SELECTING",
   1299       "identity_attributes": {
   1300         "full_name": "Max Musterman",
   1301         "social_security_number": "123456789",
   1302         "birthdate": "2000-01-01",
   1303         "birthplace": "Earth"
   1304       }
   1305     }
   1306 
   1307 Typically, the special policy discovery process (outside of the state
   1308 machine) is expected to be run in this state.  The discovery process
   1309 will use the state (and in particular the identity attributes and the
   1310 list of active providers) to discover a set of possible recovery
   1311 documents with their respective provider URLs, policy version and
   1312 identity attribute mask. An identity attribute mask is a bitmask that
   1313 describes which of the optional attributes from the identity
   1314 attributes should be omitted to recover this backup.  Once the user
   1315 has selected a backup providing this triplet, it is possible to
   1316 proceed using ``next``.
   1317 
   1318 Especially if the discovered policies are inadequate, it is again
   1319 possible to add providers using ``add_provider``.
   1320 
   1321 
   1322 **add_provider**:
   1323 
   1324 This operation can be performed in state ``SECRET_SELECTING``.  It
   1325 adds one additional Anastasis provider to the list of providers that
   1326 the discovery process should henceforth consider.  Note that removing
   1327 providers is not possible at this time.
   1328 
   1329 Here, the client must provide an object with the base URL of the
   1330 providers to add, for example:
   1331 
   1332 .. code-block:: json
   1333 
   1334     {
   1335       "provider_url" : "http://localhost:8088/"
   1336     }
   1337 
   1338 
   1339 **select_version**:
   1340 
   1341 Using the ``select_version`` transition in the ``SECRET_SELECTING`` state,
   1342 it is possible to trigger the download and decryption of a recovery
   1343 policy document. Here, the arguments specify which provider, version
   1344 and mask should be used to download the document:
   1345 
   1346 .. code-block:: json
   1347 
   1348     {
   1349       "providers" : [ {
   1350         "url": "https://localhost:8088/",
   1351         "version": 0
   1352       } ],
   1353       "attribute_mask": 0
   1354     }
   1355 
   1356 The reducer will attempt to retrieve the specified recovery document
   1357 from that provider.  If a recovery document was found, the reducer
   1358 will attempt to load it and transition to a state where the user can
   1359 choose which challenges to satisfy:
   1360 
   1361 .. code-block:: json
   1362 
   1363     {
   1364       "recovery_state": "CHALLENGE_SELECTING",
   1365       "recovery_information": {
   1366         "challenges": [
   1367           {
   1368             "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
   1369             "uuid-display": "MW2R3RC",
   1370             "type": "question",
   1371             "instructions": "q1"
   1372           },
   1373           {
   1374             "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1375             "uuid-display": "TXYKGE",
   1376             "type": "email",
   1377             "instructions": "e-mail address m?il@f*.bar"
   1378           },
   1379         ],
   1380         "policies": [
   1381           [
   1382             {
   1383               "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
   1384             },
   1385             {
   1386               "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
   1387             },
   1388           ],
   1389         ],
   1390         "provider_url": "http://localhost:8088/",
   1391         "version": 1,
   1392       },
   1393       "recovery_document": {
   1394         "...": "..."
   1395       }
   1396     }
   1397 
   1398 The ``recovery_document`` is an internal representation of the recovery
   1399 information and of no concern to the user interface. The pertinent information
   1400 is in the ``recovery_information``. Here, the ``challenges`` array is a list
   1401 of possible challenges the user could attempt to solve next, while ``policies``
   1402 is an array of policies, with each policy being an array of challenges.
   1403 Satisfying all of the challenges of one of the policies will enable the secret
   1404 to be recovered.  The ``provider_url`` from where the recovery document was
   1405 obtained and its ``version`` are also provided.  Each challenge comes with
   1406 four mandatory fields:
   1407 
   1408     - **uuid**: A unique identifier of the challenge; this is what the
   1409       UUIDs in the policies array refer to.
   1410     - **uuid-display**: Shortened idenfier which is included in messages
   1411       send to the user.  Allows the user to
   1412       distinguish different PIN/TANs should say the same phone number be
   1413       used for SMS-authentication with different providers.
   1414     - **type**: This is the type of the challenge, as a string.
   1415     - **instructions**: Contains additional important hints for the user
   1416       to allow the user to satisfy the challenge.  It typically includes
   1417       an abbreviated form of the contact information or the security
   1418       question. Details depend on ``type``.
   1419 
   1420 If a recovery document was not found, either the user never performed
   1421 a backup, entered incorrect attributes, or used a provider not yet in
   1422 the list of Anastasis providers.  Hence, the user must now either
   1423 select a different provider, or go ``back`` and update the identity
   1424 attributes.  In the case a recovery document was not found, the
   1425 transition fails, returning the error code and a human-readable error
   1426 message together with a transition failure:
   1427 
   1428 .. code-block:: json
   1429 
   1430     {
   1431       "error_message": "account unknown to Anastasis server",
   1432       "error_code": 9,
   1433     }
   1434 
   1435 Here, the ``error_code`` is from the ``enum ANASTASIS_RecoveryStatus``
   1436 and describes precisely what failed about the download, while the
   1437 ``error_message`` is a human-readable (English) explanation of the code.
   1438 Applications may want to translate the message using GNU gettext;
   1439 translations should be available in the ``anastasis`` text domain.
   1440 However, in general it should be sufficient to display the slightly
   1441 more generic Taler error code that is returned with the new state.
   1442 
   1443 
   1444 **sync_providers**
   1445 
   1446 The downloaded policy may include secrets from providers for which
   1447 we do not (yet) have the cost structure or even the salt. So here
   1448 an application can use the ``sync_providers`` request to download
   1449 ``/config`` from providers that are in the challenge list but not
   1450 yet known with their salt and other attributes in the provider list.
   1451 
   1452 The transition fails if all providers relevant for the selected
   1453 policy are already downloaded. Applications may either internally
   1454 check the state for this, or call ``sync_providers`` until it fails
   1455 with this error:
   1456 
   1457 .. code-block:: json
   1458 
   1459   {
   1460     "detail": "already in sync",
   1461     "code": 8400,
   1462     "hint": "The given action is invalid for the current state of the reducer."
   1463   }
   1464 
   1465 As providers may fail to respond, this action may need to be called
   1466 repeatedly. The action will block until progress is made on any provider.
   1467 As some providers may never respond, the application should disable
   1468 challenge buttons for challenges where providers are down.  However,
   1469 users should be able to solve challenges where the provider is up while
   1470 the reducer is polling for ``/config`` in the background.
   1471 
   1472 
   1473 **select_challenge:**
   1474 
   1475 Selecting a challenge takes different, depending on the state of the payment.
   1476 A comprehensive example for ``select_challenge`` would be:
   1477 
   1478 .. code-block:: json
   1479 
   1480     {
   1481         "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
   1482         "timeout" : { "d_ms" : 5000 },
   1483         "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
   1484     }
   1485 
   1486 The ``uuid`` field is mandatory and specifies the selected challenge.
   1487 The other fields are optional, and are needed in case the user has
   1488 previously been requested to pay for the challenge.  In this case,
   1489 the ``payment_secret`` identifies the previous payment request, and
   1490 ``timeout`` says how long the Anastasis service should wait for the
   1491 payment to be completed before giving up (long polling).
   1492 
   1493 Depending on the type of the challenge and the need for payment, the
   1494 reducer may transition into ``CHALLENGE_SOLVING`` or ``CHALLENGE_PAYING``
   1495 states.  In ``CHALLENGE_SOLVING``, the new state will primarily specify
   1496 the selected challenge:
   1497 
   1498 .. code-block:: json
   1499 
   1500     {
   1501       "backup_state": "CHALLENGE_SOLVING",
   1502       "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
   1503     }
   1504 
   1505 In ``CHALLENGE_PAYING``, the new state will include instructions for payment
   1506 in the ``challenge_feedback``. In general, ``challenge_feedback`` includes
   1507 information about attempted challenges, with the final state being ``solved``:
   1508 
   1509 .. code-block:: json
   1510 
   1511     {
   1512       "recovery_state": "CHALLENGE_SELECTING",
   1513       "recovery_information": {
   1514         "...": "..."
   1515       }
   1516       "challenge_feedback": {
   1517         "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
   1518           "state" : "solved"
   1519         }
   1520       }
   1521     }
   1522 
   1523 Challenges feedback for a challenge can have many different ``state`` values
   1524 that applications must all handle. States other than ``solved`` are:
   1525 
   1526 - **payment**: Here, the user must pay for a challenge. An example would be:
   1527 
   1528   .. code-block:: json
   1529 
   1530      {
   1531        "backup_state": "CHALLENGE_PAYING",
   1532        "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
   1533        "challenge_feedback": {
   1534          "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
   1535           "state" : "payment",
   1536           "taler_pay_uri" : "taler://pay/...",
   1537           "provider" : "https://localhost:8080/",
   1538           "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
   1539          }
   1540        }
   1541      }
   1542 
   1543 - **body**: Here, the server provided an HTTP reply for
   1544   how to solve the challenge, but the reducer could not parse
   1545   them into a known format. A mime-type may be provided and may
   1546   help parse the details.
   1547 
   1548   .. code-block:: json
   1549 
   1550      {
   1551        "recovery_state": "CHALLENGE_SOLVING",
   1552        "recovery_information": {
   1553            "...": "..."
   1554        }
   1555        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1556        "challenge_feedback": {
   1557          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1558            "state": "body",
   1559            "body": "CROCKFORDBASE32ENCODEDBODY",
   1560            "http_status": 403,
   1561            "mime_type" : "anything/possible"
   1562          }
   1563        }
   1564      }
   1565 
   1566 - **hint**: Here, the server provided human-readable hint for
   1567   how to solve the challenge.  Note that the ``hint`` provided this
   1568   time is from the Anastasis provider and may differ from the ``instructions``
   1569   for the challenge under ``recovery_information``:
   1570 
   1571   .. code-block:: json
   1572 
   1573      {
   1574        "recovery_state": "CHALLENGE_SOLVING",
   1575        "recovery_information": {
   1576            "...": "..."
   1577        }
   1578        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1579        "challenge_feedback": {
   1580          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1581            "state": "hint",
   1582            "hint": "Recovery TAN send to email mail@DOMAIN",
   1583            "http_status": 403
   1584          }
   1585        }
   1586      }
   1587 
   1588 - **details**: Here, the server provided a detailed JSON status response
   1589   related to solving the challenge:
   1590 
   1591   .. code-block:: json
   1592 
   1593     {
   1594       "recovery_state": "CHALLENGE_SOLVING",
   1595       "recovery_information": {
   1596          "...": "..."
   1597       }
   1598       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1599       "challenge_feedback": {
   1600         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1601           "state": "details",
   1602           "details": {
   1603             "code": 8111,
   1604             "hint": "The client's response to the challenge was invalid.",
   1605             "detail" : null
   1606           },
   1607           "http_status": 403
   1608         }
   1609       }
   1610     }
   1611 
   1612 - **redirect**: To solve the challenge, the user must visit the indicated
   1613   Web site at ``redirect_url``, for example to perform video authentication:
   1614 
   1615   .. code-block:: json
   1616 
   1617      {
   1618        "recovery_state": "CHALLENGE_SOLVING",
   1619        "recovery_information": {
   1620           "...": "..."
   1621        }
   1622        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1623        "challenge_feedback": {
   1624          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1625            "state": "redirect",
   1626            "redirect_url": "https://videoconf.example.com/",
   1627            "http_status": 303
   1628          }
   1629        }
   1630      }
   1631 
   1632 - **server-failure**: This indicates that the Anastasis provider encountered
   1633   a failure and recovery using this challenge cannot proceed at this time.
   1634   Examples for failures might be that the provider is unable to send SMS
   1635   messages at this time due to an outage.  The body includes details about
   1636   the failure. The user may try again later or continue with other challenges.
   1637 
   1638   .. code-block:: json
   1639 
   1640     {
   1641       "recovery_state": "CHALLENGE_SELECTING",
   1642       "recovery_information": {
   1643           "...": "..."
   1644       }
   1645       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1646       "challenge_feedback": {
   1647         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1648          "state": "server-failure",
   1649          "http_status": "500",
   1650          "error_code": 52
   1651        }
   1652      }
   1653    }
   1654 
   1655 - **truth-unknown**: This indicates that the Anastasis provider is unaware of
   1656   the specified challenge. This is typically a permanent failure, and user
   1657   interfaces should not allow users to re-try this challenge.
   1658 
   1659   .. code-block:: json
   1660 
   1661     {
   1662       "recovery_state": "CHALLENGE_SELECTING",
   1663       "recovery_information": {
   1664           "...": "..."
   1665       }
   1666       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1667       "challenge_feedback": {
   1668         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1669           "state": "truth-unknown",
   1670           "error_code": 8108
   1671         }
   1672       }
   1673     }
   1674 
   1675 - **rate-limit-exceeded**: This indicates that the user has made too many invalid attempts in too short an amount of time.
   1676 
   1677   .. code-block:: json
   1678 
   1679      {
   1680        "recovery_state": "CHALLENGE_SELECTING",
   1681        "recovery_information": {
   1682            "...": "..."
   1683        }
   1684        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1685        "challenge_feedback": {
   1686          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1687            "state": "rate-limit-exceeded",
   1688            "error_code": 8121
   1689          }
   1690        }
   1691      }
   1692 
   1693 - **authentication-timeout**: This indicates that the challenge is awaiting for some external authentication process to complete. The application should ``poll`` for it to complete, or proceed with selecting other challenges.
   1694 
   1695   .. code-block:: json
   1696 
   1697      {
   1698        "recovery_state": "CHALLENGE_SELECTING",
   1699        "recovery_information": {
   1700            "...": "..."
   1701        }
   1702        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1703        "challenge_feedback": {
   1704          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1705            "state": "authentication-timeout",
   1706            "error_code": 8122
   1707          }
   1708        }
   1709      }
   1710 
   1711 - **external-instructions**: This indicates that the challenge requires the user to perform some authentication method-specific actions. Details about what the user should do are provided.
   1712 
   1713   .. code-block:: json
   1714 
   1715      {
   1716        "recovery_state": "CHALLENGE_SELECTING",
   1717        "recovery_information": {
   1718            "...": "..."
   1719        }
   1720        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1721        "challenge_feedback": {
   1722          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1723            "state": "external-instructions",
   1724            "method": "iban",
   1725            "async": true, // optional
   1726            "answer_code": 987654321, // optional
   1727            "details": {
   1728              "...": "..."
   1729            }
   1730          }
   1731        }
   1732      }
   1733 
   1734   If "async" is "true", then the client should
   1735   poll for the challenge being satisfied using
   1736   the "answer_code" that has been provided.
   1737 
   1738   The specific instructions on how to satisfy
   1739   the challenge depend on the ``method``.
   1740   They include:
   1741 
   1742   - **iban**: The user must perform a wire transfer from their account to the Anastasis provider.
   1743 
   1744     .. code-block:: json
   1745 
   1746       {
   1747         "challenge_amount": "EUR:1",
   1748         "credit_iban": "DE12345789000",
   1749         "business_name": "Data Loss Incorporated",
   1750         "wire_transfer_subject": "Anastasis 987654321"
   1751       }
   1752 
   1753     Note that the actual wire transfer subject must contain both
   1754     the numeric ``answer_code`` as well as
   1755     the string ``Anastasis``.
   1756 
   1757 **poll:**
   1758 
   1759 With a ``poll`` transition, the application indicates that it wants to wait longer for one or more of the challenges that are awaiting some external authentication (state ``external-instructions``) or experienced some kind of timeout (state ``authentication-timeout``) to possibly complete.  While technically optional, the ``timeout`` argument should really be provided to enable long-polling, for example:
   1760 
   1761 .. code-block:: json
   1762 
   1763     {
   1764         "timeout" : { "d_ms" : 5000 },
   1765     }
   1766 
   1767 
   1768 **pay:**
   1769 
   1770 With a ``pay`` transition, the application indicates to the reducer that
   1771 a payment may have been made. Here, it is again possible to specify an
   1772 optional ``timeout`` argument for long-polling, for example:
   1773 
   1774 .. code-block:: json
   1775 
   1776     {
   1777         "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
   1778         "timeout" : { "d_ms" : 5000 },
   1779     }
   1780 
   1781 Depending on the type of the challenge and the result of the operation, the
   1782 new state may be ``CHALLENGE_SOLVING`` (if say the SMS was now sent to the
   1783 user), ``CHALLENGE_SELECTING`` (if the answer to the security question was
   1784 correct), ``RECOVERY_FINISHED`` (if this was the last challenge that needed to
   1785 be solved) or still ``CHALLENGE_PAYING`` (if the challenge was not actually
   1786 paid for).  For sample messages, see the different types of
   1787 ``challenge_feedback`` in the section about ``select_challenge``.
   1788 
   1789 
   1790 **solve_challenge:**
   1791 
   1792 Solving a challenge takes various formats, depending on the type of the
   1793 challenge and what is known about the answer.  The different supported
   1794 formats are:
   1795 
   1796 .. code-block:: json
   1797 
   1798     {
   1799         "answer": "answer to security question"
   1800     }
   1801 
   1802 .. code-block:: json
   1803 
   1804     {
   1805         "pin": 1234
   1806     }
   1807 
   1808 .. code-block:: json
   1809 
   1810     {
   1811         "hash": "SOMEBASE32ENCODEDHASHVALUE"
   1812     }