diff --git a/secure-access-token-authorizer.nix b/secure-access-token-authorizer.nix
index be5fabe508d62a74a32234d1678709696a86c981..cb825d72a6899b9bbd278a033b9198dfdf16ac0f 100644
--- a/secure-access-token-authorizer.nix
+++ b/secure-access-token-authorizer.nix
@@ -9,13 +9,16 @@ buildPythonPackage rec {
   ];
 
   propagatedBuildInputs = with pythonPackages; [
+    attrs
     zope_interface
     twisted
     tahoe-lafs
   ];
 
   checkInputs = with pythonPackages; [
+    fixtures
     testtools
+    hypothesis
   ];
 
   checkPhase = ''
diff --git a/src/_secureaccesstokenauthorizer/_plugin.py b/src/_secureaccesstokenauthorizer/_plugin.py
index ccede2047b78a7cd3a30ad19bbfbf27c265eb630..4b4019244fa4d4f0b34ec53f7e2b139fd31f4889 100644
--- a/src/_secureaccesstokenauthorizer/_plugin.py
+++ b/src/_secureaccesstokenauthorizer/_plugin.py
@@ -17,18 +17,33 @@ The Twisted plugin that glues the Secure Access Token system into
 Tahoe-LAFS.
 """
 
+import attr
+
 from zope.interface import (
     implementer,
 )
 
+from twisted.internet.defer import (
+    succeed,
+)
+
 from allmydata.interfaces import (
     IFoolscapStoragePlugin,
+    IAnnounceableStorageServer,
 )
 
 from .api import (
     SecureAccessTokenAuthorizerStorageServer,
 )
 
+@implementer(IAnnounceableStorageServer)
+@attr.s
+class AnnounceableStorageServer(object):
+    announcement = attr.ib()
+    storage_server = attr.ib()
+
+
+
 @implementer(IFoolscapStoragePlugin)
 class SecureAccessTokenAuthorizer(object):
     """
@@ -38,10 +53,18 @@ class SecureAccessTokenAuthorizer(object):
     name = u"privatestorageio-satauthz-v1"
 
     def get_storage_server(self, configuration, get_anonymous_storage_server):
-        return SecureAccessTokenAuthorizerStorageServer(
+        announcement = {}
+        storage_server = SecureAccessTokenAuthorizerStorageServer(
             get_anonymous_storage_server(),
             **configuration
         )
+        return succeed(
+            AnnounceableStorageServer(
+                announcement,
+                storage_server,
+            ),
+        )
+
 
     def get_storage_client(self, configuration, announcement):
         raise NotImplementedError()
diff --git a/src/_secureaccesstokenauthorizer/_storage_server.py b/src/_secureaccesstokenauthorizer/_storage_server.py
index 075a0fbf216b9f25c55b8d20015bf63892fdc903..79585222ff7af9274791eb260f820749f21b9b24 100644
--- a/src/_secureaccesstokenauthorizer/_storage_server.py
+++ b/src/_secureaccesstokenauthorizer/_storage_server.py
@@ -30,6 +30,7 @@ from foolscap.constraint import (
 )
 from foolscap.api import (
     ListOf,
+    Referenceable,
 )
 from foolscap.remoteinterface import (
     RemoteMethodSchema,
@@ -95,7 +96,7 @@ class RITokenAuthorizedStorageServer(RemoteInterface):
 
 
 @implementer(RITokenAuthorizedStorageServer)
-class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer)):
+class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer), Referenceable):
     def allocate_buckets(self, tokens, *a, **kw):
         self._validate_tokens(tokens)
         return super(SecureAccessTokenAuthorizerStorageServer, self).allocate_buckets(*a, **kw)
