From e4b26753aa80bd26b288d70e7734b056144f2d6e Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Mon, 7 Feb 2022 14:52:47 -0500
Subject: [PATCH] bump the API version to 2; also remove some duplication in
 its definition

---
 docs/source/configuration.rst                 | 28 +++++++++----------
 docs/source/interface.rst                     | 12 ++++----
 src/_zkapauthorizer/_plugin.py                |  2 +-
 src/_zkapauthorizer/api.py                    |  4 +++
 src/_zkapauthorizer/config.py                 |  3 +-
 src/_zkapauthorizer/model.py                  |  6 ++++
 src/_zkapauthorizer/resource.py               |  8 +++---
 src/_zkapauthorizer/storage_common.py         |  5 ++--
 src/_zkapauthorizer/tests/strategies.py       |  9 +++---
 .../tests/test_client_resource.py             | 17 +++++------
 src/_zkapauthorizer/tests/test_plugin.py      | 19 +++++++------
 .../tests/test_storage_client.py              | 24 ++++++++--------
 src/twisted/plugins/zkapauthorizer.py         |  4 +--
 13 files changed, 79 insertions(+), 62 deletions(-)

diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst
index 2828d4a..6b01d21 100644
--- a/docs/source/configuration.rst
+++ b/docs/source/configuration.rst
@@ -8,9 +8,9 @@ To enable the plugin at all, add its name to the list of storage plugins in the
 (``tahoe.cfg`` in the relevant node directory)::
 
   [client]
-  storage.plugins = privatestorageio-zkapauthz-v1
+  storage.plugins = privatestorageio-zkapauthz-v2
 
-Then configure the plugin as desired in the ``storageclient.plugins.privatestorageio-zkapauthz-v1`` section.
+Then configure the plugin as desired in the ``storageclient.plugins.privatestorageio-zkapauthz-v2`` section.
 
 redeemer
 ~~~~~~~~
@@ -20,7 +20,7 @@ The ``dummy`` value is useful for testing purposes only.
 
 For example::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   redeemer = dummy
   issuer-public-key = YXNkYXNkYXNkYXNkYXNkCg==
 
@@ -31,7 +31,7 @@ In this case, the ``ristretto-issuer-root-url`` item is also required.
 
 For example::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   redeemer = ristretto
   ristretto-issuer-root-url = https://issuer.example.invalid/
 
@@ -40,14 +40,14 @@ If the values are not the same, the client will decline to use the storage serve
 
 The client can also be configured with the value of a single pass::
 
-    [storageclient.plugins.privatestorageio-zkapauthz-v1]
+    [storageclient.plugins.privatestorageio-zkapauthz-v2]
     pass-value = 1048576
 
 The value given here must agree with the value servers use in their configuration or the storage service will be unusable.
 
 The client can also be configured with the number of passes to expect in exchange for one voucher::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   default-token-count = 32768
 
 The value given here must agree with the value the issuer uses in its configuration or redemption may fail.
@@ -58,7 +58,7 @@ allowed-public-keys
 Regardless of which redeemer is selected,
 the client must also be configured with the public part of the issuer key pair which it will allow to sign tokens::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   allowed-public-keys = AAAA...,BBBB...,CCCC...
 
 The ``allowed-public-keys`` value is a comma-separated list of encoded public keys.
@@ -76,7 +76,7 @@ The client will try to make the average (mean) interval between runs equal to th
 The value is an integer number of seconds.
 For example to run on average every 26 days::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   lease.crawl-interval.mean = 2246400
 
 
@@ -88,7 +88,7 @@ The random intervals between runs have a uniform distribution with this item's v
 The value is an integer number of seconds.
 For example to make all intervals fall within a 7 day period::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   lease.crawl-interval.range = 302400
 
 
@@ -101,7 +101,7 @@ If the crawler encounters a lease with less time left than this then it will ren
 The value is an integer number of seconds.
 For example to renew leases on all shares which will expire in less than one week::
 
-  [storageclient.plugins.privatestorageio-zkapauthz-v1]
+  [storageclient.plugins.privatestorageio-zkapauthz-v2]
   lease.min-time-remaining = 604800
 
 Server
