diff --git a/projects/activitypub_relay/relay.sh b/projects/activitypub_relay/relay.sh
index f004c74..6444e60 100755
--- a/projects/activitypub_relay/relay.sh
+++ b/projects/activitypub_relay/relay.sh
@@ -4,4 +4,4 @@ cd "$(realpath $(dirname $0))"
 
 bazel build ...
 
-exec ../../bazel-bin/projects/activitypub_relay/activitypub_relay -c $(realpath ./relay.yaml) run
+exec ../../bazel-bin/projects/activitypub_relay/activitypub_relay -c $(realpath ./relay_prod.yaml) run
diff --git a/projects/activitypub_relay/src/python/relay/__main__.py b/projects/activitypub_relay/src/python/relay/__main__.py
index 87a3fe0..699daee 100644
--- a/projects/activitypub_relay/src/python/relay/__main__.py
+++ b/projects/activitypub_relay/src/python/relay/__main__.py
@@ -357,6 +357,7 @@ def relay_setup(obj: Application):
         obj.config.listen = os.getenv("LISTEN_ADDRESS", obj.config.listen)
         obj.config.port = int(os.getenv("LISTEN_PORT", obj.config.port))
         obj.config.host = os.getenv("RELAY_HOSTNAME")
+        obj.config.admin_token = os.getenv("RELAY_ADMIN_TOKEN")
         if not obj.config.host:
             click.echo("Error: No relay host configured! Set $RELAY_HOSTNAME")
             exit(1)
diff --git a/projects/activitypub_relay/src/python/relay/config.py b/projects/activitypub_relay/src/python/relay/config.py
index 431a674..b40288b 100644
--- a/projects/activitypub_relay/src/python/relay/config.py
+++ b/projects/activitypub_relay/src/python/relay/config.py
@@ -78,6 +78,7 @@ class RelayConfig(DotDict):
                 "json": 1024,
                 "objects": 1024,
                 "digests": 1024,
+                "admin_token": None,
             }
         )
 
diff --git a/projects/activitypub_relay/src/python/relay/misc.py b/projects/activitypub_relay/src/python/relay/misc.py
index 20d67c6..412185f 100644
--- a/projects/activitypub_relay/src/python/relay/misc.py
+++ b/projects/activitypub_relay/src/python/relay/misc.py
@@ -6,6 +6,7 @@ import logging
 import socket
 from urllib.parse import urlparse
 import uuid
+from typing import Union
 
 from Crypto.Hash import SHA, SHA256, SHA512
 from Crypto.PublicKey import RSA
@@ -453,7 +454,7 @@ class Message(DotDict):
 
 class Response(AiohttpResponse):
     @classmethod
