anastasis

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

reducer.rst (57878B)


      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           "truth_lifetime": { "d_ms" : 50000000 },
    413           "storage_limit_in_megabytes": 1,
    414           "provider_name": "Anastasis 4",
    415           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    416         },
    417         "http://localhost:8088/": {
    418           "http_status": 200,
    419           "methods": [
    420             { "type" : "question",
    421               "usage_fee" : "EUR:0.01" },
    422             { "type" : "sms",
    423               "usage_fee" : "EUR:0.55" }
    424           ],
    425           "annual_fee": "EUR:0.99",
    426           "truth_upload_fee": "EUR:3.99",
    427           "liability_limit": "EUR:1",
    428           "currency": "EUR",
    429           "truth_lifetime": { "d_ms" : 50000000 },
    430           "storage_limit_in_megabytes": 1,
    431           "provider_name": "Anastasis 4",
    432           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    433         }
    434       }
    435     }
    436 
    437 The array of ``required_attributes`` contains attributes about the user
    438 that must be provided includes:
    439 
    440   - **type**: The type of the attribute, for now only ``string`` and ``date`` are
    441     supported.
    442   - **name**: The name of the attribute, this is the key under which the
    443     attribute value must be provided later. The name must be unique per response.
    444   - **label**: A human-readable description of the attribute in English.
    445     Translated descriptions may be provided under **label_i18n**.
    446   - **uuid**: A UUID that uniquely identifies identical attributes across
    447     different countries. Useful to preserve values should the user enter
    448     some attributes, and then switch to another country.  Note that
    449     attributes must not be preserved if they merely have the same **name**,
    450     only the **uuid** will be identical if the semantics is identical.
    451   - **widget**: An optional name of a widget that is known to nicely render
    452     the attribute entry in user interfaces where named widgets are
    453     supported.
    454   - **validation-regex**: An optional extended POSIX regular expression
    455     that is to be used to validate (string) inputs to ensure they are
    456     well-formed.
    457   - **validation-logic**: Optional name of a function that should be called
    458     to validate the input.  If the function is not known to the particular
    459     client, the respective validation can be skipped (at the expense of
    460     typos by users not being detected, possibly rendering secrets
    461     irrecoverable).
    462   - **optional**: Optional boolean field that, if ``true``, indicates that
    463     this attribute is not actually required but optional and users MAY leave
    464     it blank in case they do not have the requested information. Used for
    465     common fields that apply to some large part of the population but are
    466     not sufficiently universal to be actually required.
    467 
    468 The authentication providers are listed under a key that is the
    469 base URL of the service. For each provider, the following
    470 information is provided if the provider was successfully contacted:
    471 
    472   - **http_status**: HTTP status code, always ``200`` on success.
    473   - **methods**: Array of authentication methods supported by this
    474     provider. Includes the **type** of the authentication method
    475     and the **usage_fee** (how much the user must pay for authorization
    476     using this method during recovery).
    477   - **annual_fee**: Fee the provider charges to store the recovery
    478     policy for one year.
    479   - **truth_upload_fee**: Fee the provider charges to store a key share.
    480   - **liability_limit**: Amount the provider can be held liable for in
    481     case a key share or recovery document cannot be recovered due to
    482     provider failures.
    483   - **currency**: Currency in which the provider wants to be paid,
    484     will match all of the fees.
    485   - **storage_limit_in_megabytes**: Maximum size of an upload (for
    486     both recovery document and truth data) in megabytes.
    487   - **provider_name**: Human-readable name of the provider's business.
    488   - **salt**: Salt value used by the provider, used to derive the
    489     user's identity at this provider. Should be unique per provider,
    490     and must never change for a given provider.  The salt is
    491     base32 encoded.
    492 
    493 If contacting the provider failed, the information returned is:
    494 
    495   - **http_status**: HTTP status code (if available, possibly 0 if
    496     we did not even obtain an HTTP response).
    497   - **error_code**: Taler error code, never 0.
    498 
    499 
    500 **add_provider**:
    501 
    502 This operation can be performed in state ``USER_ATTRIBUTES_COLLECTING``.
    503 It
    504 adds one or more Anastasis providers to the list of providers the reducer
    505 should henceforth consider.  Note that removing providers is not possible at
    506 this time.
    507 
    508 Here, the client must provide an object with the base URLs of the
    509 providers to add or disable. The object maps the
    510 URLs to status information about the provider to
    511 use. For example:
    512 
    513 .. code-block:: json
    514 
    515     {
    516       "http://localhost:8088/" : { "disabled" : false },
    517       "http://localhost:8089/" : { "disabled" : false },
    518       "http://localhost:8090/" : { "disabled" : true }
    519     }
    520 
    521 Note that existing providers will remain in the state they were in.  The following is an
    522 example for an expected new state where the service on port 8089 is
    523 unreachable, the services on port 8088 and 8888 were previously known, and service on
    524 port 8088 was now added, and on 8090 is disabled:
    525 
    526 .. code-block:: json
    527 
    528     {
    529       "backup_state": "USER_ATTRIBUTES_COLLECTING",
    530       "authentication_providers": {
    531         "http://localhost:8089/": {
    532           "disabled": false,
    533           "error_code": 11,
    534           "http_status": 0
    535         },
    536         "http://localhost:8090/": {
    537           "disabled": true
    538         },
    539         "http://localhost:8088/": {
    540           "disabled": false,
    541           "http_status": 200,
    542           "methods": [
    543             { "type" : "question",
    544               "usage_fee" : "EUR:0.01" },
    545             { "type" : "sms",
    546               "usage_fee" : "EUR:0.55" }
    547           ],
    548           "annual_fee": "EUR:0.99",
    549           "truth_upload_fee": "EUR:3.99",
    550           "liability_limit": "EUR:1",
    551           "currency": "EUR",
    552           "truth_lifetime": { "d_ms" : 50000000 },
    553           "storage_limit_in_megabytes": 1,
    554           "provider_name": "Anastasis 4",
    555           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
    556         }
    557         "http://localhost:8888/": {
    558           "methods": [
    559             { "type" : "question",
    560               "usage_fee" : "EUR:0.01" },
    561             { "type" : "sms",
    562               "usage_fee" : "EUR:0.55" }
    563           ],
    564           "annual_fee": "EUR:0.99",
    565           "truth_upload_fee": "EUR:3.99",
    566           "liability_limit": "EUR:1",
    567           "currency": "EUR",
    568           "truth_lifetime": { "d_ms" : 50000000 },
    569           "storage_limit_in_megabytes": 1,
    570           "provider_name": "Anastasis 42",
    571           "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
    572         }
    573       }
    574     }
    575 
    576 
    577 
    578 Backup transitions
    579 ------------------
    580 
    581 **enter_user_attributes:**
    582 
    583 This transition provides the user's personal attributes. The specific set of
    584 attributes required depends on the country of residence of the user.  Some
    585 attributes may be optional, in which case they should be omitted entirely
    586 (that is, not simply be set to ``null`` or an empty string).  Example
    587 arguments would be:
    588 
    589 .. code-block:: json
    590 
    591     {
    592       "identity_attributes": {
    593         "full_name": "Max Musterman",
    594         "social_security_number": "123456789",
    595         "birthdate": "2000-01-01",
    596         "birthplace": "Earth"
    597      }
    598     }
    599 
    600 Note that at this stage, the state machines between backup and
    601 recovery diverge and the ``recovery_state`` will begin to look
    602 very different from the ``backup_state``.
    603 
    604 For backups, if all required attributes are present, the reducer will
    605 transition to an ``AUTHENTICATIONS_EDITING`` state with the attributes added
    606 to it:
    607 
    608 .. code-block:: json
    609 
    610     {
    611       "backup_state": "AUTHENTICATIONS_EDITING",
    612       "identity_attributes": {
    613         "full_name": "Max Musterman",
    614         "social_security_number": "123456789",
    615         "birthdate": "2000-01-01",
    616         "birthplace": "Earth"
    617       }
    618     }
    619 
    620 If required attributes are missing, do not match the required regular
    621 expression, or fail the custom validation logic, the reducer SHOULD return an
    622 error response indicating that the transition has failed and what is wrong about
    623 the input and not transition to a new state.  A reducer that does not support
    624 some specific validation logic MAY accept the invalid input and proceed anyway.
    625 The error state will include a Taler error code that is specific to the
    626 failure, and optional details.
    627 
    628 Example:
    629 
    630 .. code-block:: json
    631 
    632     {
    633       "code": 8404,
    634       "hint": "An input did not match the regular expression.",
    635       "detail": "social_security_number"
    636     }
    637 
    638 Clients may safely repeat this transition to validate the user's inputs
    639 until they satisfy all of the constraints.  This way, the user interface
    640 does not have to perform the input validation directly.
    641 
    642 
    643 **add_authentication**:
    644 
    645 This transition adds an authentication method.  The method must be supported
    646 by one or more providers that are included in the current state.  Adding an
    647 authentication method requires specifying the ``type`` and ``instructions`` to
    648 be given to the user.  The ``challenge`` is encrypted and stored at the
    649 Anastasis provider. The specific semantics of the value depend on the
    650 ``type``.  Typical challenges values are a phone number (to send an SMS to),
    651 an e-mail address (to send a PIN code to) or the answer to a security
    652 question.  Note that these challenge values will still be encrypted (and
    653 possibly hashed) before being given to the Anastasis providers.
    654 
    655 Note that the ``challenge`` must be given in Crockford Base32 encoding, as it
    656 MAY include binary data (such as a photograph of the user).  In the latter
    657 case, the optional ``mime_type`` field must be provided to give the MIME type
    658 of the value encoded in ``challenge``.
    659 
    660 .. code-block:: json
    661 
    662     {
    663       "authentication_method":
    664       {
    665         "type": "question",
    666         "mime_type" : "text/plain",
    667         "instructions" : "What is your favorite GNU package?",
    668         "challenge" : "E1QPPS8A",
    669       }
    670     }
    671 
    672 If the information provided is valid, the reducer will add the new
    673 authentication method to the array of authentication methods:
    674 
    675 .. code-block:: json
    676 
    677     {
    678       "backup_state": "AUTHENTICATIONS_EDITING",
    679       "authentication_methods": [
    680         {
    681           "type": "question",
    682           "mime_type" : "text/plain",
    683           "instructions" : "What is your favorite GNU package?",
    684           "challenge" : "E1QPPS8A",
    685         },
    686         {
    687           "type": "email",
    688           "instructions" : "E-mail to user@*le.com",
    689           "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
    690         }
    691       ]
    692     }
    693 
    694 
    695 **delete_authentication**:
    696 
    697 This transition can be used to remove an authentication method from the
    698 array of authentication methods. It simply requires the index of the
    699 authentication method to remove. Note that the array is 0-indexed:
    700 
    701 .. code-block:: json
    702 
    703     {
    704       "authentication_method": 1
    705     }
    706 
    707 Assuming we begin with the state from the example above, this would
    708 remove the ``email`` authentication method, resulting in the following
    709 response:
    710 
    711 .. code-block:: json
    712 
    713     {
    714       "backup_state": "AUTHENTICATIONS_EDITING",
    715       "authentication_methods": [
    716         {
    717           "type": "question",
    718           "mime_type" : "text/plain",
    719           "instructions" : "What is your favorite GNU package?",
    720           "challenge" : "gdb",
    721         }
    722       ]
    723     }
    724 
    725 If the index is invalid, the reducer will return an error
    726 response instead of making a transition.
    727 
    728 
    729 **next** (from ``AUTHENTICATIONS_EDITING``):
    730 
    731 This transition confirms that the user has finished adding (or removing)
    732 authentication methods, and that the system should now automatically compute
    733 a set of reasonable recovery policies.
    734 
    735 This transition does not take any mandatory arguments.  Optional arguments can
    736 be provided to upload the recovery document only to a specific subset of the
    737 providers:
    738 
    739 .. code-block:: json
    740 
    741     {
    742       "providers": [
    743         "http://localhost:8088/",
    744         "http://localhost:8089/"
    745       ]
    746     }
    747 
    748 The resulting state provides the suggested recovery policies in a way suitable
    749 for presentation to the user:
    750 
    751 .. code-block:: javascript
    752 
    753     {
    754       "backup_state": "POLICIES_REVIEWING",
    755       "policy_providers" : [
    756           { "provider_url" : "http://localhost:8088/" },
    757           { "provider_url" : "http://localhost:8089/" }
    758       ],
    759       "policies": [
    760         {
    761           "methods": [
    762             {
    763               "authentication_method": 0,
    764               "provider": "http://localhost:8088/"
    765             },
    766             {
    767               "authentication_method": 1,
    768               "provider": "http://localhost:8089/"
    769             },
    770             {
    771               "authentication_method": 2,
    772               "provider": "http://localhost:8087/"
    773             }
    774           ]
    775         },
    776         {
    777           "methods": [
    778             {
    779               "authentication_method": 0,
    780               "provider": "http://localhost:8088/"
    781             },
    782             {
    783               "authentication_method": 1,
    784               "provider": "http://localhost:8089/"
    785             },
    786             {
    787               "authentication_method": 3,
    788               "provider": "http://localhost:8089/"
    789             }
    790           ]
    791         }
    792       ]
    793     }
    794 
    795 For each recovery policy, the state includes the specific details of which
    796 authentication ``methods`` must be solved to recovery the secret using this
    797 policy.  The ``methods`` array specifies the index of the
    798 ``authentication_method`` in the ``authentication_methods`` array, as well as
    799 the provider that was selected to supervise this authentication.
    800 
    801 If no authentication method was provided, the reducer will
    802 return an error response instead of making a transition.
    803 
    804 
    805 **add_policy**:
    806 
    807 Using this transition, the user can add an additional recovery policy to the
    808 state.  The argument format is the same that is used in the existing state.
    809 An example for a possible argument would thus be:
    810 
    811 .. code-block:: javascript
    812 
    813     {
    814       "policy": [
    815         {
    816           "authentication_method": 1,
    817           "provider": "http://localhost:8088/"
    818         },
    819         {
    820           "authentication_method": 3,
    821           "provider": "http://localhost:8089/"
    822         }
    823       ]
    824     }
    825 
    826 Note that the specified providers must already be in the
    827 ``authentication_providers`` of the state. You cannot add new providers at
    828 this stage.  The reducer will simply attempt to append the suggested policy to
    829 the "policies" array, returning an updated state:
    830 
    831 .. code-block:: json
    832 
    833     {
    834       "backup_state": "POLICIES_REVIEWING",
    835       "policies": [
    836         {
    837           "methods": [
    838             {
    839               "authentication_method": 0,
    840               "provider": "http://localhost:8089/"
    841             },
    842             {
    843               "authentication_method": 1,
    844               "provider": "http://localhost:8088/"
    845             }
    846           ]
    847         },
    848         {
    849           "methods": [
    850             {
    851               "authentication_method": 0,
    852               "provider": "http://localhost:8089/"
    853             },
    854             {
    855               "authentication_method": 2,
    856               "provider": "http://localhost:8088/"
    857             }
    858           ]
    859         },
    860         {
    861           "methods": [
    862             {
    863               "authentication_method": 1,
    864               "provider": "http://localhost:8089/"
    865             },
    866             {
    867               "authentication_method": 2,
    868               "provider": "http://localhost:8088/"
    869             }
    870           ]
    871         },
    872         {
    873           "methods": [
    874             {
    875               "authentication_method": 1,
    876               "provider": "http://localhost:8088/"
    877             },
    878             {
    879               "authentication_method": 3,
    880               "provider": "http://localhost:8089/"
    881             }
    882           ]
    883         }
    884       ]
    885     }
    886 
    887 If the new policy is invalid, for example because it adds an unknown
    888 authentication method, or the selected provider does not support the type of
    889 authentication, the reducer return an error response instead of
    890 adding the new policy.
    891 
    892 
    893 **update_policy**:
    894 
    895 Using this transition, the user can modify an existing recovery policy
    896 in the state.
    897 The argument format is the same that is used in **add_policy**,
    898 except there is an additional key ``policy_index`` which
    899 identifies the policy to modify.
    900 An example for a possible argument would thus be:
    901 
    902 .. code-block:: javascript
    903 
    904     {
    905       "policy_index" : 1,
    906       "policy": [
    907         {
    908           "authentication_method": 1,
    909           "provider": "http://localhost:8088/"
    910         },
    911         {
    912           "authentication_method": 3,
    913           "provider": "http://localhost:8089/"
    914         }
    915       ]
    916     }
    917 
    918 If the new policy is invalid, for example because it adds an unknown
    919 authentication method, or the selected provider does not support the type of
    920 authentication, the reducer will return an error response instead of
    921 modifying the policy.
    922 
    923 
    924 
    925 **delete_policy:**
    926 
    927 This transition allows the deletion of a recovery policy. The argument
    928 simply specifies the index of the policy to delete, for example:
    929 
    930 .. code-block:: json
    931 
    932     {
    933       "policy_index": 3
    934     }
    935 
    936 Given as input the state from the example above, the expected new state would
    937 be:
    938 
    939 .. code-block:: json
    940 
    941     {
    942       "backup_state": "POLICIES_REVIEWING",
    943       "policies": [
    944         {
    945           "methods": [
    946             {
    947               "authentication_method": 0,
    948               "provider": "http://localhost:8089/"
    949             },
    950             {
    951               "authentication_method": 1,
    952               "provider": "http://localhost:8088/"
    953             }
    954           ]
    955         },
    956         {
    957           "methods": [
    958             {
    959               "authentication_method": 0,
    960               "provider": "http://localhost:8089/"
    961             },
    962             {
    963               "authentication_method": 2,
    964               "provider": "http://localhost:8088/"
    965             }
    966           ]
    967         },
    968         {
    969           "methods": [
    970             {
    971               "authentication_method": 1,
    972               "provider": "http://localhost:8089/"
    973             },
    974             {
    975               "authentication_method": 2,
    976               "provider": "http://localhost:8088/"
    977             }
    978           ]
    979         }
    980       ]
    981     }
    982 
    983 If the index given is invalid, the reducer will return an error response
    984 instead of deleting a policy.
    985 
    986 
    987 **delete_challenge:**
    988 
    989 This transition allows the deletion of an individual
    990 challenge from a recovery policy. The argument
    991 simply specifies the index of the policy and challenge
    992 to delete, for example:
    993 
    994 .. code-block:: json
    995 
    996     {
    997       "policy_index": 1,
    998       "challenge_index" : 1
    999     }
   1000 
   1001 Given as input the state from the example above, the expected new state would
   1002 be:
   1003 
   1004 .. code-block:: json
   1005 
   1006     {
   1007       "backup_state": "POLICIES_REVIEWING",
   1008       "policies": [
   1009         {
   1010           "methods": [
   1011             {
   1012               "authentication_method": 0,
   1013               "provider": "http://localhost:8089/"
   1014             },
   1015             {
   1016               "authentication_method": 1,
   1017               "provider": "http://localhost:8088/"
   1018             }
   1019           ]
   1020         },
   1021         {
   1022           "methods": [
   1023             {
   1024               "authentication_method": 0,
   1025               "provider": "http://localhost:8089/"
   1026             }
   1027           ]
   1028         },
   1029         {
   1030           "methods": [
   1031             {
   1032               "authentication_method": 1,
   1033               "provider": "http://localhost:8089/"
   1034             },
   1035             {
   1036               "authentication_method": 2,
   1037               "provider": "http://localhost:8088/"
   1038             }
   1039           ]
   1040         }
   1041       ]
   1042     }
   1043 
   1044 If the index given is invalid, the reducer will return an error response
   1045 instead of deleting a challenge.
   1046 
   1047 
   1048 **next** (from ``POLICIES_REVIEWING``):
   1049 
   1050 Using this transition, the user confirms that the policies in the current
   1051 state are acceptable. The transition does not take any arguments.
   1052 
   1053 The reducer will simply transition to the ``SECRET_EDITING`` state:
   1054 
   1055 .. code-block:: json
   1056 
   1057     {
   1058       "backup_state": "SECRET_EDITING",
   1059       "upload_fees" : [ { "fee": "KUDOS:42" } ],
   1060       "expiration" : { "t_ms" : 1245362362 }
   1061     }
   1062 
   1063 Here, ``upload_fees`` is an array of applicable upload fees for the
   1064 given policy expiration time. This is an array because fees could
   1065 be in different currencies.  The final cost may be lower if the
   1066 user already paid for some of the time.
   1067 
   1068 If the array of ``policies`` is currently empty, the reducer will
   1069 return an error response instead of allowing the user to continue.
   1070 
   1071 
   1072 **enter_secret:**
   1073 
   1074 This transition provides the reducer with the actual core ``secret`` of the user
   1075 that Anastasis is supposed to backup (and possibly recover). The argument is
   1076 simply the Crockford-Base32 encoded ``value`` together with its ``mime`` type, or a ``text`` field with a human-readable secret text.
   1077 For example:
   1078 
   1079 .. code-block:: javascript
   1080 
   1081     {
   1082       "secret": {
   1083          "value": "EDJP6WK5EG50",
   1084          "mime" : "text/plain"
   1085       },
   1086       "expiration" : { "t_ms" : 1245362362 }
   1087     }
   1088 
   1089 If the application is unaware of the format, it set the ``mime`` field to ``null``.
   1090 The ``expiration`` field is optional.
   1091 
   1092 The reducer remains in the ``SECRET_EDITING`` state, but now the secret and
   1093 updated expiration time are part of the state and the cost calculations will
   1094 be updated.
   1095 
   1096 .. code-block:: json
   1097 
   1098     {
   1099       "backup_state": "SECRET_EDITING",
   1100       "core_secret" : {
   1101          "value": "EDJP6WK5EG50",
   1102          "mime" : "text/plain"
   1103       },
   1104       "expiration" : { "t_ms" : 1245362362 },
   1105       "upload_fees" : [ { "fee": "KUDOS:42" } ]
   1106     }
   1107 
   1108 
   1109 **clear_secret:**
   1110 
   1111 This transition removes the core secret from the state.  It is simply a
   1112 convenience function to undo ``enter_secret`` without providing a new value
   1113 immediately. The transition takes no arguments.  The resuting state will no
   1114 longer have the ``core_secret`` field, and be otherwise unchanged. Calling
   1115 **clear_secret** on a state without a ``core_secret`` will result in an error.
   1116 
   1117 
   1118 **enter_secret_name:**
   1119 
   1120 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.
   1121 Applications that have built-in support for Anastasis MUST prefix the
   1122 secret name with an underscore and an application-specific identifier
   1123 registered in GANA so that they can use recognize their own backups.
   1124 An example argument would be:
   1125 
   1126 .. code-block:: javascript
   1127 
   1128     {
   1129       "name": "_TALERWALLET_MyPinePhone",
   1130     }
   1131 
   1132 Here, ``MyPinePhone`` might be chosen by the user to identify the
   1133 device that was being backed up.
   1134 
   1135 The reducer remains in the ``SECRET_EDITING`` state, but now the
   1136 secret name is updated:
   1137 
   1138 .. code-block:: json
   1139 
   1140     {
   1141       "secret_name" : "_TALERWALLET_MyPinePhone"
   1142     }
   1143 
   1144 
   1145 **update_expiration:**
   1146 
   1147 This transition asks the reducer to change the desired expiration time
   1148 and to update the associated cost. For example:
   1149 
   1150 .. code-block:: javascript
   1151 
   1152     {
   1153       "expiration" : { "t_ms" : 1245362362 }
   1154     }
   1155 
   1156 The reducer remains in the ``SECRET_EDITING`` state, but the
   1157 expiration time and cost calculation will be updated.
   1158 
   1159 .. code-block:: json
   1160 
   1161     {
   1162       "backup_state": "SECRET_EDITING",
   1163       "expiration" : { "t_ms" : 1245362362 },
   1164       "upload_fees" : [ { "fee": "KUDOS:43" } ]
   1165     }
   1166 
   1167 
   1168 **next** (from ``SECRET_EDITING``):
   1169 
   1170 Using this transition, the user confirms that the secret and expiration
   1171 settings in the current state are acceptable. The transition does not take any
   1172 arguments.
   1173 
   1174 If the secret is currently empty, the reducer will return an
   1175 error response instead of allowing the user to continue.
   1176 
   1177 After adding a secret, the reducer may transition into different states
   1178 depending on whether payment(s) are necessary.  If payments are needed, the
   1179 ``secret`` will be stored in the state under ``core_secret``.  Applications
   1180 should be careful when persisting the resulting state, as the ``core_secret``
   1181 is not protected in the ``PAYING`` states.  The ``PAYING`` states only differ
   1182 in terms of what the payments are for (key shares or the recovery document),
   1183 in all cases the state simply includes an array of Taler URIs that refer to
   1184 payments that need to be made with the Taler wallet.
   1185 
   1186 If all payments are complete, the reducer will transition into the
   1187 ``BACKUP_FINISHED`` state and (if applicable) delete the ``core_secret`` as an
   1188 additional safety measure.
   1189 
   1190 Example results are thus:
   1191 
   1192 .. code-block:: json
   1193 
   1194     {
   1195       "backup_state": "TRUTHS_PAYING",
   1196       "secret_name" : "$NAME",
   1197       "core_secret" : { "$anything":"$anything" },
   1198       "payments": [
   1199         "taler://pay/...",
   1200         "taler://pay/..."
   1201       ]
   1202     }
   1203 
   1204 .. code-block:: json
   1205 
   1206     {
   1207       "backup_state": "POLICIES_PAYING",
   1208       "secret_name" : "$NAME",
   1209       "core_secret" : { "$anything":"$anything" },
   1210       "payments": [
   1211         "taler://pay/...",
   1212         "taler://pay/..."
   1213       ]
   1214     }
   1215 
   1216 .. code-block:: json
   1217 
   1218     {
   1219       "backup_state": "BACKUP_FINISHED",
   1220       "success_details": {
   1221         "http://localhost:8080/" : {
   1222           "policy_version" : 1,
   1223           "policy_expiration" : { "t_ms" : 1245362362000 }
   1224         },
   1225         "http://localhost:8081/" : {
   1226           "policy_version" : 3,
   1227           "policy_expiration" : { "t_ms" : 1245362362000 }
   1228         }
   1229       }
   1230     }
   1231 
   1232 
   1233 **pay:**
   1234 
   1235 This transition suggests to the reducer that a payment may have been made or
   1236 is immanent, and that the reducer should check with the Anastasis service
   1237 provider to see if the operation is now possible.  The operation takes one
   1238 optional argument, which is a ``timeout`` value that specifies how long the
   1239 reducer may wait (in long polling) for the payment to complete:
   1240 
   1241 .. code-block:: json
   1242 
   1243     {
   1244       "timeout":  { "d_ms" : 5000 },
   1245     }
   1246 
   1247 The specified timeout is passed on to the Anastasis service provider(s), which
   1248 will wait this long before giving up.  If no timeout is given, the check is
   1249 done as quickly as possible without additional delays.  The reducer will continue
   1250 to either an updated state with the remaining payment requests, to the
   1251 ``BACKUP_FINISHED`` state (if all payments have been completed and the backup
   1252 finished), or return an error response in case there was an irrecoverable error,
   1253 indicating the specific provider and how it failed.  An example for this
   1254 final error state would be:
   1255 
   1256 .. code-block:: json
   1257 
   1258     {
   1259       "http_status" : 500,
   1260       "upload_status" : 52,
   1261       "provider_url" : "https://bad.example.com/",
   1262     }
   1263 
   1264 Here, the fields have the following meaning:
   1265 
   1266   - **http_status** is the HTTP status returned by the Anastasis provider.
   1267   - **upload_status** is the Taler error code return by the provider.
   1268   - **provider_url** is the base URL of the failing provider.
   1269 
   1270 In the above example, 52 would thus imply that the Anastasis provider failed to
   1271 store information into its database.
   1272 
   1273 
   1274 Recovery transitions
   1275 --------------------
   1276 
   1277 **enter_user_attributes:**
   1278 
   1279 This transition provides the user's personal attributes. The specific set of
   1280 attributes required depends on the country of residence of the user.  Some
   1281 attributes may be optional, in which case they should be omitted entirely
   1282 (that is, not simply be set to ``null`` or an empty string).  The
   1283 arguments are identical to the **enter_user_attributes** transition from
   1284 the backup process.  Example arguments would thus be:
   1285 
   1286 .. code-block:: json
   1287 
   1288     {
   1289       "identity_attributes": {
   1290         "full_name": "Max Musterman",
   1291         "social_security_number": "123456789",
   1292         "birthdate": "2000-01-01",
   1293         "birthplace": "Earth"
   1294       }
   1295     }
   1296 
   1297 Afterwards, the reducer transitions into the ``SECRET_SELECTING`` state:
   1298 
   1299 .. code-block:: json
   1300 
   1301     {
   1302       "recovery_state": "SECRET_SELECTING",
   1303       "identity_attributes": {
   1304         "full_name": "Max Musterman",
   1305         "social_security_number": "123456789",
   1306         "birthdate": "2000-01-01",
   1307         "birthplace": "Earth"
   1308       }
   1309     }
   1310 
   1311 Typically, the special policy discovery process (outside of the state
   1312 machine) is expected to be run in this state.  The discovery process
   1313 will use the state (and in particular the identity attributes and the
   1314 list of active providers) to discover a set of possible recovery
   1315 documents with their respective provider URLs, policy version and
   1316 identity attribute mask. An identity attribute mask is a bitmask that
   1317 describes which of the optional attributes from the identity
   1318 attributes should be omitted to recover this backup.  Once the user
   1319 has selected a backup providing this triplet, it is possible to
   1320 proceed using ``next``.
   1321 
   1322 Especially if the discovered policies are inadequate, it is again
   1323 possible to add providers using ``add_provider``.
   1324 
   1325 
   1326 **add_provider**:
   1327 
   1328 This operation can be performed in state ``SECRET_SELECTING``.  It
   1329 adds one additional Anastasis provider to the list of providers that
   1330 the discovery process should henceforth consider.  Note that removing
   1331 providers is not possible at this time.
   1332 
   1333 Here, the client must provide an object with the base URL of the
   1334 providers to add, for example:
   1335 
   1336 .. code-block:: json
   1337 
   1338     {
   1339       "provider_url" : "http://localhost:8088/"
   1340     }
   1341 
   1342 
   1343 **select_version**:
   1344 
   1345 Using the ``select_version`` transition in the ``SECRET_SELECTING`` state,
   1346 it is possible to trigger the download and decryption of a recovery
   1347 policy document. Here, the arguments specify which provider, version
   1348 and mask should be used to download the document:
   1349 
   1350 .. code-block:: json
   1351 
   1352     {
   1353       "providers" : [ {
   1354         "url": "https://localhost:8088/",
   1355         "version": 0
   1356       } ],
   1357       "attribute_mask": 0
   1358     }
   1359 
   1360 The reducer will attempt to retrieve the specified recovery document
   1361 from that provider.  If a recovery document was found, the reducer
   1362 will attempt to load it and transition to a state where the user can
   1363 choose which challenges to satisfy:
   1364 
   1365 .. code-block:: json
   1366 
   1367     {
   1368       "recovery_state": "CHALLENGE_SELECTING",
   1369       "recovery_information": {
   1370         "challenges": [
   1371           {
   1372             "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
   1373             "uuid-display": "MW2R3RC",
   1374             "type": "question",
   1375             "instructions": "q1"
   1376           },
   1377           {
   1378             "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1379             "uuid-display": "TXYKGE",
   1380             "type": "email",
   1381             "instructions": "e-mail address m?il@f*.bar"
   1382           },
   1383         ],
   1384         "policies": [
   1385           [
   1386             {
   1387               "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
   1388             },
   1389             {
   1390               "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
   1391             },
   1392           ],
   1393         ],
   1394         "provider_url": "http://localhost:8088/",
   1395         "version": 1,
   1396       },
   1397       "recovery_document": {
   1398         "...": "..."
   1399       }
   1400     }
   1401 
   1402 The ``recovery_document`` is an internal representation of the recovery
   1403 information and of no concern to the user interface. The pertinent information
   1404 is in the ``recovery_information``. Here, the ``challenges`` array is a list
   1405 of possible challenges the user could attempt to solve next, while ``policies``
   1406 is an array of policies, with each policy being an array of challenges.
   1407 Satisfying all of the challenges of one of the policies will enable the secret
   1408 to be recovered.  The ``provider_url`` from where the recovery document was
   1409 obtained and its ``version`` are also provided.  Each challenge comes with
   1410 four mandatory fields:
   1411 
   1412     - **uuid**: A unique identifier of the challenge; this is what the
   1413       UUIDs in the policies array refer to.
   1414     - **uuid-display**: Shortened idenfier which is included in messages
   1415       send to the user.  Allows the user to
   1416       distinguish different PIN/TANs should say the same phone number be
   1417       used for SMS-authentication with different providers.
   1418     - **type**: This is the type of the challenge, as a string.
   1419     - **instructions**: Contains additional important hints for the user
   1420       to allow the user to satisfy the challenge.  It typically includes
   1421       an abbreviated form of the contact information or the security
   1422       question. Details depend on ``type``.
   1423 
   1424 If a recovery document was not found, either the user never performed
   1425 a backup, entered incorrect attributes, or used a provider not yet in
   1426 the list of Anastasis providers.  Hence, the user must now either
   1427 select a different provider, or go ``back`` and update the identity
   1428 attributes.  In the case a recovery document was not found, the
   1429 transition fails, returning the error code and a human-readable error
   1430 message together with a transition failure:
   1431 
   1432 .. code-block:: json
   1433 
   1434     {
   1435       "error_message": "account unknown to Anastasis server",
   1436       "error_code": 9,
   1437     }
   1438 
   1439 Here, the ``error_code`` is from the ``enum ANASTASIS_RecoveryStatus``
   1440 and describes precisely what failed about the download, while the
   1441 ``error_message`` is a human-readable (English) explanation of the code.
   1442 Applications may want to translate the message using GNU gettext;
   1443 translations should be available in the ``anastasis`` text domain.
   1444 However, in general it should be sufficient to display the slightly
   1445 more generic Taler error code that is returned with the new state.
   1446 
   1447 
   1448 **sync_providers**
   1449 
   1450 The downloaded policy may include secrets from providers for which
   1451 we do not (yet) have the cost structure or even the salt. So here
   1452 an application can use the ``sync_providers`` request to download
   1453 ``/config`` from providers that are in the challenge list but not
   1454 yet known with their salt and other attributes in the provider list.
   1455 
   1456 The transition fails if all providers relevant for the selected
   1457 policy are already downloaded. Applications may either internally
   1458 check the state for this, or call ``sync_providers`` until it fails
   1459 with this error:
   1460 
   1461 .. code-block:: json
   1462 
   1463   {
   1464     "detail": "already in sync",
   1465     "code": 8400,
   1466     "hint": "The given action is invalid for the current state of the reducer."
   1467   }
   1468 
   1469 As providers may fail to respond, this action may need to be called
   1470 repeatedly. The action will block until progress is made on any provider.
   1471 As some providers may never respond, the application should disable
   1472 challenge buttons for challenges where providers are down.  However,
   1473 users should be able to solve challenges where the provider is up while
   1474 the reducer is polling for ``/config`` in the background.
   1475 
   1476 
   1477 **select_challenge:**
   1478 
   1479 Selecting a challenge takes different, depending on the state of the payment.
   1480 A comprehensive example for ``select_challenge`` would be:
   1481 
   1482 .. code-block:: json
   1483 
   1484     {
   1485         "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
   1486         "timeout" : { "d_ms" : 5000 },
   1487         "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
   1488     }
   1489 
   1490 The ``uuid`` field is mandatory and specifies the selected challenge.
   1491 The other fields are optional, and are needed in case the user has
   1492 previously been requested to pay for the challenge.  In this case,
   1493 the ``payment_secret`` identifies the previous payment request, and
   1494 ``timeout`` says how long the Anastasis service should wait for the
   1495 payment to be completed before giving up (long polling).
   1496 
   1497 Depending on the type of the challenge and the need for payment, the
   1498 reducer may transition into ``CHALLENGE_SOLVING`` or ``CHALLENGE_PAYING``
   1499 states.  In ``CHALLENGE_SOLVING``, the new state will primarily specify
   1500 the selected challenge:
   1501 
   1502 .. code-block:: json
   1503 
   1504     {
   1505       "backup_state": "CHALLENGE_SOLVING",
   1506       "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
   1507     }
   1508 
   1509 In ``CHALLENGE_PAYING``, the new state will include instructions for payment
   1510 in the ``challenge_feedback``. In general, ``challenge_feedback`` includes
   1511 information about attempted challenges, with the final state being ``solved``:
   1512 
   1513 .. code-block:: json
   1514 
   1515     {
   1516       "recovery_state": "CHALLENGE_SELECTING",
   1517       "recovery_information": {
   1518         "...": "..."
   1519       }
   1520       "challenge_feedback": {
   1521         "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
   1522           "state" : "solved"
   1523         }
   1524       }
   1525     }
   1526 
   1527 Challenges feedback for a challenge can have many different ``state`` values
   1528 that applications must all handle. States other than ``solved`` are:
   1529 
   1530 - **payment**: Here, the user must pay for a challenge. An example would be:
   1531 
   1532   .. code-block:: json
   1533 
   1534      {
   1535        "backup_state": "CHALLENGE_PAYING",
   1536        "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
   1537        "challenge_feedback": {
   1538          "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
   1539           "state" : "payment",
   1540           "taler_pay_uri" : "taler://pay/...",
   1541           "provider" : "https://localhost:8080/",
   1542           "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
   1543          }
   1544        }
   1545      }
   1546 
   1547 - **body**: Here, the server provided an HTTP reply for
   1548   how to solve the challenge, but the reducer could not parse
   1549   them into a known format. A mime-type may be provided and may
   1550   help parse the details.
   1551 
   1552   .. code-block:: json
   1553 
   1554      {
   1555        "recovery_state": "CHALLENGE_SOLVING",
   1556        "recovery_information": {
   1557            "...": "..."
   1558        }
   1559        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1560        "challenge_feedback": {
   1561          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1562            "state": "body",
   1563            "body": "CROCKFORDBASE32ENCODEDBODY",
   1564            "http_status": 403,
   1565            "mime_type" : "anything/possible"
   1566          }
   1567        }
   1568      }
   1569 
   1570 - **hint**: Here, the server provided human-readable hint for
   1571   how to solve the challenge.  Note that the ``hint`` provided this
   1572   time is from the Anastasis provider and may differ from the ``instructions``
   1573   for the challenge under ``recovery_information``:
   1574 
   1575   .. code-block:: json
   1576 
   1577      {
   1578        "recovery_state": "CHALLENGE_SOLVING",
   1579        "recovery_information": {
   1580            "...": "..."
   1581        }
   1582        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1583        "challenge_feedback": {
   1584          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1585            "state": "hint",
   1586            "hint": "Recovery TAN send to email mail@DOMAIN",
   1587            "http_status": 403
   1588          }
   1589        }
   1590      }
   1591 
   1592 - **details**: Here, the server provided a detailed JSON status response
   1593   related to solving the challenge:
   1594 
   1595   .. code-block:: json
   1596 
   1597     {
   1598       "recovery_state": "CHALLENGE_SOLVING",
   1599       "recovery_information": {
   1600          "...": "..."
   1601       }
   1602       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1603       "challenge_feedback": {
   1604         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1605           "state": "details",
   1606           "details": {
   1607             "code": 8111,
   1608             "hint": "The client's response to the challenge was invalid.",
   1609             "detail" : null
   1610           },
   1611           "http_status": 403
   1612         }
   1613       }
   1614     }
   1615 
   1616 - **redirect**: To solve the challenge, the user must visit the indicated
   1617   Web site at ``redirect_url``, for example to perform video authentication:
   1618 
   1619   .. code-block:: json
   1620 
   1621      {
   1622        "recovery_state": "CHALLENGE_SOLVING",
   1623        "recovery_information": {
   1624           "...": "..."
   1625        }
   1626        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1627        "challenge_feedback": {
   1628          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1629            "state": "redirect",
   1630            "redirect_url": "https://videoconf.example.com/",
   1631            "http_status": 303
   1632          }
   1633        }
   1634      }
   1635 
   1636 - **server-failure**: This indicates that the Anastasis provider encountered
   1637   a failure and recovery using this challenge cannot proceed at this time.
   1638   Examples for failures might be that the provider is unable to send SMS
   1639   messages at this time due to an outage.  The body includes details about
   1640   the failure. The user may try again later or continue with other challenges.
   1641 
   1642   .. code-block:: json
   1643 
   1644     {
   1645       "recovery_state": "CHALLENGE_SELECTING",
   1646       "recovery_information": {
   1647           "...": "..."
   1648       }
   1649       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1650       "challenge_feedback": {
   1651         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1652          "state": "server-failure",
   1653          "http_status": "500",
   1654          "error_code": 52
   1655        }
   1656      }
   1657    }
   1658 
   1659 - **truth-unknown**: This indicates that the Anastasis provider is unaware of
   1660   the specified challenge. This is typically a permanent failure, and user
   1661   interfaces should not allow users to re-try this challenge.
   1662 
   1663   .. code-block:: json
   1664 
   1665     {
   1666       "recovery_state": "CHALLENGE_SELECTING",
   1667       "recovery_information": {
   1668           "...": "..."
   1669       }
   1670       "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1671       "challenge_feedback": {
   1672         "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1673           "state": "truth-unknown",
   1674           "error_code": 8108
   1675         }
   1676       }
   1677     }
   1678 
   1679 - **rate-limit-exceeded**: This indicates that the user has made too many invalid attempts in too short an amount of time.
   1680 
   1681   .. code-block:: json
   1682 
   1683      {
   1684        "recovery_state": "CHALLENGE_SELECTING",
   1685        "recovery_information": {
   1686            "...": "..."
   1687        }
   1688        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1689        "challenge_feedback": {
   1690          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1691            "state": "rate-limit-exceeded",
   1692            "error_code": 8121
   1693          }
   1694        }
   1695      }
   1696 
   1697 - **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.
   1698 
   1699   .. code-block:: json
   1700 
   1701      {
   1702        "recovery_state": "CHALLENGE_SELECTING",
   1703        "recovery_information": {
   1704            "...": "..."
   1705        }
   1706        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1707        "challenge_feedback": {
   1708          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1709            "state": "authentication-timeout",
   1710            "error_code": 8122
   1711          }
   1712        }
   1713      }
   1714 
   1715 - **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.
   1716 
   1717   .. code-block:: json
   1718 
   1719      {
   1720        "recovery_state": "CHALLENGE_SELECTING",
   1721        "recovery_information": {
   1722            "...": "..."
   1723        }
   1724        "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
   1725        "challenge_feedback": {
   1726          "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
   1727            "state": "external-instructions",
   1728            "method": "iban",
   1729            "async": true, // optional
   1730            "answer_code": 987654321, // optional
   1731            "details": {
   1732              "...": "..."
   1733            }
   1734          }
   1735        }
   1736      }
   1737 
   1738   If "async" is "true", then the client should
   1739   poll for the challenge being satisfied using
   1740   the "answer_code" that has been provided.
   1741 
   1742   The specific instructions on how to satisfy
   1743   the challenge depend on the ``method``.
   1744   They include:
   1745 
   1746   - **iban**: The user must perform a wire transfer from their account to the Anastasis provider.
   1747 
   1748     .. code-block:: json
   1749 
   1750       {
   1751         "challenge_amount": "EUR:1",
   1752         "credit_iban": "DE12345789000",
   1753         "business_name": "Data Loss Incorporated",
   1754         "wire_transfer_subject": "Anastasis 987654321"
   1755       }
   1756 
   1757     Note that the actual wire transfer subject must contain both
   1758     the numeric ``answer_code`` as well as
   1759     the string ``Anastasis``.
   1760 
   1761 **poll:**
   1762 
   1763 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:
   1764 
   1765 .. code-block:: json
   1766 
   1767     {
   1768         "timeout" : { "d_ms" : 5000 },
   1769     }
   1770 
   1771 
   1772 **pay:**
   1773 
   1774 With a ``pay`` transition, the application indicates to the reducer that
   1775 a payment may have been made. Here, it is again possible to specify an
   1776 optional ``timeout`` argument for long-polling, for example:
   1777 
   1778 .. code-block:: json
   1779 
   1780     {
   1781         "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
   1782         "timeout" : { "d_ms" : 5000 },
   1783     }
   1784 
   1785 Depending on the type of the challenge and the result of the operation, the
   1786 new state may be ``CHALLENGE_SOLVING`` (if say the SMS was now sent to the
   1787 user), ``CHALLENGE_SELECTING`` (if the answer to the security question was
   1788 correct), ``RECOVERY_FINISHED`` (if this was the last challenge that needed to
   1789 be solved) or still ``CHALLENGE_PAYING`` (if the challenge was not actually
   1790 paid for).  For sample messages, see the different types of
   1791 ``challenge_feedback`` in the section about ``select_challenge``.
   1792 
   1793 
   1794 **solve_challenge:**
   1795 
   1796 Solving a challenge takes various formats, depending on the type of the
   1797 challenge and what is known about the answer.  The different supported
   1798 formats are:
   1799 
   1800 .. code-block:: json
   1801 
   1802     {
   1803         "answer": "answer to security question"
   1804     }
   1805 
   1806 .. code-block:: json
   1807 
   1808     {
   1809         "pin": 1234
   1810     }
   1811 
   1812 .. code-block:: json
   1813 
   1814     {
   1815         "hash": "SOMEBASE32ENCODEDHASHVALUE"
   1816     }