@@ -111,16 +111,16 @@ To enable the plugin at all, add its name to the list of storage plugins in the
 (``tahoe.cfg`` in the relevant node directory)::
 
   [storage]
-  plugins = privatestorageio-zkapauthz-v1
+  plugins = privatestorageio-zkapauthz-v2
 
 Then also configure the Ristretto-flavored PrivacyPass issuer the server will announce to clients::
 
-  [storageserver.plugins.privatestorageio-zkapauthz-v1]
+  [storageserver.plugins.privatestorageio-zkapauthz-v2]
   ristretto-issuer-root-url = https://issuer.example.invalid/
 
 The value of a single pass in the system can be configured here as well::
 
-  [storageserver.plugins.privatestorageio-zkapauthz-v1]
+  [storageserver.plugins.privatestorageio-zkapauthz-v2]
   pass-value = 1048576
 
 If no ``pass-value`` is given then a default will be used.
@@ -130,7 +130,7 @@ The storage server must also be configured with the path to the Ristretto-flavor
 To avoid placing secret material in tahoe.cfg,
 this configuration is done using a path::
 
-  [storageserver.plugins.privatestorageio-zkapauthz-v1]
+  [storageserver.plugins.privatestorageio-zkapauthz-v2]
   ristretto-signing-key-path = /path/to/signing.key
 
 The signing key is the keystone secret to the entire system and must be managed with extreme care to prevent unintended disclosure.
diff --git a/docs/source/interface.rst b/docs/source/interface.rst
index e771e67..27fe303 100644
--- a/docs/source/interface.rst
+++ b/docs/source/interface.rst
@@ -19,7 +19,7 @@ For example, if the secret token is ``ABCDEF``::
 
 The correct value for the token can be read from the Tahoe-LAFS node's ``private/api_auth_token`` file.
 
-``GET /storage-plugins/privatestorageio-zkapauthz-v1/version``
+``GET /storage-plugins/privatestorageio-zkapauthz-v2/version``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint returns the version of the ZKAPAuthorizer Python package in use by the Tahoe-LAFS client node.
@@ -29,7 +29,7 @@ The response is **OK** with an ``application/json`` **Content-Type**::
   { "version": <string>
   }
 
-``PUT /storage-plugins/privatestorageio-zkapauthz-v1/voucher``
+``PUT /storage-plugins/privatestorageio-zkapauthz-v2/voucher``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an external agent which has submitted a payment to cause the plugin to redeem the voucher for tokens.
@@ -44,7 +44,7 @@ If the voucher cannot be accepted at the time of the request then the response c
 If the response is **OK** then a repeated request with the same body will have no effect.
 If the response is not **OK** then a repeated request with the same body will try to accept the number again.
 
-``GET /storage-plugins/privatestorageio-zkapauthz-v1/voucher/<voucher>``
+``GET /storage-plugins/privatestorageio-zkapauthz-v2/voucher/<voucher>``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an external agent to monitor the status of the redemption of a voucher.
@@ -125,7 +125,7 @@ The *finished* timestamp gives the time when the unpaid error was encountered.
 The *finished* timestamp gives the time when this other error condition was encountered.
 The *details* string may give additional details about what the error was.
 
-``GET /storage-plugins/privatestorageio-zkapauthz-v1/voucher``
+``GET /storage-plugins/privatestorageio-zkapauthz-v2/voucher``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an external agent to retrieve the status of all vouchers.
@@ -137,7 +137,7 @@ The response is **OK** with ``application/json`` content-type response body like
 
 The elements of the list are objects like the one returned by issuing a **GET** to a child of this collection resource.
 
-``GET /storage-plugins/privatestorageio-zkapauthz-v1/lease-maintenance``
+``GET /storage-plugins/privatestorageio-zkapauthz-v2/lease-maintenance``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an external agent to retrieve information about automatic spending for lease maintenance.
@@ -159,7 +159,7 @@ If it has run,
  * ``when``: associated with an ISO8601 datetime string giving the approximate time the process ran
  * ``count``: associated with a number giving the number of passes which would need to be spent to renew leases on all stored objects seen during the lease maintenance activity
 