-    def new(cls, body="", status=200, headers=None, ctype="text"):
+    def new(cls, body: Union[dict, str, bytes] = "", status=200, headers=None, ctype="text"):
         kwargs = {
             "status": status,
             "headers": headers,
diff --git a/projects/activitypub_relay/src/python/relay/views.py b/projects/activitypub_relay/src/python/relay/views.py
index 5f11990..06b26e5 100644
--- a/projects/activitypub_relay/src/python/relay/views.py
+++ b/projects/activitypub_relay/src/python/relay/views.py
@@ -1,6 +1,6 @@
 import logging
 
-from aiohttp.web import HTTPUnauthorized
+from aiohttp.web import HTTPUnauthorized, Request
 from relay import __version__, misc
 from relay.http_debug import STATS
 from relay.misc import (
@@ -148,7 +148,8 @@ async def inbox(request):
 
 @register_route("GET", "/.well-known/webfinger")
 async def webfinger(request):
-    subject = request.query["resource"]
+    if not (subject := request.query.get("resource")):
+        return Response.new_error(404, "no resource specified", "json")
 
     if subject != f"acct:relay@{request.app.config.host}":
         return Response.new_error(404, "user not found", "json")
@@ -203,5 +204,73 @@ async def nodeinfo_wellknown(request):
 
 
 @register_route("GET", "/stats")
-async def stats(*args, **kwargs):
-    return Response.new(STATS, ctype="json")
+async def stats(request):
+    stats = STATS.copy()
+    stats["pending_requests"] = len(request.app.database.get("follow-requests", {}))
+    return Response.new(stats, ctype="json")
+
+
+@register_route("POST", "/admin/config")
+async def set_config(request: Request):
+    if not (auth := request.headers.get("Authorization")):
+        return Response.new_error(403, "access denied", "json")
+
+    if not auth == f"Bearer {request.app.config.admin_token}":
+        return Response.new_error(403, "access denied", "json")
+
+    # FIXME: config doesn't have a way to go from JSON or update, using dict stuff
+    new_config = await request.json()
+
+    request.app.config.update(new_config)
+
+    # If there are pending follows which are NOW whitelisted, allow them
+    if request.app.config.whitelist_enabled:
+        for domain in request.app.config.whitelist:
+            if (pending_follow := request.app.database.get_request(domain, False)):
+                await misc.request(
+                    actor.shared_inbox,
+                    misc.Message.new_response(
+                        host=request.app.config.host,
+                        actor=pending_follow["actor"],
+                        followid=pending_follow["followid"],
+                        accept=True
+                    ),
+                )
+
+                await misc.request(
+                    actor.shared_inbox,
+                    misc.Message.new_follow(
+                        host=request.app.config.host,
+                        actor=pending_follow["actor"]
+                    ),
+                )
+
+                request.app.database.del_request(domain)
+
+        request.app.database.save()
+
+    request.app.config.save()
+
+    return Response.new(status=202)
+
+
+@register_route("GET", "/admin/config")
+def set_config(request: Request):
+    if not (auth := request.headers.get("Authorization")):
+        return Response.new_error(403, "access denied", "json")
+
+    if not auth == f"Bearer {request.app.config.admin_token}":
+        return Response.new_error(403, "access denied", "json")
+
+    return Response.new(request.app.config, status=200, ctype="json")
+
+
+@register_route("GET", "/admin/pending")
+def get_pending(request):
+    if not (auth := request.headers.get("Authorization")):
+        return Response.new_error(403, "access denied", "json")
+
+    if not auth == f"Bearer {request.app.config.admin_token}":
+        return Response.new_error(403, "access denied", "json")
+
+    return Response.new(request.app.database["follow-requests"], status=200, ctype="json")
diff --git a/projects/shoggoth/src/python/ichor/__main__.py b/projects/shoggoth/src/python/ichor/__main__.py
index db49042..ad3e6f6 100644
--- a/projects/shoggoth/src/python/ichor/__main__.py
+++ b/projects/shoggoth/src/python/ichor/__main__.py
@@ -4,12 +4,8 @@
 ichor entrypoint
 """
 
-from ichor.bootstrap import (
-    BOOTSTRAP,
-    NOT1,
-    TRUE,
-)
 from ichor import isa
+from ichor.bootstrap import BOOTSTRAP, NOT1, TRUE
 from ichor.interpreter import Interpreter
 
 
diff --git a/projects/shoggoth/src/python/shoggoth/analyzer.py b/projects/shoggoth/src/python/shoggoth/analyzer.py
index d11a985..8def210 100644
--- a/projects/shoggoth/src/python/shoggoth/analyzer.py
+++ b/projects/shoggoth/src/python/shoggoth/analyzer.py
@@ -5,6 +5,7 @@
 from abc import ABC
 from dataclasses import dataclass
 import typing as t
+from uuid import UUID
 
 from shoggoth.types import Keyword, List, Symbol
 
@@ -85,12 +86,20 @@ class Multiverse:
 
     """
 
-    soup: t.Dict[]
-
     @dataclass
     class Namespace:
         pass
 
+    @dataclass
+    class Entry:
+        ns: "Namespace"
+        expr: t.Any
+        value: t.Any
+
+    soup: t.Dict[UUID, Entry] = {}
+
+
+
 
 BOOTSTRAP = "lang.shoggoth.v0.bootstrap"
 SPECIALS = Multiverse.Namespace(Symbol(BOOTSTRAP), {