diff --git a/src/_secureaccesstokenauthorizer/tests/matchers.py b/src/_secureaccesstokenauthorizer/tests/matchers.py
new file mode 100644
index 0000000000000000000000000000000000000000..29dc8dd46b4070767ca0d896baaff19d0f61f12c
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/tests/matchers.py
@@ -0,0 +1,40 @@
+# Copyright 2019 PrivateStorage.io, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Testtools matchers useful for the test suite.
+"""
+
+import attr
+
+from testtools.matchers import (
+    Mismatch,
+)
+
+@attr.s
+class Provides(object):
+    """
+    Match objects that provide one or more Zope Interface interfaces.
+    """
+    interfaces = attr.ib()
+
+    def match(self, obj):
+        missing = set()
+        for iface in self.interfaces:
+            if not iface.providedBy(obj):
+                missing.add(iface)
+        if missing:
+            return Mismatch("{} does not provide expected {}".format(
+                obj, ", ".join(str(iface) for iface in missing),
+            ))
diff --git a/src/_secureaccesstokenauthorizer/tests/strategies.py b/src/_secureaccesstokenauthorizer/tests/strategies.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb008c7767d77edc061f550523a2475e30acdfe4
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/tests/strategies.py
@@ -0,0 +1,27 @@
+# Copyright 2019 PrivateStorage.io, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Hypothesis strategies for property testing.
+"""
+
+from hypothesis.strategies import (
+    just,
+)
+
+def configurations():
+    """
+    Build configuration values for the plugin.
+    """
+    return just({})
diff --git a/src/_secureaccesstokenauthorizer/tests/test_plugin.py b/src/_secureaccesstokenauthorizer/tests/test_plugin.py
index 2b9913bc58b4208cf1ed67e3a98258bc66d5e054..d57d304cb80a57490d9779a9eafe0af6c41252dd 100644
--- a/src/_secureaccesstokenauthorizer/tests/test_plugin.py
+++ b/src/_secureaccesstokenauthorizer/tests/test_plugin.py
@@ -25,10 +25,24 @@ from testtools import (
 )
 from testtools.matchers import (
     Contains,
+    AfterPreprocessing,
+)
+from testtools.twistedsupport import (
+    succeeded,
+)
+
+from hypothesis import (
+    given,
+)
+
+from foolscap.ipb import (
+    IReferenceable,
+    IRemotelyCallable,
 )
 
 from allmydata.interfaces import (
     IFoolscapStoragePlugin,
+    IAnnounceableStorageServer,
 )
 
 from twisted.plugin import (
@@ -38,6 +52,17 @@ from twisted.plugins.secureaccesstokenauthorizer import (
     storage_server,
 )
 
+from .strategies import (
+    configurations,
+)
+from .matchers import (
+    Provides,
+)
+
+def get_anonymous_storage_server():
+    return None
+
+
 class PluginTests(TestCase):
     """
     Tests for ``twisted.plugins.secureaccesstokenauthorizer.storage_server``.
@@ -57,3 +82,45 @@ class PluginTests(TestCase):
         ``storage_server`` provides ``IFoolscapStoragePlugin``.
         """
         verifyObject(IFoolscapStoragePlugin, storage_server)
+
+
+    @given(configurations())
+    def test_returns_announceable(self, configuration):
+        """
+        ``storage_server.get_storage_server`` returns an instance which provides
+        ``IAnnounceableStorageServer``.
+        """
+        storage_server_deferred = storage_server.get_storage_server(
+            configuration,
+            get_anonymous_storage_server,
+        )
+        self.assertThat(
+            storage_server_deferred,
+            succeeded(Provides([IAnnounceableStorageServer])),
+        )
+
+
+    @given(configurations())
+    def test_returns_referenceable(self, configuration):
+        """
+        The storage server attached to the result of
+        ``storage_server.get_storage_server`` provides ``IReferenceable`` and
+        ``IRemotelyCallable``.
+        """
+        # XXX It's not clear what the actual Foolscap-imposed requirements on
+        # this object should be.  Maybe the two above-mentioned interfaces are
+        # important ... or maybe not?
+
+        storage_server_deferred = storage_server.get_storage_server(
+            configuration,
+            get_anonymous_storage_server,
+        )
+        self.assertThat(
+            storage_server_deferred,
+            succeeded(
+                AfterPreprocessing(
+                    lambda ann: ann.storage_server,
+                    Provides([IReferenceable, IRemotelyCallable]),
+                ),
+            ),
+        )