-``POST /storage-plugins/privatestorageio-zkapauthz-v1/calculate-price``
+``POST /storage-plugins/privatestorageio-zkapauthz-v2/calculate-price``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 This endpoint allows an agent to calculate the number of ZKAPs it will cost to store a collection of files of specified sizes.
diff --git a/src/_zkapauthorizer/_plugin.py b/src/_zkapauthorizer/_plugin.py
index 7d25ffa..bc94b2e 100644
--- a/src/_zkapauthorizer/_plugin.py
+++ b/src/_zkapauthorizer/_plugin.py
@@ -80,7 +80,7 @@ class ZKAPAuthorizer(object):
         connection.
     """
 
-    name = attr.ib(default="privatestorageio-zkapauthz-v1")
+    name = attr.ib()
     _stores = attr.ib(default=attr.Factory(WeakValueDictionary))
 
     def _get_store(self, node_config):
diff --git a/src/_zkapauthorizer/api.py b/src/_zkapauthorizer/api.py
index f4bb2c2..4076c7c 100644
--- a/src/_zkapauthorizer/api.py
+++ b/src/_zkapauthorizer/api.py
@@ -20,6 +20,10 @@ __all__ = [
     "ZKAPAuthorizer",
 ]
 
+# The identifier for this plugin.  This appears in URLs for resources the
+# client plugin exposes, configuration files, etc.
+NAME = "privatestorageio-zkapauthz-v2"
+
 from ._storage_client import ZKAPAuthorizerStorageClient
 from ._storage_server import LeaseRenewalRequired, ZKAPAuthorizerStorageServer
 from .storage_common import MorePassesRequired
diff --git a/src/_zkapauthorizer/config.py b/src/_zkapauthorizer/config.py
index cb9dc38..f92cde0 100644
--- a/src/_zkapauthorizer/config.py
+++ b/src/_zkapauthorizer/config.py
@@ -21,6 +21,7 @@ from typing import Optional
 
 from allmydata.node import _Config
 
+from .api import NAME
 from .lease_maintenance import LeaseMaintenanceConfig
 
 
@@ -124,7 +125,7 @@ def _read_duration(cfg, option, default):
         as a ``timedelta``.
     """
     # type: (_Config, str) -> Optional[timedelta]
