From 2ad1586d00730278cdf3bd3f4ccf91629a01c5b5 Mon Sep 17 00:00:00 2001
From: Eike Kettner <eike.kettner@posteo.de>
Date: Sat, 28 Sep 2019 22:17:45 +0200
Subject: [PATCH] Set stricter compile options and fix cookie data

---
 build.sbt                                     |  8 ++---
 .../scala/docspell/backend/auth/Login.scala   |  4 +--
 .../scala/docspell/backend/ops/OJob.scala     |  2 +-
 .../scala/docspell/common/LenientUri.scala    |  7 ++++
 .../docspell/common/ProcessItemArgs.scala     |  2 +-
 .../main/scala/docspell/joex/JoexServer.scala |  4 +--
 .../docspell/joex/process/CreateItem.scala    | 10 ++++--
 .../docspell/joex/routes/InfoRoutes.scala     |  6 ++--
 .../docspell/joex/routes/JoexRoutes.scala     |  8 ++---
 .../docspell/joex/scheduler/Logger.scala      |  2 +-
 .../docspell/restserver/RestServer.scala      | 36 +++++++++----------
 .../docspell/restserver/auth/CookieData.scala |  7 ++--
 .../restserver/conv/Conversions.scala         |  2 +-
 .../restserver/http4s/ResponseGenerator.scala |  5 +--
 .../restserver/routes/AttachmentRoutes.scala  |  3 +-
 .../restserver/routes/Authenticate.scala      |  2 +-
 .../restserver/routes/CollectiveRoutes.scala  |  5 ++-
 .../restserver/routes/EquipmentRoutes.scala   |  3 +-
 .../restserver/routes/InfoRoutes.scala        |  6 ++--
 .../restserver/routes/ItemRoutes.scala        |  7 ++--
 .../restserver/routes/JobQueueRoutes.scala    |  3 +-
 .../routes/OrganizationRoutes.scala           | 17 +++++----
 .../restserver/routes/PersonRoutes.scala      | 17 +++++----
 .../restserver/routes/SourceRoutes.scala      |  3 +-
 .../restserver/routes/TagRoutes.scala         |  3 +-
 .../restserver/routes/UserRoutes.scala        |  3 +-
 .../restserver/webapp/TemplateRoutes.scala    |  6 ++--
 .../restserver/webapp/WebjarRoutes.scala      |  4 +--
 .../scala/docspell/store/records/RJob.scala   |  2 +-
 29 files changed, 94 insertions(+), 93 deletions(-)

diff --git a/build.sbt b/build.sbt
index 1498df68..cf6055ba 100644
--- a/build.sbt
+++ b/build.sbt
@@ -10,14 +10,14 @@ val sharedSettings = Seq(
     "-deprecation",
     "-encoding", "UTF-8",
     "-language:higherKinds",
-    "-language:postfixOps",
     "-feature",
     "-Werror", // fail when there are warnings
     "-unchecked",
     "-Xlint:_",
-    "-Ywarn-dead-code",
-    "-Ywarn-numeric-widen",
-    "-Ywarn-value-discard"
+    "-Wdead-code",
+    "-Wunused",
+    "-Wvalue-discard",
+    "-Wnumeric-widen"
   ),
   scalacOptions in (Compile, console) :=
     (scalacOptions.value.filter(o => !o.contains("Xlint")) ++ Seq("-Xlint:_,-unused")),
diff --git a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala
index d093b43a..5c75a8bf 100644
--- a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala
+++ b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala
@@ -57,7 +57,7 @@ object Login {
           if (at.sigInvalid(config.serverSecret)) Result.invalidAuth.pure[F]
           else if (at.isExpired(config.sessionValid)) Result.invalidTime.pure[F]
           else Result.ok(at).pure[F]
-        case Left(err) =>
+        case Left(_) =>
           Result.invalidAuth.pure[F]
       }
 
@@ -73,7 +73,7 @@ object Login {
             res   <- if (data.exists(check(up.pass))) okResult
                      else Result.invalidAuth.pure[F]
           } yield res
-        case Left(err) =>
+        case Left(_) =>
           Result.invalidAuth.pure[F]
       }
     }
diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OJob.scala b/modules/backend/src/main/scala/docspell/backend/ops/OJob.scala
index 99d7861a..189123de 100644
--- a/modules/backend/src/main/scala/docspell/backend/ops/OJob.scala
+++ b/modules/backend/src/main/scala/docspell/backend/ops/OJob.scala
@@ -61,7 +61,7 @@ object OJob {
           jobm  = job.filter(canDelete)
           del  <- jobm.traverse(j => RJob.delete(j.id))
         } yield del match {
-          case Some(n) => Right(JobCancelResult.Removed: JobCancelResult)
+          case Some(_) => Right(JobCancelResult.Removed: JobCancelResult)
           case None => Left(mustCancel(job))
         }
 
diff --git a/modules/common/src/main/scala/docspell/common/LenientUri.scala b/modules/common/src/main/scala/docspell/common/LenientUri.scala
index 6754e013..4ea61a32 100644
--- a/modules/common/src/main/scala/docspell/common/LenientUri.scala
+++ b/modules/common/src/main/scala/docspell/common/LenientUri.scala
@@ -39,6 +39,13 @@ case class LenientUri(scheme: NonEmptyList[String]
       rethrow.
       flatMap(url => fs2.io.readInputStream(Sync[F].delay(url.openStream()), chunkSize, blocker, true))
 
+  def host: Option[String] =
+    authority.
+      map(a => a.indexOf(':') match {
+        case -1 => a
+        case n => a.substring(0, n)
+      })
+
   def asString: String = {
     val schemePart = scheme.toList.mkString(":")
     val authPart = authority.map(a => s"//$a").getOrElse("")
diff --git a/modules/common/src/main/scala/docspell/common/ProcessItemArgs.scala b/modules/common/src/main/scala/docspell/common/ProcessItemArgs.scala
index 808449dd..c46164ab 100644
--- a/modules/common/src/main/scala/docspell/common/ProcessItemArgs.scala
+++ b/modules/common/src/main/scala/docspell/common/ProcessItemArgs.scala
@@ -11,7 +11,7 @@ case class ProcessItemArgs(meta: ProcessMeta, files: List[File]) {
       case Nil => s"${meta.sourceAbbrev}: No files"
       case n :: Nil => n
       case n1 :: n2 :: Nil => s"$n1, $n2"
-      case more => s"${files.size} files from ${meta.sourceAbbrev}"
+      case _ => s"${files.size} files from ${meta.sourceAbbrev}"
     }
   }
 
diff --git a/modules/joex/src/main/scala/docspell/joex/JoexServer.scala b/modules/joex/src/main/scala/docspell/joex/JoexServer.scala
index 502ce01e..3dd58806 100644
--- a/modules/joex/src/main/scala/docspell/joex/JoexServer.scala
+++ b/modules/joex/src/main/scala/docspell/joex/JoexServer.scala
@@ -27,8 +27,8 @@ object JoexServer {
       joexApp  <- JoexAppImpl.create[F](cfg, signal, connectEC, blocker)
 
       httpApp = Router(
-        "/api/info" -> InfoRoutes(cfg),
-        "/api/v1" -> JoexRoutes(cfg, joexApp)
+        "/api/info" -> InfoRoutes(),
+        "/api/v1" -> JoexRoutes(joexApp)
       ).orNotFound
 
       // With Middlewares in place
diff --git a/modules/joex/src/main/scala/docspell/joex/process/CreateItem.scala b/modules/joex/src/main/scala/docspell/joex/process/CreateItem.scala
index 878fa519..98cd11fc 100644
--- a/modules/joex/src/main/scala/docspell/joex/process/CreateItem.scala
+++ b/modules/joex/src/main/scala/docspell/joex/process/CreateItem.scala
@@ -25,9 +25,9 @@ object CreateItem {
 
       def fileMetas(itemId: Ident, now: Timestamp) = Stream.emits(ctx.args.files).
         flatMap(f => ctx.store.bitpeace.get(f.fileMetaId.id).map(fm => (f, fm))).
-        collect({ case (f, Some(fm)) if validFiles.contains(fm.mimetype.baseType) => (f, fm) }).
+        collect({ case (f, Some(fm)) if validFiles.contains(fm.mimetype.baseType) => f }).
         zipWithIndex.
-        evalMap({ case ((f, fm), index) =>
+        evalMap({ case (f, index) =>
             Ident.randomId[F].map(id => RAttachment(id, itemId, f.fileMetaId, index.toInt, now, f.name))
         }).
         compile.toVector
@@ -64,7 +64,11 @@ object CreateItem {
     }
 
   private def logDifferences[F[_]: Sync](ctx: Context[F, ProcessItemArgs], saved: Vector[RAttachment], saveCount: Int): F[Unit] =
-    ctx.logger.info("TODO log diffs")
+    if (ctx.args.files.size != saved.size) {
+      ctx.logger.warn(s"Not all given files (${ctx.args.files.size}) have been stored. Files retained: ${saved.size}; saveCount=$saveCount")
+    } else {
+      ().pure[F]
+    }
 
   private def storeItemError[F[_]: Sync](ctx: Context[F, ProcessItemArgs]): F[Unit] = {
     val msg = "Inserting item failed. DB returned 0 update count!"
diff --git a/modules/joex/src/main/scala/docspell/joex/routes/InfoRoutes.scala b/modules/joex/src/main/scala/docspell/joex/routes/InfoRoutes.scala
index e187c987..ec91e40c 100644
--- a/modules/joex/src/main/scala/docspell/joex/routes/InfoRoutes.scala
+++ b/modules/joex/src/main/scala/docspell/joex/routes/InfoRoutes.scala
@@ -1,15 +1,15 @@
 package docspell.joex.routes
 
 import cats.effect.Sync
-import docspell.joex.{BuildInfo, Config}
+import docspell.joex.BuildInfo
 import docspell.joexapi.model.VersionInfo
 import org.http4s.HttpRoutes
-import org.http4s.dsl.Http4sDsl
 import org.http4s.circe.CirceEntityEncoder._
+import org.http4s.dsl.Http4sDsl
 
 object InfoRoutes {
 
-  def apply[F[_]: Sync](cfg: Config): HttpRoutes[F] = {
+  def apply[F[_]: Sync](): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
     HttpRoutes.of[F] {
diff --git a/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala b/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala
index 0e177d2d..aa00f910 100644
--- a/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala
+++ b/modules/joex/src/main/scala/docspell/joex/routes/JoexRoutes.scala
@@ -1,18 +1,18 @@
 package docspell.joex.routes
 
-import cats.implicits._
 import cats.effect._
+import cats.implicits._
 import docspell.common.{Duration, Ident, Timestamp}
-import docspell.joex.{Config, JoexApp}
+import docspell.joex.JoexApp
 import docspell.joexapi.model._
 import docspell.store.records.{RJob, RJobLog}
 import org.http4s.HttpRoutes
-import org.http4s.dsl.Http4sDsl
 import org.http4s.circe.CirceEntityEncoder._
+import org.http4s.dsl.Http4sDsl
 
 object JoexRoutes {
 
-  def apply[F[_]: ConcurrentEffect: Timer](cfg: Config, app: JoexApp[F]): HttpRoutes[F] = {
+  def apply[F[_]: ConcurrentEffect: Timer](app: JoexApp[F]): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
     HttpRoutes.of[F] {
diff --git a/modules/joex/src/main/scala/docspell/joex/scheduler/Logger.scala b/modules/joex/src/main/scala/docspell/joex/scheduler/Logger.scala
index 1b250f4d..4347255a 100644
--- a/modules/joex/src/main/scala/docspell/joex/scheduler/Logger.scala
+++ b/modules/joex/src/main/scala/docspell/joex/scheduler/Logger.scala
@@ -43,7 +43,7 @@ object Logger {
     for {
       q    <- Queue.circularBuffer[F, LogEvent](bufferSize)
       log   = create(jobId, jobInfo, q)
-      fib  <- Concurrent[F].start(q.dequeue.through(sink.receive).compile.drain)
+      _    <- Concurrent[F].start(q.dequeue.through(sink.receive).compile.drain)
     } yield log
 
 }
\ No newline at end of file
diff --git a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala
index f28cbf34..223822be 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala
@@ -2,14 +2,14 @@ package docspell.restserver
 
 import cats.effect._
 import docspell.backend.auth.AuthToken
-import org.http4s.server.blaze.BlazeServerBuilder
-import org.http4s.implicits._
-import fs2.Stream
-import org.http4s.server.middleware.Logger
-import org.http4s.server.Router
-import docspell.restserver.webapp._
 import docspell.restserver.routes._
+import docspell.restserver.webapp._
+import fs2.Stream
 import org.http4s.HttpRoutes
+import org.http4s.implicits._
+import org.http4s.server.Router
+import org.http4s.server.blaze.BlazeServerBuilder
+import org.http4s.server.middleware.Logger
 
 import scala.concurrent.ExecutionContext
 
@@ -22,12 +22,12 @@ object RestServer {
       restApp  <- RestAppImpl.create[F](cfg, connectEC, httpClientEc, blocker)
 
       httpApp = Router(
-        "/api/info" -> routes.InfoRoutes(cfg),
+        "/api/info" -> routes.InfoRoutes(),
         "/api/v1/open/" -> openRoutes(cfg, restApp),
         "/api/v1/sec/" -> Authenticate(restApp.backend.login, cfg.auth) {
           token => securedRoutes(cfg, restApp, token)
         },
-        "/app/assets" -> WebjarRoutes.appRoutes[F](blocker, cfg),
+        "/app/assets" -> WebjarRoutes.appRoutes[F](blocker),
         "/app" -> TemplateRoutes[F](blocker, cfg)
       ).orNotFound
 
@@ -47,16 +47,16 @@ object RestServer {
   def securedRoutes[F[_]: Effect](cfg: Config, restApp: RestApp[F], token: AuthToken): HttpRoutes[F] =
     Router(
       "auth" -> LoginRoutes.session(restApp.backend.login, cfg),
-      "tag" -> TagRoutes(restApp.backend, cfg, token),
-      "equipment" -> EquipmentRoutes(restApp.backend, cfg, token),
-      "organization" -> OrganizationRoutes(restApp.backend, cfg, token),
-      "person" -> PersonRoutes(restApp.backend, cfg, token),
-      "source" -> SourceRoutes(restApp.backend, cfg, token),
-      "user" -> UserRoutes(restApp.backend, cfg, token),
-      "collective" -> CollectiveRoutes(restApp.backend, cfg, token),
-      "queue" -> JobQueueRoutes(restApp.backend, cfg, token),
-      "item" -> ItemRoutes(restApp.backend, cfg, token),
-      "attachment" -> AttachmentRoutes(restApp.backend, cfg, token),
+      "tag" -> TagRoutes(restApp.backend, token),
+      "equipment" -> EquipmentRoutes(restApp.backend, token),
+      "organization" -> OrganizationRoutes(restApp.backend, token),
+      "person" -> PersonRoutes(restApp.backend, token),
+      "source" -> SourceRoutes(restApp.backend, token),
+      "user" -> UserRoutes(restApp.backend, token),
+      "collective" -> CollectiveRoutes(restApp.backend, token),
+      "queue" -> JobQueueRoutes(restApp.backend, token),
+      "item" -> ItemRoutes(restApp.backend, token),
+      "attachment" -> AttachmentRoutes(restApp.backend, token),
       "upload" -> UploadRoutes.secured(restApp.backend, cfg, token)
     )
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/auth/CookieData.scala b/modules/restserver/src/main/scala/docspell/restserver/auth/CookieData.scala
index 862aeada..aee5d998 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/auth/CookieData.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/auth/CookieData.scala
@@ -11,9 +11,10 @@ case class CookieData(auth: AuthToken) {
   def asString: String = auth.asString
 
   def asCookie(cfg: Config): ResponseCookie = {
-    val domain = "" //cfg.baseUrl.hostAndPort
-    val sec = false //cfg.baseUrl.protocol.exists(_.endsWith("s"))
-    ResponseCookie(CookieData.cookieName, asString, domain = Some(domain), path = Some("/api/v1"), httpOnly = true, secure = sec)
+    val domain = cfg.baseUrl.host
+    val sec = cfg.baseUrl.scheme.exists(_.endsWith("s"))
+    val path = cfg.baseUrl.path/"api"/"v1"/"sec"
+    ResponseCookie(CookieData.cookieName, asString, domain = domain, path = Some(path.asString), httpOnly = true, secure = sec)
   }
 }
 object CookieData {
diff --git a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala
index 2beecc99..0ba71b32 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala
@@ -243,7 +243,7 @@ trait Conversions {
 
   def newUser[F[_]: Sync](u: User, cid: Ident): F[RUser] =
     timeId.map { case (id, now) =>
-      RUser(id, u.login, cid, u.password.getOrElse(Password.empty), u.state, u.email, u.loginCount, u.lastLogin, u.created)
+      RUser(id, u.login, cid, u.password.getOrElse(Password.empty), u.state, u.email, 0, None, now)
     }
 
   def changeUser(u: User, cid: Ident): RUser =
diff --git a/modules/restserver/src/main/scala/docspell/restserver/http4s/ResponseGenerator.scala b/modules/restserver/src/main/scala/docspell/restserver/http4s/ResponseGenerator.scala
index 629a22f4..06f26ab1 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/http4s/ResponseGenerator.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/http4s/ResponseGenerator.scala
@@ -1,5 +1,6 @@
 package docspell.restserver.http4s
 
+import cats.implicits._
 import cats.Applicative
 import org.http4s.{EntityEncoder, Header, Response}
 import org.http4s.dsl.Http4sDsl
@@ -16,14 +17,14 @@ trait ResponseGenerator[F[_]] {
       e.fold(
         a => UnprocessableEntity(a),
         b => Ok(b)
-      )
+      ).map(_.withHeaders(headers: _*))
   }
 
   implicit final class OptionResponse[A](o: Option[A]) {
     def toResponse(headers: Header*)
                   (implicit F: Applicative[F]
                   , w0: EntityEncoder[F, A]): F[Response[F]] =
-      o.map(a => Ok(a)).getOrElse(NotFound())
+      o.map(a => Ok(a)).getOrElse(NotFound()).map(_.withHeaders(headers: _*))
   }
 
 }
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala
index d1f8629f..525699f8 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala
@@ -12,13 +12,12 @@ import org.http4s.dsl.Http4sDsl
 import org.http4s.headers._
 import org.http4s.circe.CirceEntityEncoder._
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions
 import org.http4s.headers.ETag.EntityTag
 
 object AttachmentRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/Authenticate.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/Authenticate.scala
index 56bc08d3..9d958ce0 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/Authenticate.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/Authenticate.scala
@@ -15,7 +15,7 @@ object Authenticate {
   def authenticateRequest[F[_]: Effect](auth: String => F[Login.Result])(req: Request[F]): F[Login.Result] =
     CookieData.authenticator(req) match {
       case Right(str) => auth(str)
-      case Left(err) => Login.Result.invalidAuth.pure[F]
+      case Left(_) => Login.Result.invalidAuth.pure[F]
     }
 
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala
index 863ceecc..7b36fa37 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala
@@ -5,17 +5,16 @@ import cats.implicits._
 import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions
 import docspell.restserver.http4s.ResponseGenerator
 import org.http4s.HttpRoutes
-import org.http4s.circe.CirceEntityEncoder._
 import org.http4s.circe.CirceEntityDecoder._
+import org.http4s.circe.CirceEntityEncoder._
 import org.http4s.dsl.Http4sDsl
 
 object CollectiveRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F] with ResponseGenerator[F] {}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala
index ced18702..5f276eff 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/EquipmentRoutes.scala
@@ -6,7 +6,6 @@ import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.common.Ident
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions._
 import org.http4s.HttpRoutes
 import org.http4s.circe.CirceEntityDecoder._
@@ -15,7 +14,7 @@ import org.http4s.dsl.Http4sDsl
 
 object EquipmentRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/InfoRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/InfoRoutes.scala
index 2b79c026..978faad3 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/InfoRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/InfoRoutes.scala
@@ -2,14 +2,14 @@ package docspell.restserver.routes
 
 import cats.effect.Sync
 import docspell.restapi.model.VersionInfo
-import docspell.restserver.{BuildInfo, Config}
-import org.http4s.circe.CirceEntityEncoder._
+import docspell.restserver.BuildInfo
 import org.http4s.HttpRoutes
+import org.http4s.circe.CirceEntityEncoder._
 import org.http4s.dsl.Http4sDsl
 
 object InfoRoutes {
 
-  def apply[F[_]: Sync](cfg: Config): HttpRoutes[F] = {
+  def apply[F[_]: Sync](): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
     HttpRoutes.of[F] {
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala
index ad70e74e..eb6b91fa 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala
@@ -10,7 +10,6 @@ import org.http4s.dsl.Http4sDsl
 import org.http4s.circe.CirceEntityEncoder._
 import org.http4s.circe.CirceEntityDecoder._
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.common.syntax.all._
 import docspell.restserver.conv.Conversions
 import org.log4s._
@@ -18,7 +17,7 @@ import org.log4s._
 object ItemRoutes {
   private[this] val logger = getLogger
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
 
@@ -40,13 +39,13 @@ object ItemRoutes {
           resp   <- result.map(r => Ok(r)).getOrElse(NotFound(BasicResult(false, "Not found.")))
         } yield resp
 
-      case req@POST -> Root / Ident(id) / "confirm" =>
+      case POST -> Root / Ident(id) / "confirm" =>
         for {
           res  <- backend.item.setState(id, ItemState.Confirmed, user.account.collective)
           resp <- Ok(Conversions.basicResult(res, "Item data confirmed"))
         } yield resp
 
-      case req@POST -> Root / Ident(id) / "unconfirm" =>
+      case POST -> Root / Ident(id) / "unconfirm" =>
         for {
           res  <- backend.item.setState(id, ItemState.Created, user.account.collective)
           resp <- Ok(Conversions.basicResult(res, "Item back to created."))
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/JobQueueRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/JobQueueRoutes.scala
index d7951460..4539e90b 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/JobQueueRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/JobQueueRoutes.scala
@@ -5,7 +5,6 @@ import cats.implicits._
 import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.common.Ident
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions
 import org.http4s.HttpRoutes
 import org.http4s.circe.CirceEntityEncoder._
@@ -13,7 +12,7 @@ import org.http4s.dsl.Http4sDsl
 
 object JobQueueRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F] {}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala
index 31bb782c..ee56422c 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/OrganizationRoutes.scala
@@ -4,19 +4,18 @@ import cats.effect._
 import cats.implicits._
 import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
-import org.http4s.HttpRoutes
-import org.http4s.dsl.Http4sDsl
-import org.http4s.circe.CirceEntityEncoder._
-import org.http4s.circe.CirceEntityDecoder._
-import docspell.restapi.model._
-import docspell.restserver.Config
-import docspell.restserver.conv.Conversions._
-import ParamDecoder._
 import docspell.common.Ident
+import docspell.restapi.model._
+import docspell.restserver.conv.Conversions._
+import docspell.restserver.routes.ParamDecoder._
+import org.http4s.HttpRoutes
+import org.http4s.circe.CirceEntityDecoder._
+import org.http4s.circe.CirceEntityEncoder._
+import org.http4s.dsl.Http4sDsl
 
 object OrganizationRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala
index d49747e9..d69ecf31 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/PersonRoutes.scala
@@ -4,22 +4,21 @@ import cats.effect._
 import cats.implicits._
 import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
-import org.http4s.HttpRoutes
-import org.http4s.dsl.Http4sDsl
-import org.http4s.circe.CirceEntityEncoder._
-import org.http4s.circe.CirceEntityDecoder._
-import docspell.restapi.model._
-import docspell.restserver.Config
-import docspell.restserver.conv.Conversions._
 import docspell.common.Ident
 import docspell.common.syntax.all._
-import ParamDecoder._
+import docspell.restapi.model._
+import docspell.restserver.conv.Conversions._
+import docspell.restserver.routes.ParamDecoder._
+import org.http4s.HttpRoutes
+import org.http4s.circe.CirceEntityDecoder._
+import org.http4s.circe.CirceEntityEncoder._
+import org.http4s.dsl.Http4sDsl
 import org.log4s._
 
 object PersonRoutes {
   private[this] val logger = getLogger
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F]{}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/SourceRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/SourceRoutes.scala
index 13e80289..b90640a1 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/SourceRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/SourceRoutes.scala
@@ -6,7 +6,6 @@ import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.common.Ident
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions._
 import docspell.restserver.http4s.ResponseGenerator
 import org.http4s.HttpRoutes
@@ -16,7 +15,7 @@ import org.http4s.dsl.Http4sDsl
 
 object SourceRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F] with ResponseGenerator[F] {}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/TagRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/TagRoutes.scala
index 7cc2879d..3efdae72 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/TagRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/TagRoutes.scala
@@ -6,7 +6,6 @@ import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.common.Ident
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions._
 import docspell.restserver.http4s.ResponseGenerator
 import org.http4s.HttpRoutes
@@ -16,7 +15,7 @@ import org.http4s.dsl.Http4sDsl
 
 object TagRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F] with ResponseGenerator[F] {}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala
index cfe26fcb..bb6f154d 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/routes/UserRoutes.scala
@@ -6,7 +6,6 @@ import docspell.backend.BackendApp
 import docspell.backend.auth.AuthToken
 import docspell.common.Ident
 import docspell.restapi.model._
-import docspell.restserver.Config
 import docspell.restserver.conv.Conversions._
 import docspell.restserver.http4s.ResponseGenerator
 import org.http4s.HttpRoutes
@@ -16,7 +15,7 @@ import org.http4s.dsl.Http4sDsl
 
 object UserRoutes {
 
-  def apply[F[_]: Effect](backend: BackendApp[F], cfg: Config, user: AuthToken): HttpRoutes[F] = {
+  def apply[F[_]: Effect](backend: BackendApp[F], user: AuthToken): HttpRoutes[F] = {
     val dsl = new Http4sDsl[F] with ResponseGenerator[F] {}
     import dsl._
 
diff --git a/modules/restserver/src/main/scala/docspell/restserver/webapp/TemplateRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/webapp/TemplateRoutes.scala
index f603a3d1..5e734c8c 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/webapp/TemplateRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/webapp/TemplateRoutes.scala
@@ -36,7 +36,7 @@ object TemplateRoutes {
       case GET -> Root / "doc" =>
         for {
           templ  <- docTemplate
-          resp   <- Ok(DocData(cfg).render(templ), `Content-Type`(`text/html`))
+          resp   <- Ok(DocData().render(templ), `Content-Type`(`text/html`))
         } yield resp
     }
   }
@@ -51,7 +51,7 @@ object TemplateRoutes {
   }
 
   def loadUrl[F[_]: Sync](url: URL, blocker: Blocker)(implicit C: ContextShift[F]): F[String] =
-    Stream.bracket(Sync[F].delay(url.openStream))(in => Sync[F].delay(in.close)).
+    Stream.bracket(Sync[F].delay(url.openStream))(in => Sync[F].delay(in.close())).
       flatMap(in => io.readInputStream(in.pure[F], 64 * 1024, blocker, false)).
       through(text.utf8Decode).
       compile.fold("")(_ + _)
@@ -75,7 +75,7 @@ object TemplateRoutes {
   case class DocData(swaggerRoot: String, openapiSpec: String)
   object DocData {
 
-    def apply(cfg: Config): DocData =
+    def apply(): DocData =
       DocData("/app/assets" + Webjars.swaggerui, s"/app/assets/${BuildInfo.name}/${BuildInfo.version}/docspell-openapi.yml")
 
     implicit def yamuscaValueConverter: ValueConverter[DocData] =
diff --git a/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala
index 38c2ed8e..2becf5ea 100644
--- a/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala
+++ b/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala
@@ -7,11 +7,9 @@ import org.http4s.server.staticcontent.webjarService
 import org.http4s.server.staticcontent.NoopCacheStrategy
 import org.http4s.server.staticcontent.WebjarService.{WebjarAsset, Config => WebjarConfig}
 
-import docspell.restserver.Config
-
 object WebjarRoutes {
 
-  def appRoutes[F[_]: Effect](blocker: Blocker, cfg: Config)(implicit C: ContextShift[F]): HttpRoutes[F] = {
+  def appRoutes[F[_]: Effect](blocker: Blocker)(implicit C: ContextShift[F]): HttpRoutes[F] = {
     webjarService(
       WebjarConfig(
         filter = assetFilter,
diff --git a/modules/store/src/main/scala/docspell/store/records/RJob.scala b/modules/store/src/main/scala/docspell/store/records/RJob.scala
index d3247fb4..07d5bcad 100644
--- a/modules/store/src/main/scala/docspell/store/records/RJob.scala
+++ b/modules/store/src/main/scala/docspell/store/records/RJob.scala
@@ -109,7 +109,7 @@ object RJob {
   def setScheduled(jobId: Ident, workerId: Ident): ConnectionIO[Int] = {
     for {
       _   <- incrementRetries(jobId)
-      n   <- updateRow(table, and(id is jobId, or(worker isNull, worker is workerId), state isOneOf Seq[JobState](JobState.Waiting, JobState.Stuck)), commas(
+      n   <- updateRow(table, and(id is jobId, or(worker.isNull, worker is workerId), state isOneOf Seq[JobState](JobState.Waiting, JobState.Stuck)), commas(
         state setTo (JobState.Scheduled: JobState),
         worker setTo workerId
       )).update.run