Refactor hidden fields logic

Rather than the route handlers having to know that `req.fields` exist and passing it to the storage adapter, we instead expose the hidden fields directly to the storage adapter, so the route handlers can just use the `Storage` interface as normal without having to remember to pass through `req.fields`.

This makes hidden fields a mostly Storage-internal implementation, which will hopefully keep the external interface a bit cleaner.