-    section_name = "storageclient.plugins.privatestorageio-zkapauthz-v1"
+    section_name = "storageclient.plugins." + NAME
     value_str = cfg.get_config(
         section=section_name,
         option=option,
diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py
index 2990348..d3526ab 100644
--- a/src/_zkapauthorizer/model.py
+++ b/src/_zkapauthorizer/model.py
@@ -75,6 +75,12 @@ class NotEnoughTokens(Exception):
     """
 
 
+# The version number in _zkapauthorizer.api.NAME doesn't match the version
+# here because the database is persistent state and we need to be sure to load
+# the older version even if we signal an API compatibility break by bumping
+# the version number elsewhere.  Consider this version number part of a
+# different scheme where we're versioning our ability to open the database at
+# all.  The schema inside the database is versioned by yet another mechanism.
 CONFIG_DB_NAME = "privatestorageio-zkapauthz-v1.sqlite3"
 
 
diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py
index 93b34d0..a06c862 100644
--- a/src/_zkapauthorizer/resource.py
+++ b/src/_zkapauthorizer/resource.py
@@ -32,6 +32,7 @@ from zope.interface import Attribute
 from . import __version__ as _zkapauthorizer_version
 from ._base64 import urlsafe_b64decode
 from ._json import dumps_utf8
+from .api import NAME
 from .config import get_configured_lease_duration
 from .controller import PaymentController, get_redeemer
 from .pricecalculator import PriceCalculator
@@ -89,7 +90,7 @@ def from_configuration(
 ):
     """
     Instantiate the plugin root resource using data from its configuration
-    section, **storageclient.plugins.privatestorageio-zkapauthz-v1**, in the
+    section, **storageclient.plugins.privatestorageio-zkapauthz-v2**, in the
     Tahoe-LAFS configuration file.  See the configuration documentation for
     details of the configuration section.
 
@@ -108,16 +109,15 @@ def from_configuration(
     :return IZKAPRoot: The root of the resource hierarchy presented by the
         client side of the plugin.
     """
-    plugin_name = "privatestorageio-zkapauthz-v1"
     if redeemer is None:
         redeemer = get_redeemer(
-            plugin_name,
+            NAME,
             node_config,
             None,
             None,
         )
     default_token_count = get_token_count(
-        plugin_name,
+        NAME,
         node_config,
     )
     controller = PaymentController(
diff --git a/src/_zkapauthorizer/storage_common.py b/src/_zkapauthorizer/storage_common.py
index db04c1f..c8e8786 100644
--- a/src/_zkapauthorizer/storage_common.py
+++ b/src/_zkapauthorizer/storage_common.py
@@ -22,6 +22,7 @@ from typing import Callable
 import attr
 from pyutil.mathutil import div_ceil
 
+from .api import NAME
 from .eliot import MUTABLE_PASSES_REQUIRED
 from .validators import greater_than
 
@@ -110,7 +111,7 @@ def get_configured_pass_value(node_config):
     value is read from the **pass-value** option of the ZKAPAuthorizer plugin
     client section.
     """
-    section_name = "storageclient.plugins.privatestorageio-zkapauthz-v1"
+    section_name = "storageclient.plugins." + NAME
     return int(
         node_config.get_config(
             section=section_name,
@@ -124,7 +125,7 @@ def get_configured_allowed_public_keys(node_config):
     """
     Read the set of allowed issuer public keys from the given configuration.
     """
-    section_name = "storageclient.plugins.privatestorageio-zkapauthz-v1"
+    section_name = "storageclient.plugins." + NAME
     return set(
         node_config.get_config(
             section=section_name,
diff --git a/src/_zkapauthorizer/tests/strategies.py b/src/_zkapauthorizer/tests/strategies.py
index d468030..45d2780 100644
--- a/src/_zkapauthorizer/tests/strategies.py
+++ b/src/_zkapauthorizer/tests/strategies.py
@@ -46,6 +46,7 @@ from twisted.internet.task import Clock
 from twisted.web.test.requesthelper import DummyRequest
 from zope.interface import implementer
 
+from ..api import NAME
 from ..configutil import config_string_from_sections
 from ..lease_maintenance import LeaseMaintenanceConfig, lease_maintenance_config_to_dict
 from ..model import (
@@ -478,7 +479,7 @@ def client_lease_maintenance_configurations(maint_configs=None):
 
 
 def direct_tahoe_configs(
-    zkapauthz_v1_configuration=client_dummyredeemer_configurations(),
+    zkapauthz_v2_configuration=client_dummyredeemer_configurations(),
     shares=just((None, None, None)),
 ):
     """
@@ -492,7 +493,7 @@ def direct_tahoe_configs(
     """
     config_texts = minimal_tahoe_configs(
         {
-            "privatestorageio-zkapauthz-v1": zkapauthz_v1_configuration,
+            NAME: zkapauthz_v2_configuration,
         },
         shares,
     )
@@ -506,7 +507,7 @@ def direct_tahoe_configs(
 
 
 def tahoe_configs(
-    zkapauthz_v1_configuration=client_dummyredeemer_configurations(),
+    zkapauthz_v2_configuration=client_dummyredeemer_configurations(),
     shares=just((None, None, None)),
 ):
     """
@@ -531,7 +532,7 @@ def tahoe_configs(
 
         return set_paths
 
-    return direct_tahoe_configs(zkapauthz_v1_configuration, shares,).map(
+    return direct_tahoe_configs(zkapauthz_v2_configuration, shares,).map(
         path_setter,
     )
 
diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 96c25c8..0d1daff 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -73,6 +73,7 @@ from twisted.web.resource import IResource, getChildForRequest
 from .. import __version__ as zkapauthorizer_version
 from .._base64 import urlsafe_b64decode
 from .._json import dumps_utf8
+from ..api import NAME
 from ..configutil import config_string_from_sections
 from ..model import (
     DoubleSpend,
@@ -714,7 +715,7 @@ class VoucherTests(TestCase):
         those relevant to a voucher which is actively being redeemed, about
         the voucher are included in a json-encoded response body.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_get_known_voucher(
             config,
             api_auth_token,
@@ -746,7 +747,7 @@ class VoucherTests(TestCase):
         those relevant to a voucher which has been redeemed, about the voucher
         are included in a json-encoded response body.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_get_known_voucher(
             config,
             api_auth_token,
@@ -779,7 +780,7 @@ class VoucherTests(TestCase):
         already redeemed, about the voucher are included in a json-encoded
         response body.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_get_known_voucher(
             config,
             api_auth_token,
@@ -811,7 +812,7 @@ class VoucherTests(TestCase):
         not been paid for yet, about the voucher are included in a
         json-encoded response body.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_get_known_voucher(
             config,
             api_auth_token,
@@ -843,7 +844,7 @@ class VoucherTests(TestCase):
         kind of transient conditions, about the voucher are included in a
         json-encoded response body.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_get_known_voucher(
             config,
             api_auth_token,
@@ -933,7 +934,7 @@ class VoucherTests(TestCase):
         A ``GET`` to the ``VoucherCollection`` itself returns a list of existing
         vouchers.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_list_vouchers(
             config,
             api_auth_token,
@@ -970,7 +971,7 @@ class VoucherTests(TestCase):
         A ``GET`` to the ``VoucherCollection`` itself returns a list of existing
         vouchers including state information that reflects transient states.
         """
-        count = get_token_count("privatestorageio-zkapauthz-v1", config)
+        count = get_token_count(NAME, config)
         return self._test_list_vouchers(
             config,
             api_auth_token,
@@ -1248,7 +1249,7 @@ class CalculatePriceTests(TestCase):
             lambda share_and_lease_time: tuples(
                 just(share_and_lease_time),
                 direct_tahoe_configs(
-                    zkapauthz_v1_configuration=client_dummyredeemer_configurations(
+                    zkapauthz_v2_configuration=client_dummyredeemer_configurations(
                         min_times_remaining=just(share_and_lease_time[1]),
                     ),
                     shares=just(share_and_lease_time[0]),
diff --git a/src/_zkapauthorizer/tests/test_plugin.py b/src/_zkapauthorizer/tests/test_plugin.py
index d2badcc..f626297 100644
--- a/src/_zkapauthorizer/tests/test_plugin.py
+++ b/src/_zkapauthorizer/tests/test_plugin.py
@@ -69,6 +69,7 @@ from twisted.plugins.zkapauthorizer import storage_server
 
 from .._plugin import get_root_nodes, load_signing_key
 from .._storage_client import IncorrectStorageServerReference
+from ..api import NAME
 from ..controller import DummyRedeemer, IssuerConfigurationMismatch, PaymentController
 from ..foolscap import RIPrivacyPassAuthorizedStorageServer
 from ..lease_maintenance import SERVICE_NAME, LeaseMaintenanceConfig
@@ -339,7 +340,7 @@ tahoe_configs_with_dummy_redeemer = tahoe_configs(client_dummyredeemer_configura
 
 tahoe_configs_with_mismatched_issuer = minimal_tahoe_configs(
     {
-        "privatestorageio-zkapauthz-v1": just(
+        NAME: just(
             {"ristretto-issuer-root-url": "https://another-issuer.example.invalid/"}
         ),
     }
@@ -561,26 +562,26 @@ class ClientResourceTests(TestCase):
         )
 
 
-SERVERS_YAML = b"""
+SERVERS_YAML = """
 storage:
   v0-aaaaaaaa:
     ann:
       anonymous-storage-FURL: pb://@tcp:/
       nickname: 10.0.0.2
       storage-options:
-      - name: privatestorageio-zkapauthz-v1
+      - name: {name}
         ristretto-issuer-root-url: https://payments.example.com/
         storage-server-FURL: pb://bbbbbbbb@tcp:10.0.0.2:1234/cccccccc
-"""
+""".format(name=NAME).encode("ascii")
 
-TWO_SERVERS_YAML = b"""
+TWO_SERVERS_YAML = """
 storage:
   v0-aaaaaaaa:
     ann:
       anonymous-storage-FURL: pb://@tcp:/
       nickname: 10.0.0.2
       storage-options:
-      - name: privatestorageio-zkapauthz-v1
+      - name: {name}
         ristretto-issuer-root-url: https://payments.example.com/
         storage-server-FURL: pb://bbbbbbbb@tcp:10.0.0.2:1234/cccccccc
   v0-dddddddd:
@@ -588,10 +589,10 @@ storage:
       anonymous-storage-FURL: pb://@tcp:/
       nickname: 10.0.0.3
       storage-options:
-      - name: privatestorageio-zkapauthz-v1
+      - name: {name}
         ristretto-issuer-root-url: https://payments.example.com/
         storage-server-FURL: pb://eeeeeeee@tcp:10.0.0.3:1234/ffffffff
-"""
+""".format(name=NAME).encode("ascii")
 
 
 class LeaseMaintenanceServiceTests(TestCase):
@@ -708,7 +709,7 @@ class LeaseMaintenanceServiceTests(TestCase):
             # Then build a function that will get us a Tahoe configuration
             # that includes at least that lease maintenance configuration.
             lambda lease_maint_config: tahoe_configs(
-                zkapauthz_v1_configuration=client_lease_maintenance_configurations(
+                zkapauthz_v2_configuration=client_lease_maintenance_configurations(
                     just(lease_maint_config),
                 ),
             ).map(
diff --git a/src/_zkapauthorizer/tests/test_storage_client.py b/src/_zkapauthorizer/tests/test_storage_client.py
index 9f26eb6..947386b 100644
--- a/src/_zkapauthorizer/tests/test_storage_client.py
+++ b/src/_zkapauthorizer/tests/test_storage_client.py
@@ -38,7 +38,7 @@ from twisted.internet.defer import fail, succeed
 
 from .._storage_client import call_with_passes
 from .._storage_server import _ValidationResult
-from ..api import MorePassesRequired
+from ..api import NAME, MorePassesRequired
 from ..model import NotEnoughTokens
 from ..storage_common import (
     get_configured_allowed_public_keys,
@@ -108,7 +108,7 @@ shares.total = {}
     def test_get_configured_pass_value(self, expected):
         """
         ``get_configured_pass_value`` reads the ``pass-value`` value from the
-        ``storageclient.plugins.privatestorageio-zkapauthz-v1`` section as an
+        ``storageclient.plugins.privatestorageio-zkapauthz-v2`` section as an
         integer.
         """
         config = config_from_string(
@@ -120,11 +120,12 @@ shares.needed = 3
 shares.happy = 5
 shares.total = 10
 
-[storageclient.plugins.privatestorageio-zkapauthz-v1]
-pass-value={}
+[storageclient.plugins.{name}]
+pass-value={pass_value}
 """.format(
-                expected
-            ),
+    name=NAME,
+    pass_value=expected
+),
         )
 
         self.assertThat(
@@ -136,7 +137,7 @@ pass-value={}
     def test_get_configured_allowed_public_keys(self, expected):
         """
         ``get_configured_pass_value`` reads the ``pass-value`` value from the
-        ``storageclient.plugins.privatestorageio-zkapauthz-v1`` section as an
+        ``storageclient.plugins.privatestorageio-zkapauthz-v2`` section as an
         integer.
         """
         config = config_from_string(
@@ -148,11 +149,12 @@ shares.needed = 3
 shares.happy = 5
 shares.total = 10
 
-[storageclient.plugins.privatestorageio-zkapauthz-v1]
-allowed-public-keys = {}
+[storageclient.plugins.{name}]
+allowed-public-keys = {allowed_public_keys}
 """.format(
-                ",".join(expected)
-            ),
+    name=NAME,
+    allowed_public_keys=",".join(expected),
+),
         )
 
         self.assertThat(
diff --git a/src/twisted/plugins/zkapauthorizer.py b/src/twisted/plugins/zkapauthorizer.py
index 85448fe..ed11612 100644
--- a/src/twisted/plugins/zkapauthorizer.py
+++ b/src/twisted/plugins/zkapauthorizer.py
@@ -16,6 +16,6 @@
 A drop-in to supply plugins to the Twisted plugin system.
 """
 
-from _zkapauthorizer.api import ZKAPAuthorizer
+from _zkapauthorizer.api import NAME, ZKAPAuthorizer
 
-storage_server = ZKAPAuthorizer()
+storage_server = ZKAPAuthorizer(name=NAME)
-- 
GitLab