Repository: google/exposure-notifications-server
Pull request #1373 (2021-02-12 16:05:03)

Switch linting to GitHub Actions
Also fix issues identified by linter

**Release Note**

<!-- Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". -->

```release-note
Switch linting to GitHub Actions
```

google-oss-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/google/exposure-notifications-server/pull/1373#" title="Author self-approved">sethvargo</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **mikehelmick** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @mikehelmick` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=google%2Fexposure-notifications-server).

<details open>
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/google/exposure-notifications-server/blob/main/OWNERS)~~ [sethvargo]
- **[internal/pb/export/OWNERS](https://github.com/google/exposure-notifications-server/blob/main/internal/pb/export/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["mikehelmick"]} -->
google-oss-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/google/exposure-notifications-server/pull/1373#" title="Author self-approved">sethvargo</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=google%2Fexposure-notifications-server).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/google/exposure-notifications-server/blob/main/OWNERS)~~ [sethvargo]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
sethvargo: /assign @mikehelmick 
/assign @whaught 
google-oss-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/google/exposure-notifications-server/pull/1373#" title="Author self-approved">sethvargo</a>*, *<a href="https://github.com/google/exposure-notifications-server/pull/1373#pullrequestreview-589623097" title="Approved">whaught</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=google%2Fexposure-notifications-server).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/google/exposure-notifications-server/blob/main/OWNERS)~~ [sethvargo,whaught]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/.github/workflows/codereview.yaml b/.github/workflows/codereview.yaml
index 2f135dc..b473b0e 100644
--- a/.github/workflows/codereview.yaml
+++ b/.github/workflows/codereview.yaml
@@ -6,17 +6,35 @@ on:
     - 'main'
 
 jobs:
-  only-user-errors:
-    name: errorw-bot
+  golangci-lint:
+    name: go-lint
     runs-on: ubuntu-latest
 
+    steps:
+      - name: Check out code
+        uses: actions/checkout@v2
+
+      - name: lint
+        uses: golangci/golangci-lint-action@v2
+        with:
+          version: v1.36.0
+          only-new-issues: true
+
+  reviewdog:
+    name: reviewdog
+    runs-on: ubuntu-latest
+    continue-on-error: true
+
     steps:
       - name: Check out code
         uses: actions/checkout@v2
 
       - uses: reviewdog/action-setup@v1
 
-      - name: Check
+      - name: Install pcregrep
+        run: sudo apt-get -yqq install pcregrep
+
+      - name: errorw
         shell: bash
         env:
           REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
@@ -32,17 +50,7 @@ jobs:
             -fail-on-error="false" \
             -level="warning"
 
-  copyright-check:
-    name: copyright-check
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Check out code
-        uses: actions/checkout@v2
-
-      - uses: reviewdog/action-setup@v1
-
-      - name: Check
+      - name: copyright-check
         shell: bash
         env:
           REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
@@ -59,6 +67,23 @@ jobs:
             -fail-on-error="true" \
             -level="error"
 
+      - name: tab-check
+        shell: bash
+        env:
+          REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
+        run: |-
+          set -eEu
+          set +o pipefail
+
+          YEAR=$(date +"%Y")
+          make tabcheck | \
+          reviewdog -efm="%f:%l:%m" \
+            -name="tab-check" \
+            -reporter="github-pr-review" \
+            -filter-mode="diff_context" \
+            -fail-on-error="true" \
+            -level="error"
+
   zap-logger:
     name: zap-logger
     runs-on: ubuntu-latest
diff --git a/.golangci.yaml b/.golangci.yaml
new file mode 100644
index 0000000..4bfd14c
--- /dev/null
+++ b/.golangci.yaml
@@ -0,0 +1,94 @@
+# Copyright 2021 Google 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.
+
+run:
+  # default: '1m'
+  timeout: '5m'
+
+  # default: []
+  build-tags:
+  - 'all'
+
+  # default: []
+  skip-dirs:
+  - 'internal/pb'
+
+  # default: true
+  skip-dirs-use-default: false
+
+  # default: ''
+  modules-download-mode: 'readonly'
+
+  # default: false
+  allow-parallel-runners: true
+
+linters:
+  enable:
+  - 'asciicheck'
+  - 'bodyclose'
+  - 'deadcode'
+  - 'depguard'
+  - 'dogsled'
+  - 'errcheck'
+  - 'errorlint'
+  - 'exportloopref'
+  - 'gofmt'
+  - 'gofumpt'
+  - 'goheader'
+  - 'goimports'
+  - 'golint'
+  - 'gomodguard'
+  - 'goprintffuncname'
+  - 'gosec'
+  - 'gosimple'
+  - 'govet'
+  - 'ineffassign'
+  - 'interfacer'
+  - 'makezero'
+  - 'misspell'
+  - 'noctx'
+  - 'nolintlint'
+  - 'paralleltest'
+  - 'prealloc'
+  - 'predeclared'
+  - 'scopelint'
+  - 'sqlclosecheck'
+  - 'staticcheck'
+  - 'structcheck'
+  - 'stylecheck'
+  - 'typecheck'
+  - 'unconvert'
+  - 'unused'
+  - 'varcheck'
+  - 'whitespace'
+
+issues:
+  # default: []
+  exclude:
+  - '^S1023:' # staticcheck: redundant returns help with http handlers
+  - '^SA3000:' # staticcheck: not required in Go 11.4+
+  - '^G102:' # gosec: we have to bind to all ifaces
+  - '^G402:' # gosec: some services terminate at the load balancer
+  - '^G505:' # gosec: we use crypto/sha1 for some HMACs
+  - '^Range statement' # paralleltest: false positives
+
+  # default: 50
+  max-issues-per-linter: 0
+
+  # default: 3
+  max-same-issues: 0
+
+severity:
+  # default: ''
+  default-severity: error
diff --git a/Makefile b/Makefile
index 8a81802..cccbcd1 100644
--- a/Makefile
+++ b/Makefile
@@ -12,51 +12,32 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-VETTERS = "asmdecl,assign,atomic,bools,buildtag,cgocall,composites,copylocks,errorsas,httpresponse,loopclosure,lostcancel,nilfunc,printf,shift,stdmethods,structtag,tests,unmarshal,unreachable,unsafeptr,unusedresult"
 GOFMT_FILES = $(shell go list -f '{{.Dir}}' ./... | grep -v '/pb')
+HTML_FILES = $(shell find . -name \*.html)
 GO_FILES = $(shell find . -name \*.go)
-
-bodyclose:
-	@command -v bodyclose > /dev/null 2>&1 || go get github.com/timakin/bodyclose
-	@go vet -tags=all -vettool=$$(which bodyclose) ./...
-.PHONY: bodyclose
-
-fmtcheck:
-	@command -v goimports > /dev/null 2>&1 || go get golang.org/x/tools/cmd/goimports
-	@CHANGES="$$(goimports -d $(GOFMT_FILES))"; \
-		if [ -n "$${CHANGES}" ]; then \
-			echo "Unformatted (run goimports -w .):\n\n$${CHANGES}\n\n"; \
-			exit 1; \
-		fi
-	@# Annoyingly, goimports does not support the simplify flag.
-	@CHANGES="$$(gofmt -s -d $(GOFMT_FILES))"; \
-		if [ -n "$${CHANGES}" ]; then \
-			echo "Unformatted (run gofmt -s -w .):\n\n$${CHANGES}\n\n"; \
+MD_FILES = $(shell find . -name \*.md)
+
+# lint uses the same linter as CI and tries to report the same results running
+# locally. There is a chance that CI detects linter errors that are not found
+# locally, but it should be rare.
+lint:
+	@command -v golangci-lint > /dev/null 2>&1 || GO111MODULE=off go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.36.0
+	golangci-lint run --config .golangci.yaml
+.PHONY: lint
+
+tabcheck:
+	@FINDINGS="$$(awk '/\t/ {printf "%s:%s:found tab character\n",FILENAME,FNR}' $(HTML_FILES))"; \
+		if [ -n "$${FINDINGS}" ]; then \
+			echo "$${FINDINGS}\n\n"; \
 			exit 1; \
 		fi
-.PHONY: fmtcheck
-
-spellcheck:
-	@command -v misspell > /dev/null 2>&1 || go get github.com/client9/misspell/cmd/misspell
-	@misspell -locale="US" -error -source="text" **/*
-.PHONY: spellcheck
-
-# SA3000 is not required in Go 1.15+: https://github.com/dominikh/go-tools/issues/708
-staticcheck:
-	@command -v staticcheck > /dev/null 2>&1 || go get honnef.co/go/tools/cmd/staticcheck
-	@staticcheck -tags=all -checks="all,-SA3000" -tests $(GOFMT_FILES)
-.PHONY: staticcheck
-
-zapcheck:
-	@command -v zapw > /dev/null 2>&1 || GO111MODULE=off go get github.com/sethvargo/zapw/cmd/zapw
-	@zapw ./...
+.PHONY: tabcheck
 
 test:
 	@go test \
 		-count=1 \
 		-short \
 		-timeout=5m \
-		-vet="${VETTERS}" \
 		./...
 .PHONY: test
 
@@ -65,7 +46,6 @@ test-acc:
 		-count=1 \
 		-race \
 		-timeout=10m \
-		-vet="${VETTERS}" \
 		./... \
 		-coverprofile=coverage.out
 .PHONY: test-acc
@@ -73,3 +53,8 @@ test-acc:
 test-coverage:
 	@go tool cover -func ./coverage.out | grep total
 .PHONY: test-coverage
+
+zapcheck:
+	@command -v zapw > /dev/null 2>&1 || GO111MODULE=off go get github.com/sethvargo/zapw/cmd/zapw
+	@zapw ./...
+.PHONY: zapcheck
diff --git a/cmd/admin-console/templates/export.html b/cmd/admin-console/templates/export.html
index bdbe40b..733a903 100644
--- a/cmd/admin-console/templates/export.html
+++ b/cmd/admin-console/templates/export.html
@@ -51,7 +51,7 @@
           <option value="false" {{if not .export.IncludeTravelers}}selected{{end}}>No</option>
         </select>
         <small class="form-text text-muted">
-          Should federeated-in traveler keys be included in this export. If this
+          Should federated-in traveler keys be included in this export. If this
           server is sharing keys with anouther server, the recommended setting
           is 'yes'. Even if you are not yet federating, but may in the future,
           'yes' is still the recommended setting.
@@ -65,9 +65,8 @@
           <option value="false" {{if not .export.OnlyNonTravelers}}selected{{end}}>No</option>
         </select>
         <small class="form-text text-muted">
-		  Should only federeated-in non-traveler keys be included in this
-		  export. Note, setting this with 'Include Travelers' will result in an
-		  error.
+          Should only federated-in non-traveler keys be included in this export.
+          Note, setting this with 'Include Travelers' will result in an error.
         </small>
       </div>
 
@@ -77,7 +76,7 @@
         <label for="exclude-regions">Exclude regions</label>
         <small class="form-text text-muted">
           One per line, leave blank for only using the output region (above).
-		  Allows you to exclude travelers from certain regions.
+          Allows you to exclude travelers from certain regions.
         </small>
       </div>
 
diff --git a/internal/admin/config.go b/internal/admin/config.go
index 68e10f5..9377d62 100644
--- a/internal/admin/config.go
+++ b/internal/admin/config.go
@@ -29,10 +29,12 @@ import (
 	"github.com/google/exposure-notifications-server/pkg/secrets"
 )
 
-var _ setup.BlobstoreConfigProvider = (*Config)(nil)
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.KeyManagerConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.BlobstoreConfigProvider     = (*Config)(nil)
+	_ setup.DatabaseConfigProvider      = (*Config)(nil)
+	_ setup.KeyManagerConfigProvider    = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider = (*Config)(nil)
+)
 
 type Config struct {
 	Database      database.Config
diff --git a/internal/admin/handle_health_authority.go b/internal/admin/handle_health_authority.go
index 53fc372..7acc643 100644
--- a/internal/admin/handle_health_authority.go
+++ b/internal/admin/handle_health_authority.go
@@ -141,7 +141,6 @@ func (s *Server) HandleHealthAuthorityKeys() func(c *gin.Context) {
 				ErrorPage(c, fmt.Sprintf("Error saving health authority key: %v", err))
 				return
 			}
-
 		} else if action == "revoke" || action == "reinstate" || action == "activate" {
 			version := c.Param("version")
 
@@ -173,7 +172,6 @@ func (s *Server) HandleHealthAuthorityKeys() func(c *gin.Context) {
 				ErrorPage(c, fmt.Sprintf("Error saving health authority key: %v", err))
 				return
 			}
-
 		} else {
 			ErrorPage(c, "invalid action")
 			return
diff --git a/internal/authorizedapp/database/authorized_app.go b/internal/authorizedapp/database/authorized_app.go
index 7198987..497e803 100644
--- a/internal/authorizedapp/database/authorized_app.go
+++ b/internal/authorizedapp/database/authorized_app.go
@@ -57,7 +57,6 @@ func (aa *AuthorizedAppDB) InsertAuthorizedApp(ctx context.Context, m *model.Aut
 		`, m.AppPackageName, m.AllAllowedRegions(),
 			m.AllAllowedHealthAuthorityIDs(), m.BypassHealthAuthorityVerification,
 			m.BypassRevisionToken)
-
 		if err != nil {
 			return fmt.Errorf("inserting authorizedapp: %w", err)
 		}
diff --git a/internal/authorizedapp/database_provider.go b/internal/authorizedapp/database_provider.go
index 3004911..defd788 100644
--- a/internal/authorizedapp/database_provider.go
+++ b/internal/authorizedapp/database_provider.go
@@ -80,7 +80,6 @@ func (p *DatabaseProvider) AppConfig(ctx context.Context, name string) (*model.A
 		return config, nil
 	}
 	cached, err := p.cache.WriteThruLookup(name, lookup)
-
 	// Indicates an error on the write thru lookup.
 	if err != nil {
 		return nil, err
diff --git a/internal/cleanup/config.go b/internal/cleanup/config.go
index 65879fd..7225c05 100644
--- a/internal/cleanup/config.go
+++ b/internal/cleanup/config.go
@@ -25,10 +25,12 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.BlobstoreConfigProvider = (*Config)(nil)
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+var (
+	_ setup.BlobstoreConfigProvider             = (*Config)(nil)
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables for
 // the cleanup components.
diff --git a/internal/database/connection.go b/internal/database/connection.go
index 3bd13f8..1c74add 100644
--- a/internal/database/connection.go
+++ b/internal/database/connection.go
@@ -52,7 +52,7 @@ func NewFromEnv(ctx context.Context, cfg *Config) (*DB, error) {
 
 	pool, err := pgxpool.ConnectConfig(ctx, pgxConfig)
 	if err != nil {
-		return nil, fmt.Errorf("failed to create connection pool: %v", err)
+		return nil, fmt.Errorf("failed to create connection pool: %w", err)
 	}
 
 	return &DB{Pool: pool}, nil
diff --git a/internal/database/database_util.go b/internal/database/database_util.go
index c726291..8d9cdba 100644
--- a/internal/database/database_util.go
+++ b/internal/database/database_util.go
@@ -62,10 +62,8 @@ const (
 	defaultPostgresImageRef = "postgres:13-alpine"
 )
 
-var (
-	// ApproxTime is a compare helper for clock skew.
-	ApproxTime = cmp.Options{cmpopts.EquateApproxTime(1 * time.Second)}
-)
+// ApproxTime is a compare helper for clock skew.
+var ApproxTime = cmp.Options{cmpopts.EquateApproxTime(1 * time.Second)}
 
 // TestInstance is a wrapper around the Docker-based database instance.
 type TestInstance struct {
diff --git a/internal/debugger/config.go b/internal/debugger/config.go
index 8de29ab..5c6904d 100644
--- a/internal/debugger/config.go
+++ b/internal/debugger/config.go
@@ -24,11 +24,13 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.AuthorizedAppConfigProvider = (*Config)(nil)
-var _ setup.BlobstoreConfigProvider = (*Config)(nil)
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.KeyManagerConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.AuthorizedAppConfigProvider = (*Config)(nil)
+	_ setup.BlobstoreConfigProvider     = (*Config)(nil)
+	_ setup.DatabaseConfigProvider      = (*Config)(nil)
+	_ setup.KeyManagerConfigProvider    = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables.
 type Config struct {
diff --git a/internal/debugger/handler_debug.go b/internal/debugger/handler_debug.go
index c0cc7c5..41f7710 100644
--- a/internal/debugger/handler_debug.go
+++ b/internal/debugger/handler_debug.go
@@ -208,7 +208,11 @@ func cloudRunEnv(ctx context.Context, name string) (map[string]string, error) {
 	// Lookup service to get revision
 	serviceURL := fmt.Sprintf("https://%s-run.googleapis.com/apis/serving.knative.dev/v1/namespaces/%s/services/%s",
 		region, project, name)
-	serviceResp, err := client.Get(serviceURL)
+	serviceReq, err := http.NewRequestWithContext(ctx, "GET", serviceURL, nil)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create service request: %w", err)
+	}
+	serviceResp, err := client.Do(serviceReq)
 	if err != nil {
 		return nil, fmt.Errorf("failed to lookup service: %w", err)
 	}
@@ -227,7 +231,11 @@ func cloudRunEnv(ctx context.Context, name string) (map[string]string, error) {
 	// Lookup revision to get environment.
 	revisionURL := fmt.Sprintf("https://%s-run.googleapis.com/apis/serving.knative.dev/v1/namespaces/%s/revisions/%s",
 		region, project, s.Status.Revision)
-	revisionResp, err := client.Get(revisionURL)
+	revisionReq, err := http.NewRequestWithContext(ctx, "GET", revisionURL, nil)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create revision request: %w", err)
+	}
+	revisionResp, err := client.Do(revisionReq)
 	if err != nil {
 		return nil, fmt.Errorf("failed to lookup revision: %w", err)
 	}
diff --git a/internal/export/batcher.go b/internal/export/batcher.go
index 5ca7d53..f85d93f 100644
--- a/internal/export/batcher.go
+++ b/internal/export/batcher.go
@@ -128,7 +128,7 @@ func (s *Server) maybeCreateBatches(ctx context.Context, ec *model.ExportConfig,
 		return 0, nil
 	}
 
-	var batches []*model.ExportBatch
+	batches := make([]*model.ExportBatch, 0, len(ranges))
 	for _, br := range ranges {
 		infoIds := make([]int64, len(ec.SignatureInfoIDs))
 		copy(infoIds, ec.SignatureInfoIDs)
diff --git a/internal/export/config.go b/internal/export/config.go
index 33df61a..18c1258 100644
--- a/internal/export/config.go
+++ b/internal/export/config.go
@@ -27,11 +27,13 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.BlobstoreConfigProvider = (*Config)(nil)
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.KeyManagerConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+var (
+	_ setup.BlobstoreConfigProvider             = (*Config)(nil)
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.KeyManagerConfigProvider            = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables for
 // the export components.
diff --git a/internal/export/database/export.go b/internal/export/database/export.go
index 2c0e811..b9dd8cb 100644
--- a/internal/export/database/export.go
+++ b/internal/export/database/export.go
@@ -26,6 +26,7 @@ import (
 	"github.com/google/exposure-notifications-server/internal/database"
 	"github.com/google/exposure-notifications-server/internal/export/model"
 	"github.com/google/exposure-notifications-server/internal/storage"
+	"github.com/google/exposure-notifications-server/pkg/cryptorand"
 	"github.com/google/exposure-notifications-server/pkg/logging"
 
 	pgx "github.com/jackc/pgx/v4"
@@ -554,9 +555,11 @@ func (db *ExportDB) LeaseBatch(ctx context.Context, ttl time.Duration, batchMaxC
 	}
 
 	// Randomize openBatchIDs so that workers aren't competing for the same job.
-	openBatchIDs = shuffle(openBatchIDs)
+	shuffle(openBatchIDs)
 
 	for _, bid := range openBatchIDs {
+		bid := bid
+
 		// In a serialized transaction, fetch the existing batch and make sure it can be leased, then lease it.
 		leased := false
 		err := db.db.InTx(ctx, pgx.ReadCommitted, func(tx pgx.Tx) error {
@@ -639,7 +642,7 @@ func lookupExportBatch(ctx context.Context, batchID int64, queryRow queryRowFn)
 	var expires *time.Time
 	eb := model.ExportBatch{}
 	if err := row.Scan(&eb.BatchID, &eb.ConfigID, &eb.BucketName, &eb.FilenameRoot, &eb.StartTimestamp, &eb.EndTimestamp, &eb.OutputRegion, &eb.Status, &expires, &eb.SignatureInfoIDs, &eb.InputRegions, &eb.IncludeTravelers, &eb.ExcludeRegions, &eb.OnlyNonTravelers, &eb.MaxRecordsOverride); err != nil {
-		if err == pgx.ErrNoRows {
+		if errors.Is(err, pgx.ErrNoRows) {
 			return nil, database.ErrNotFound
 		}
 		return nil, err
@@ -669,7 +672,7 @@ func (db *ExportDB) FinalizeBatch(ctx context.Context, eb *model.ExportBatch, fi
 				Status:           model.ExportBatchComplete,
 			}
 			if err := addExportFile(ctx, tx, &ef); err != nil {
-				if err == database.ErrKeyConflict {
+				if errors.Is(err, database.ErrKeyConflict) {
 					logging.FromContext(ctx).Infof("ExportFile %q already exists in database, skipping without overwriting. This can occur when reprocessing a failed batch.", file)
 				} else {
 					return fmt.Errorf("adding export file entry: %w", err)
@@ -855,6 +858,8 @@ func (db *ExportDB) DeleteFilesBefore(ctx context.Context, before time.Time, blo
 	batchFileDeleteCounter := make(map[int64]int)
 
 	for _, f := range files {
+		f := f
+
 		// If file is already deleted, skip to the next.
 		if f.fileStatus == model.ExportBatchDeleted {
 			batchFileDeleteCounter[f.batchID]++
@@ -970,12 +975,11 @@ func completeBatch(ctx context.Context, tx pgx.Tx, batchID int64) error {
 	return nil
 }
 
-func shuffle(vals []int64) []int64 {
-	r := rand.New(rand.NewSource(time.Now().Unix()))
-	ret := make([]int64, len(vals))
-	perm := r.Perm(len(vals))
-	for i, randIndex := range perm {
-		ret[i] = vals[randIndex]
-	}
-	return ret
+// shuffle shuffles the values in vals in-place.
+func shuffle(vals []int64) {
+	//nolint:gosec // cryptorand.NewSource is a random source
+	r := rand.New(cryptorand.NewSource())
+	r.Shuffle(len(vals), func(i, j int) {
+		vals[i], vals[j] = vals[j], vals[i]
+	})
 }
diff --git a/internal/export/exportfile.go b/internal/export/exportfile.go
index 49bdca9..2f9cb1c 100644
--- a/internal/export/exportfile.go
+++ b/internal/export/exportfile.go
@@ -99,7 +99,7 @@ func MarshalExportFile(eb *model.ExportBatch, exposures, revisedExposures []*pub
 func UnmarshalExportFile(zippedProtoPayload []byte) (*export.TemporaryExposureKeyExport, []byte, error) {
 	zp, err := zip.NewReader(bytes.NewReader(zippedProtoPayload), int64(len(zippedProtoPayload)))
 	if err != nil {
-		return nil, nil, fmt.Errorf("can't read payload: %v", err)
+		return nil, nil, fmt.Errorf("can't read payload: %w", err)
 	}
 
 	for _, file := range zp.File {
@@ -193,7 +193,7 @@ func marshalContents(eb *model.ExportBatch, exposures, revisedExposures []*publi
 	// This could be done at the db layer but doing it here makes it explicit that its
 	// important to the serialization
 	sortExposures(exposures)
-	var pbeks []*export.TemporaryExposureKey
+	pbeks := make([]*export.TemporaryExposureKey, 0, len(exposures))
 	for _, exp := range exposures {
 		pbek := makeTEK(exp)
 		assignReportType(&exp.ReportType, pbek)
@@ -204,7 +204,7 @@ func marshalContents(eb *model.ExportBatch, exposures, revisedExposures []*publi
 	}
 
 	sortExposures(revisedExposures)
-	var pbRevisedKeys []*export.TemporaryExposureKey
+	pbRevisedKeys := make([]*export.TemporaryExposureKey, 0, len(revisedExposures))
 	for _, exp := range revisedExposures {
 		pbek := makeTEK(exp)
 		assignReportType(exp.RevisedReportType, pbek)
@@ -212,7 +212,7 @@ func marshalContents(eb *model.ExportBatch, exposures, revisedExposures []*publi
 		pbRevisedKeys = append(pbRevisedKeys, pbek)
 	}
 
-	var exportSigInfos []*export.SignatureInfo
+	exportSigInfos := make([]*export.SignatureInfo, 0, len(signers))
 	for _, si := range signers {
 		exportSigInfos = append(exportSigInfos, createSignatureInfo(si.SignatureInfo))
 	}
@@ -253,7 +253,7 @@ func createSignatureInfo(si *model.SignatureInfo) *export.SignatureInfo {
 func UnmarshalSignatureFile(zippedProtoPayload []byte) (*export.TEKSignatureList, error) {
 	zp, err := zip.NewReader(bytes.NewReader(zippedProtoPayload), int64(len(zippedProtoPayload)))
 	if err != nil {
-		return nil, fmt.Errorf("can't read payload: %v", err)
+		return nil, fmt.Errorf("can't read payload: %w", err)
 	}
 
 	for _, file := range zp.File {
@@ -287,11 +287,11 @@ func unmarshalSignatureContent(file *zip.File) (*export.TEKSignatureList, error)
 }
 
 func marshalSignature(exportContents []byte, signers []*Signer) ([]byte, error) {
-	var signatures []*export.TEKSignature
+	signatures := make([]*export.TEKSignature, 0, len(signers))
 	for _, s := range signers {
 		sig, err := generateSignature(exportContents, s.Signer)
 		if err != nil {
-			return nil, fmt.Errorf("unable to generate signature: %v", err)
+			return nil, fmt.Errorf("unable to generate signature: %w", err)
 		}
 		teks := &export.TEKSignature{
 			SignatureInfo: createSignatureInfo(s.SignatureInfo),
@@ -306,7 +306,7 @@ func marshalSignature(exportContents []byte, signers []*Signer) ([]byte, error)
 	}
 	protoBytes, err := proto.Marshal(&teksl)
 	if err != nil {
-		return nil, fmt.Errorf("unable to marshal signature file: %v", err)
+		return nil, fmt.Errorf("unable to marshal signature file: %w", err)
 	}
 	return protoBytes, nil
 }
diff --git a/internal/export/worker.go b/internal/export/worker.go
index 9c9d882..925d2ae 100644
--- a/internal/export/worker.go
+++ b/internal/export/worker.go
@@ -92,8 +92,8 @@ func (s *Server) handleDoWork() http.Handler {
 			// In the export lease selection, we attempt to order export batch filling such that
 			// earlier batches are filled before later batches. This helps to reduce the possibility
 			// of non-overlapping generated data.
-			locks := make([]string, len(batch.EffectiveInputRegions()))
-			copy(locks, batch.EffectiveInputRegions())
+			locks := make([]string, 0, len(batch.EffectiveInputRegions())+1)
+			locks = append(locks, batch.EffectiveInputRegions()...)
 			if batch.IncludeTravelers {
 				locks = append(locks, travelerLockID)
 			}
@@ -313,7 +313,7 @@ func (s *Server) exportBatch(ctx context.Context, eb *model.ExportBatch, emitInd
 	// Create the export files.
 	batchSize := len(groups)
 	splitBatch := batchSize > 1
-	var objectNames []string
+	objectNames := make([]string, 0, len(groups))
 	for i, group := range groups {
 		if ctx.Err() != nil {
 			logger.Infof("Timed out writing export files for batch %s, the entire batch will be retried once the batch lease expires on %v", eb.BatchID, eb.LeaseExpires)
@@ -366,7 +366,7 @@ type createFileInfo struct {
 func (s *Server) createFile(ctx context.Context, cfi *createFileInfo) (string, error) {
 	logger := logging.FromContext(ctx)
 
-	var signers []*Signer
+	signers := make([]*Signer, 0, len(cfi.signatureInfos))
 	for _, si := range cfi.signatureInfos {
 		signer, err := s.env.GetSignerForKey(ctx, si.SigningKey)
 		if err != nil {
@@ -420,7 +420,7 @@ func (s *Server) retryingCreateIndex(ctx context.Context, eb *model.ExportBatch,
 
 		// Mark files that we've previously cared about as expired.
 		if err := s.markExpiredFiles(ctx, eb); err != nil {
-			return fmt.Errorf("marking expired: %v", err)
+			return fmt.Errorf("marking expired: %w", err)
 		}
 
 		indexName, entries, err := s.createIndex(ctx, eb, objectNames)
diff --git a/internal/exportimport/config.go b/internal/exportimport/config.go
index ba62460..52cedf9 100644
--- a/internal/exportimport/config.go
+++ b/internal/exportimport/config.go
@@ -23,9 +23,11 @@ import (
 	"github.com/google/exposure-notifications-server/pkg/secrets"
 )
 
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+)
 
 type Config struct {
 	Database              database.Config
diff --git a/internal/exportimport/database/exportimport.go b/internal/exportimport/database/exportimport.go
index 512bb12..f111813 100644
--- a/internal/exportimport/database/exportimport.go
+++ b/internal/exportimport/database/exportimport.go
@@ -244,7 +244,6 @@ func (db *ExportImportDB) AddImportFilePublicKey(ctx context.Context, ifpk *mode
 			VALUES
 				($1, $2, $3, $4, $5, $6)
 			`, ifpk.ExportImportID, ifpk.KeyID, ifpk.KeyVersion, ifpk.PublicKeyPEM, ifpk.From, ifpk.Thru)
-
 		if err != nil {
 			return fmt.Errorf("inserting importfilepublickey: %w", err)
 		}
@@ -356,7 +355,7 @@ func (db *ExportImportDB) CreateNewFilesAndFailOld(ctx context.Context, ei *mode
 		// Go through incoming list and insert a new entry for each filename we haven't seen before.
 		insertStmt, err := prepareInsertImportFile(ctx, tx)
 		if err != nil {
-			return fmt.Errorf("preparing insert statement: %v", err)
+			return fmt.Errorf("preparing insert statement: %w", err)
 		}
 
 		for _, fname := range filenames {
diff --git a/internal/exportimport/import.go b/internal/exportimport/import.go
index 8626a36..2e83d76 100644
--- a/internal/exportimport/import.go
+++ b/internal/exportimport/import.go
@@ -33,9 +33,7 @@ import (
 	"go.uber.org/zap"
 )
 
-var (
-	ErrArchiveNotFound = errors.New("archive file not found")
-)
+var ErrArchiveNotFound = errors.New("archive file not found")
 
 type ImportRequest struct {
 	config       *Config
@@ -67,11 +65,18 @@ func (s *Server) ImportExportFile(ctx context.Context, ir *ImportRequest) (*Impo
 	}
 
 	logger := logging.FromContext(ctx)
+
 	// Download zip file.
-	client := &http.Client{
+	httpClient := &http.Client{
 		Timeout: s.config.ExportFileDownloadTimeout,
 	}
-	resp, err := client.Get(ir.file.ZipFilename)
+
+	req, err := http.NewRequestWithContext(ctx, "GET", ir.file.ZipFilename, nil)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create request to download export file: %w", err)
+	}
+
+	resp, err := httpClient.Do(req)
 	if err != nil {
 		return nil, fmt.Errorf("error downloading export file: %w", err)
 	}
diff --git a/internal/exportimport/importer.go b/internal/exportimport/importer.go
index 177cbf2..3bcf0c0 100644
--- a/internal/exportimport/importer.go
+++ b/internal/exportimport/importer.go
@@ -43,7 +43,7 @@ func (s *Server) handleImport() http.Handler {
 		logger.Info("starting export importer")
 		defer func() {
 			w.WriteHeader(http.StatusOK)
-			w.Write([]byte("ok"))
+			fmt.Fprint(w, "ok")
 		}()
 		ctx = logging.WithLogger(ctx, logger)
 
@@ -100,7 +100,6 @@ func (s *Server) runImport(ctx context.Context, config *model.ExportImport) erro
 	keys, err := s.exportImportDB.AllowedKeys(ctx, config)
 	if err != nil {
 		return fmt.Errorf("unable to read public keys: %w", err)
-
 	}
 	logger.Debugw("allowed public keys for file", "publicKeys", keys)
 
@@ -127,7 +126,7 @@ func (s *Server) runImport(ctx context.Context, config *model.ExportImport) erro
 		if err != nil {
 			errs = append(errs, err)
 			str := fmt.Sprintf("import file error [retry %d]", file.Retries)
-			file.Retries += 1
+			file.Retries++
 			if errors.Is(err, ErrArchiveNotFound) {
 				str += ", file not found"
 			}
@@ -149,6 +148,7 @@ func (s *Server) runImport(ctx context.Context, config *model.ExportImport) erro
 	}
 	return nil
 }
+
 func deadlinePassed(ctx context.Context) bool {
 	deadline, ok := ctx.Deadline()
 	if !ok {
diff --git a/internal/exportimport/scheduler.go b/internal/exportimport/scheduler.go
index e973cd9..ea3710d 100644
--- a/internal/exportimport/scheduler.go
+++ b/internal/exportimport/scheduler.go
@@ -70,7 +70,7 @@ func (s *Server) handleSchedule() http.Handler {
 			return
 		}
 
-		client := &http.Client{
+		httpClient := &http.Client{
 			Timeout: s.config.IndexFileDownloadTimeout,
 		}
 
@@ -78,7 +78,13 @@ func (s *Server) handleSchedule() http.Handler {
 		for _, config := range configs {
 			logger.Infow("checking index file", "config", config)
 
-			resp, err := client.Get(config.IndexFile)
+			req, err := http.NewRequestWithContext(ctx, "GET", config.IndexFile, nil)
+			if err != nil {
+				logger.Errorw("failed to create request to download index file", "file", config.IndexFile, "error", err)
+				continue
+			}
+
+			resp, err := httpClient.Do(req)
 			if err != nil {
 				anyErrors = true
 				logger.Errorw("error downloading index file", "file", config.IndexFile, "error", err)
@@ -106,7 +112,7 @@ func (s *Server) handleSchedule() http.Handler {
 			status = http.StatusInternalServerError
 		}
 		w.WriteHeader(status)
-		w.Write([]byte(http.StatusText(status)))
+		fmt.Fprint(w, http.StatusText(status))
 	})
 }
 
diff --git a/internal/exportimport/server.go b/internal/exportimport/server.go
index 86e0021..7f630cb 100644
--- a/internal/exportimport/server.go
+++ b/internal/exportimport/server.go
@@ -41,12 +41,12 @@ type Server struct {
 
 // NewServer creates a Server that manages deletion of
 // old export files that are no longer needed by clients for download.
-func NewServer(config *Config, env *serverenv.ServerEnv) (*Server, error) {
+func NewServer(cfg *Config, env *serverenv.ServerEnv) (*Server, error) {
 	if env.Database() == nil {
 		return nil, fmt.Errorf("missing database in server environment")
 	}
 
-	if rt := config.BackfillReportType; !(rt == "" || rt == verifyapi.ReportTypeConfirmed || rt == verifyapi.ReportTypeClinical) {
+	if rt := cfg.BackfillReportType; !(rt == "" || rt == verifyapi.ReportTypeConfirmed || rt == verifyapi.ReportTypeClinical) {
 		return nil, fmt.Errorf("BACKFILL_REPORT_TYPE value is invalid, must be %q, %q, or %q", "", verifyapi.ReportTypeConfirmed, verifyapi.ReportTypeClinical)
 	}
 
@@ -55,7 +55,7 @@ func NewServer(config *Config, env *serverenv.ServerEnv) (*Server, error) {
 	publishDB := pubdb.New(db)
 
 	return &Server{
-		config:         config,
+		config:         cfg,
 		env:            env,
 		db:             db,
 		exportImportDB: exportImportDB,
diff --git a/internal/federationin/config.go b/internal/federationin/config.go
index 2004227..2e46be3 100644
--- a/internal/federationin/config.go
+++ b/internal/federationin/config.go
@@ -37,9 +37,11 @@ var (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+)
 
 // Config is the configuration for federation-pull components (data pulled from other servers).
 type Config struct {
diff --git a/internal/federationin/database/federationin.go b/internal/federationin/database/federationin.go
index 3c35345..39c5bc5 100644
--- a/internal/federationin/database/federationin.go
+++ b/internal/federationin/database/federationin.go
@@ -17,6 +17,7 @@ package database
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"time"
 
@@ -81,7 +82,7 @@ func getFederationInQuery(ctx context.Context, queryID string, queryRow queryRow
 	if err := row.Scan(&q.QueryID, &q.ServerAddr, &q.Audience, &q.IncludeRegions, &q.ExcludeRegions,
 		&q.OnlyLocalProvenance, &q.OnlyTravelers,
 		&lastTimestamp, &lastCursor, &revisedTimestamp, &revisedCursor); err != nil {
-		if err == pgx.ErrNoRows {
+		if errors.Is(err, pgx.ErrNoRows) {
 			return nil, database.ErrNotFound
 		}
 		return nil, fmt.Errorf("scanning results: %w", err)
@@ -155,7 +156,7 @@ func getFederationInSync(ctx context.Context, syncID int64, queryRowContext quer
 		insertions                 *int
 	)
 	if err := row.Scan(&s.SyncID, &s.QueryID, &s.Started, &completed, &insertions, &max, &maxRevised); err != nil {
-		if err == pgx.ErrNoRows {
+		if errors.Is(err, pgx.ErrNoRows) {
 			return nil, database.ErrNotFound
 		}
 		return nil, fmt.Errorf("scanning results: %w", err)
diff --git a/internal/federationout/config.go b/internal/federationout/config.go
index 28de5a7..9d950f6 100644
--- a/internal/federationout/config.go
+++ b/internal/federationout/config.go
@@ -24,9 +24,11 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+)
 
 // Config is the configuration for the federation components (data sent to other servers).
 type Config struct {
diff --git a/internal/federationout/database/federationout.go b/internal/federationout/database/federationout.go
index 352184c..57aa40c 100644
--- a/internal/federationout/database/federationout.go
+++ b/internal/federationout/database/federationout.go
@@ -86,5 +86,4 @@ func (db *FederationOutDB) GetFederationOutAuthorization(ctx context.Context, is
 	}
 
 	return &auth, nil
-
 }
diff --git a/internal/generate/config.go b/internal/generate/config.go
index 98e32c3..6b4e949 100644
--- a/internal/generate/config.go
+++ b/internal/generate/config.go
@@ -26,10 +26,12 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
-var _ model.TransformerConfig = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+	_ model.TransformerConfig                   = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables for
 // the publish components.
diff --git a/internal/integration/client.go b/internal/integration/client.go
index 11f36c0..e3fab62 100644
--- a/internal/integration/client.go
+++ b/internal/integration/client.go
@@ -198,8 +198,8 @@ func (c *client) do(req *http.Request, out interface{}) (*http.Response, error)
 
 	var errResp errorResponse
 	if err := json.Unmarshal(body, &errResp); err == nil && errResp.Error() != "" {
-		return nil, fmt.Errorf("%s: error response from API: %s, body: %s",
-			errPrefix, errResp.Error(), body)
+		return nil, fmt.Errorf("%s: error response from API: %s, err: %w, body: %s",
+			errPrefix, errResp.Error(), err, body)
 	}
 
 	if err := json.Unmarshal(body, out); err != nil {
diff --git a/internal/jsonutil/unmarshal.go b/internal/jsonutil/unmarshal.go
index 999ba6b..5595617 100644
--- a/internal/jsonutil/unmarshal.go
+++ b/internal/jsonutil/unmarshal.go
@@ -48,11 +48,11 @@ func Unmarshal(w http.ResponseWriter, r *http.Request, data interface{}) (int, e
 		var unmarshalError *json.UnmarshalTypeError
 		switch {
 		case errors.As(err, &syntaxErr):
-			return http.StatusBadRequest, fmt.Errorf("malformed json at position %v", syntaxErr.Offset)
+			return http.StatusBadRequest, fmt.Errorf("malformed json at position %d", syntaxErr.Offset)
 		case errors.Is(err, io.ErrUnexpectedEOF):
 			return http.StatusBadRequest, fmt.Errorf("malformed json")
 		case errors.As(err, &unmarshalError):
-			return http.StatusBadRequest, fmt.Errorf("invalid value %v at position %v", unmarshalError.Field, unmarshalError.Offset)
+			return http.StatusBadRequest, fmt.Errorf("invalid value %q at position %d", unmarshalError.Field, unmarshalError.Offset)
 		case strings.HasPrefix(err.Error(), "json: unknown field"):
 			fieldName := strings.TrimPrefix(err.Error(), "json: unknown field ")
 			return http.StatusBadRequest, fmt.Errorf("unknown field %s", fieldName)
@@ -61,7 +61,7 @@ func Unmarshal(w http.ResponseWriter, r *http.Request, data interface{}) (int, e
 		case err.Error() == "http: request body too large":
 			return http.StatusRequestEntityTooLarge, err
 		default:
-			return http.StatusInternalServerError, fmt.Errorf("failed to decode json %v", err)
+			return http.StatusInternalServerError, fmt.Errorf("failed to decode json: %w", err)
 		}
 	}
 	if d.More() {
diff --git a/internal/jwks/config.go b/internal/jwks/config.go
index cd31217..c789a2b 100644
--- a/internal/jwks/config.go
+++ b/internal/jwks/config.go
@@ -22,8 +22,10 @@ import (
 	"github.com/google/exposure-notifications-server/pkg/secrets"
 )
 
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider      = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider = (*Config)(nil)
+)
 
 type Config struct {
 	Database      database.Config
diff --git a/internal/jwks/jwks.go b/internal/jwks/jwks.go
index 82a474d..c26b477 100644
--- a/internal/jwks/jwks.go
+++ b/internal/jwks/jwks.go
@@ -189,12 +189,13 @@ func (mgr *Manager) updateHA(ctx context.Context, ha *model.HealthAuthority) err
 	}
 
 	// Get the keys for the health authority
-	if keys, err := haDB.GetHealthAuthorityKeys(ctx, ha); err != nil {
-		return fmt.Errorf("error getting keys: %v", err)
-	} else {
-		ha.Keys = keys
+	keys, err := haDB.GetHealthAuthorityKeys(ctx, ha)
+	if err != nil {
+		return fmt.Errorf("error getting keys: %w", err)
 	}
 
+	ha.Keys = keys
+
 	resp, err := mgr.getKeys(ctx, ha)
 	if err != nil {
 		return err
diff --git a/internal/keyrotation/config.go b/internal/keyrotation/config.go
index c21dbd2..6543aa9 100644
--- a/internal/keyrotation/config.go
+++ b/internal/keyrotation/config.go
@@ -26,10 +26,12 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
-var _ setup.KeyManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+	_ setup.KeyManagerConfigProvider            = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables for
 // the key rotation components.
diff --git a/internal/keyrotation/rotate.go b/internal/keyrotation/rotate.go
index a47e106..b52f7b9 100644
--- a/internal/keyrotation/rotate.go
+++ b/internal/keyrotation/rotate.go
@@ -112,12 +112,7 @@ func (s *Server) doRotate(ctx context.Context) error {
 	return result.ErrorOrNil()
 }
 
-func (s *Server) maybeDeleteKey(
-	ctx context.Context,
-	key *revisiondatabase.RevisionKey,
-	effectiveID int64,
-	previousCreated time.Time) (bool, error) {
-
+func (s *Server) maybeDeleteKey(ctx context.Context, key *revisiondatabase.RevisionKey, effectiveID int64, previousCreated time.Time) (bool, error) {
 	if key.KeyID == effectiveID {
 		return false, nil
 	}
diff --git a/internal/mirror/config.go b/internal/mirror/config.go
index cadb2aa..8c038e3 100644
--- a/internal/mirror/config.go
+++ b/internal/mirror/config.go
@@ -24,10 +24,12 @@ import (
 	"github.com/google/exposure-notifications-server/pkg/secrets"
 )
 
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
-var _ setup.BlobstoreConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
+var (
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+	_ setup.BlobstoreConfigProvider             = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+)
 
 type Config struct {
 	Database              database.Config
diff --git a/internal/mirror/database/mirror.go b/internal/mirror/database/mirror.go
index 072afaa..4a6b739 100644
--- a/internal/mirror/database/mirror.go
+++ b/internal/mirror/database/mirror.go
@@ -253,6 +253,9 @@ func (db *MirrorDB) SaveFiles(ctx context.Context, mirrorID int64, filenames []*
 			}
 
 			for fName, rewrittenFilename := range wantFiles {
+				fName := fName
+				rewrittenFilename := rewrittenFilename
+
 				var localFilename *string
 				if fName != rewrittenFilename {
 					localFilename = &rewrittenFilename
diff --git a/internal/mirror/mirror.go b/internal/mirror/mirror.go
index 97190ed..7c4fc1e 100644
--- a/internal/mirror/mirror.go
+++ b/internal/mirror/mirror.go
@@ -38,11 +38,11 @@ import (
 
 const mirrorLockPrefix = "mirror-lock"
 
-type MirrorResponse struct {
-	Mirrors []*MirrorStatus `json:"mirrors"`
+type Response struct {
+	Mirrors []*Status `json:"mirrors"`
 }
 
-type MirrorStatus struct {
+type Status struct {
 	ID        int64    `json:"id"`
 	Processed bool     `json:"processed"`
 	Errors    []string `json:"errors,omitempty"`
@@ -77,12 +77,12 @@ func (s *Server) handleMirror() http.Handler {
 		}
 
 		// Start building a response for all mirrors.
-		var resp MirrorResponse
+		var resp Response
 		var hasError bool
 
 		for _, mirror := range mirrors {
 			// Build the initial status
-			status := &MirrorStatus{ID: mirror.ID}
+			status := &Status{ID: mirror.ID}
 
 			// If the deadline has passed, do not attempt to process additional
 			// mirrors. Note that exceeding the deadline is NOT considered an error.
@@ -175,7 +175,7 @@ func (s *Server) processMirror(ctx context.Context, deadline time.Time, mirror *
 
 	// Download the index, which will return the fully qualified download links
 	// for the files.
-	indexFiles, err := s.downloadIndex(mirror)
+	indexFiles, err := s.downloadIndex(ctx, mirror)
 	if err != nil {
 		return fmt.Errorf("failed to download index: %w", err)
 	}
@@ -268,7 +268,7 @@ func (s *Server) processMirror(ctx context.Context, deadline time.Time, mirror *
 			"file", filename,
 			"download_path", status.DownloadPath)
 
-		b, err := downloadFile(status.DownloadPath, s.config.ExportFileDownloadTimeout, s.config.MaxZipBytes)
+		b, err := downloadFile(ctx, status.DownloadPath, s.config.ExportFileDownloadTimeout, s.config.MaxZipBytes)
 		if err != nil {
 			merr = multierror.Append(merr, fmt.Errorf("failed to download export file %s: %w", filename, err))
 			status.Failed = true
@@ -384,11 +384,16 @@ func computeActions(knownFiles []*model.MirrorFile, indexFiles []string) map[str
 // URL does not return a 200, an error is returned. If the process takes longer
 // than the provided timeout, an error is returned. If more bytes remain after
 // maxBytes, an error is returned. Otherwise, the raw bytes are returned.
-func downloadFile(u string, timeout time.Duration, maxBytes int64) ([]byte, error) {
+func downloadFile(ctx context.Context, u string, timeout time.Duration, maxBytes int64) ([]byte, error) {
 	client := &http.Client{Timeout: timeout}
 
 	// Start the download.
-	resp, err := client.Get(u)
+	req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create request %s: %w", u, err)
+	}
+
+	resp, err := client.Do(req)
 	if err != nil {
 		return nil, fmt.Errorf("failed to download %s: %w", u, err)
 	}
@@ -407,7 +412,7 @@ func downloadFile(u string, timeout time.Duration, maxBytes int64) ([]byte, erro
 	}
 	if r.N == 0 {
 		// Check if there's more data to be read and return an error if so.
-		if _, err := r.R.Read(make([]byte, 1)); err != io.EOF {
+		if _, err := r.R.Read(make([]byte, 1)); !errors.Is(err, io.EOF) {
 			return nil, fmt.Errorf("failed to read %s: response exceeds %d bytes", u, maxBytes)
 		}
 	}
@@ -426,8 +431,8 @@ func downloadFile(u string, timeout time.Duration, maxBytes int64) ([]byte, erro
 //
 // The values are returned in the order in which they appear in the file, joined
 // with the configured mirror ExportRoot.
-func (s *Server) downloadIndex(mirror *model.Mirror) ([]string, error) {
-	b, err := downloadFile(mirror.IndexFile, s.config.IndexFileDownloadTimeout, s.config.MaxIndexBytes)
+func (s *Server) downloadIndex(ctx context.Context, mirror *model.Mirror) ([]string, error) {
+	b, err := downloadFile(ctx, mirror.IndexFile, s.config.IndexFileDownloadTimeout, s.config.MaxIndexBytes)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/project/random.go b/internal/project/random.go
index 2f3b45f..1c4569b 100644
--- a/internal/project/random.go
+++ b/internal/project/random.go
@@ -22,21 +22,21 @@ import (
 )
 
 // RandomHexString generates a random string of the provided length.
-func RandomHexString(len int) (string, error) {
-	b, err := RandomBytes((len + 1) / 2)
+func RandomHexString(length int) (string, error) {
+	b, err := RandomBytes((length + 1) / 2)
 	if err != nil {
 		return "", err
 	}
-	return hex.EncodeToString(b)[:len], nil
+	return hex.EncodeToString(b)[:length], nil
 }
 
 // RandomBase64String encodes a random base64 string of a given length.
-func RandomBase64String(len int) (string, error) {
-	b, err := RandomBytes(len)
+func RandomBase64String(length int) (string, error) {
+	b, err := RandomBytes(length)
 	if err != nil {
 		return "", err
 	}
-	return base64.URLEncoding.EncodeToString(b)[:len], nil
+	return base64.URLEncoding.EncodeToString(b)[:length], nil
 }
 
 // RandomBytes returns a byte slice of random values of the given length.
diff --git a/internal/publish/config.go b/internal/publish/config.go
index b0395cb..f63546d 100644
--- a/internal/publish/config.go
+++ b/internal/publish/config.go
@@ -33,13 +33,15 @@ import (
 )
 
 // Compile-time check to assert this config matches requirements.
-var _ setup.AuthorizedAppConfigProvider = (*Config)(nil)
-var _ setup.DatabaseConfigProvider = (*Config)(nil)
-var _ setup.SecretManagerConfigProvider = (*Config)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
-var _ model.TransformerConfig = (*Config)(nil)
-var _ setup.KeyManagerConfigProvider = (*Config)(nil)
-var _ middleware.Maintainable = (*Config)(nil)
+var (
+	_ setup.AuthorizedAppConfigProvider         = (*Config)(nil)
+	_ setup.DatabaseConfigProvider              = (*Config)(nil)
+	_ setup.SecretManagerConfigProvider         = (*Config)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*Config)(nil)
+	_ model.TransformerConfig                   = (*Config)(nil)
+	_ setup.KeyManagerConfigProvider            = (*Config)(nil)
+	_ middleware.Maintainable                   = (*Config)(nil)
+)
 
 // Config represents the configuration and associated environment variables for
 // the publish components.
diff --git a/internal/publish/database/exposure.go b/internal/publish/database/exposure.go
index 9ead061..4aaa460 100644
--- a/internal/publish/database/exposure.go
+++ b/internal/publish/database/exposure.go
@@ -114,7 +114,7 @@ func (db *PublishDB) IterateExposures(ctx context.Context, criteria IterateExpos
 
 	query, args, err := generateExposureQuery(criteria)
 	if err != nil {
-		return "", fmt.Errorf("generating where: %v", err)
+		return "", fmt.Errorf("generating where: %w", err)
 	}
 
 	logger := logging.FromContext(ctx).Named("IterateExposures")
@@ -358,7 +358,7 @@ func executeInsertExposure(ctx context.Context, tx pgx.Tx, stmtName string, exp
 		exp.HealthAuthorityID, exp.ReportType, exp.DaysSinceSymptomOnset,
 		exp.ExportImportID, exp.ImportFileID)
 	if err != nil {
-		return fmt.Errorf("inserting exposure: %v", err)
+		return fmt.Errorf("inserting exposure: %w", err)
 	}
 	return nil
 }
@@ -385,7 +385,7 @@ func executeReviseExposure(ctx context.Context, tx pgx.Tx, stmtName string, exp
 		exp.RevisedImportFileID,
 		encodeExposureKey(exp.ExposureKey))
 	if err != nil {
-		return fmt.Errorf("revising exposure: %v", err)
+		return fmt.Errorf("revising exposure: %w", err)
 	}
 	if result.RowsAffected() != 1 {
 		return fmt.Errorf("invalid key revision request")
@@ -629,11 +629,11 @@ func (db *PublishDB) InsertAndReviseExposures(ctx context.Context, req *InsertAn
 		// Prepare the insert and update statements.
 		insertStmt, err := prepareInsertExposure(ctx, tx)
 		if err != nil {
-			return fmt.Errorf("preparing insert statement: %v", err)
+			return fmt.Errorf("preparing insert statement: %w", err)
 		}
 		updateStmt, err := prepareReviseExposure(ctx, tx)
 		if err != nil {
-			return fmt.Errorf("preparing update statement: %v", err)
+			return fmt.Errorf("preparing update statement: %w", err)
 		}
 
 		// only possible if all passed in keys are already existing and not revisions.
@@ -696,7 +696,7 @@ func (db *PublishDB) DeleteExposuresBefore(ctx context.Context, before time.Time
 				created_at < $1
 			`, before)
 		if err != nil {
-			return fmt.Errorf("deleting exposures: %v", err)
+			return fmt.Errorf("deleting exposures: %w", err)
 		}
 		count = result.RowsAffected()
 		return nil
@@ -714,7 +714,7 @@ func encodeCursor(s string) string {
 func decodeCursor(encoded string) (string, error) {
 	b, err := base64util.DecodeString(encoded)
 	if err != nil {
-		return "", fmt.Errorf("decoding cursor: %v", err)
+		return "", fmt.Errorf("decoding cursor: %w", err)
 	}
 	return string(b), nil
 }
diff --git a/internal/publish/database/stats.go b/internal/publish/database/stats.go
index 560fb63..bea5983 100644
--- a/internal/publish/database/stats.go
+++ b/internal/publish/database/stats.go
@@ -37,7 +37,7 @@ func (db *PublishDB) DeleteStatsBefore(ctx context.Context, before time.Time) (i
 				hour < $1
 			`, before)
 		if err != nil {
-			return fmt.Errorf("deleting exposures: %v", err)
+			return fmt.Errorf("deleting exposures: %w", err)
 		}
 		count = result.RowsAffected()
 		return nil
@@ -90,7 +90,7 @@ func (db *PublishDB) ReadStats(ctx context.Context, healthAuthorityID int64) ([]
 	return results, nil
 }
 
-func scanOneHealthAuthorityStats(rows pgx.Rows, stats *model.HealthAuthorityStats) error {
+func scanOneHealthAuthorityStats(rows pgx.Row, stats *model.HealthAuthorityStats) error {
 	return rows.Scan(
 		&stats.HealthAuthorityID, &stats.Hour, &stats.PublishCount, &stats.TEKCount,
 		&stats.RevisionCount, &stats.OldestTekDays, &stats.OnsetAgeDays, &stats.MissingOnset)
diff --git a/internal/publish/model/exposure_model.go b/internal/publish/model/exposure_model.go
index 818ef81..9b6314d 100644
--- a/internal/publish/model/exposure_model.go
+++ b/internal/publish/model/exposure_model.go
@@ -143,9 +143,8 @@ func FromExportKey(key *export.TemporaryExposureKey, config *ExportImportConfig)
 		return nil, fmt.Errorf("saw likely key when not allowed")
 	}
 
-	//lint:ignore SA1019 may be set on v1 files.
+	//nolint:staticcheck // SA1019: may be set on v1 files.
 	if key.TransmissionRiskLevel != nil {
-		//lint:ignore SA1019 may be set on v1 files.
 		if tr := *key.TransmissionRiskLevel; tr < verifyapi.MinTransmissionRisk {
 			return nil, fmt.Errorf("transmission risk too low: %d, must be >= %d", tr, verifyapi.MinTransmissionRisk)
 		} else if tr > verifyapi.MaxTransmissionRisk {
diff --git a/internal/publish/publish.go b/internal/publish/publish.go
index 7def2b2..236503a 100644
--- a/internal/publish/publish.go
+++ b/internal/publish/publish.go
@@ -172,7 +172,7 @@ func generatePadding(minPadding, paddingRange int64) (string, error) {
 	if minBytes <= 0 {
 		minBytes = 1024
 	}
-	padRange := int64(paddingRange)
+	padRange := paddingRange
 	if padRange <= 0 {
 		padRange = 1024
 	}
diff --git a/internal/revision/revision.go b/internal/revision/revision.go
index 5492d03..c60c879 100644
--- a/internal/revision/revision.go
+++ b/internal/revision/revision.go
@@ -35,14 +35,12 @@ import (
 	"google.golang.org/protobuf/proto"
 )
 
-var (
-	// Used for padding only.
-	zeroTEK = pb.RevisableKey{
-		TemporaryExposureKey: make([]byte, 16),
-		IntervalCount:        0,
-		IntervalNumber:       0,
-	}
-)
+// Used for padding only.
+var zeroTEK = pb.RevisableKey{
+	TemporaryExposureKey: make([]byte, 16),
+	IntervalCount:        0,
+	IntervalNumber:       0,
+}
 
 // TokenManager is responsible for creating and unlocking revision tokens.
 type TokenManager struct {
diff --git a/internal/setup/setup.go b/internal/setup/setup.go
index 6b54e9f..ff5bbff 100644
--- a/internal/setup/setup.go
+++ b/internal/setup/setup.go
@@ -76,7 +76,7 @@ func Setup(ctx context.Context, config interface{}) (*serverenv.ServerEnv, error
 // responsible for establishing database connections, resolving secrets, and
 // accessing app configs. The provided interface must implement the various
 // interfaces.
-func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*serverenv.ServerEnv, error) {
+func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*serverenv.ServerEnv, error) { //nolint:golint
 	logger := logging.FromContext(ctx)
 
 	// Build a list of mutators. This list will grow as we initialize more of the
@@ -174,7 +174,7 @@ func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*
 		oeConfig := provider.ObservabilityExporterConfig()
 		oe, err := observability.NewFromEnv(oeConfig)
 		if err != nil {
-			return nil, fmt.Errorf("unable to create observability provider: %v", err)
+			return nil, fmt.Errorf("unable to create observability provider: %w", err)
 		}
 		if err := oe.StartExporter(ctx); err != nil {
 			return nil, fmt.Errorf("failed to start observability: %w", err)
@@ -194,7 +194,7 @@ func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*
 		bsConfig := provider.BlobstoreConfig()
 		blobStore, err := storage.BlobstoreFor(ctx, bsConfig)
 		if err != nil {
-			return nil, fmt.Errorf("unable to connect to storage system: %v", err)
+			return nil, fmt.Errorf("unable to connect to storage system: %w", err)
 		}
 		blobStorage := serverenv.WithBlobStorage(blobStore)
 
@@ -211,7 +211,7 @@ func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*
 		dbConfig := provider.DatabaseConfig()
 		db, err := database.NewFromEnv(ctx, dbConfig)
 		if err != nil {
-			return nil, fmt.Errorf("unable to connect to database: %v", err)
+			return nil, fmt.Errorf("unable to connect to database: %w", err)
 		}
 
 		// Update serverEnv setup.
@@ -228,7 +228,7 @@ func SetupWith(ctx context.Context, config interface{}, l envconfig.Lookuper) (*
 			if err != nil {
 				// Ensure the database is closed on an error.
 				defer db.Close(ctx)
-				return nil, fmt.Errorf("unable to create AuthorizedApp provider: %v", err)
+				return nil, fmt.Errorf("unable to create AuthorizedApp provider: %w", err)
 			}
 
 			// Update serverEnv setup.
diff --git a/internal/storage/aws_s3.go b/internal/storage/aws_s3.go
index e083d9e..19bad16 100644
--- a/internal/storage/aws_s3.go
+++ b/internal/storage/aws_s3.go
@@ -19,6 +19,7 @@ package storage
 import (
 	"bytes"
 	"context"
+	"errors"
 	"fmt"
 	"io/ioutil"
 
@@ -98,8 +99,8 @@ func (s *AWSS3) GetObject(ctx context.Context, bucket, key string) ([]byte, erro
 		Key:    aws.String(key),
 	})
 	if err != nil {
-		if aerr, ok := err.(awserr.Error); ok &&
-			aerr.Code() == s3.ErrCodeNoSuchBucket || aerr.Code() == s3.ErrCodeNoSuchKey {
+		var aerr awserr.Error
+		if errors.As(err, &aerr) && (aerr.Code() == s3.ErrCodeNoSuchBucket || aerr.Code() == s3.ErrCodeNoSuchKey) {
 			return nil, ErrNotFound
 		}
 		return nil, fmt.Errorf("failed to get object: %w", err)
diff --git a/internal/storage/azure_blobstore.go b/internal/storage/azure_blobstore.go
index e1cf242..5feda48 100644
--- a/internal/storage/azure_blobstore.go
+++ b/internal/storage/azure_blobstore.go
@@ -19,6 +19,7 @@ package storage
 import (
 	"bytes"
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"net/url"
@@ -60,7 +61,7 @@ func newMSITokenCredential(blobstoreURL string) (azblob.Credential, error) {
 
 	spt, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, blobstoreURL)
 	if err != nil {
-		return nil, fmt.Errorf("failed to get service principal token from msi %v: %v", msiEndpoint, err)
+		return nil, fmt.Errorf("failed to get service principal token from msi %v: %w", msiEndpoint, err)
 	}
 
 	tokenRefresher := func(credential azblob.TokenCredential) time.Duration {
@@ -104,7 +105,7 @@ func NewAzureBlobstore(ctx context.Context, _ *Config) (Blobstore, error) {
 	primaryURLRaw := fmt.Sprintf("https://%s.blob.core.windows.net", accountName)
 	primaryURL, err := url.Parse(primaryURLRaw)
 	if err != nil {
-		return nil, fmt.Errorf("failed to parse URL %v: %v", primaryURLRaw, err)
+		return nil, fmt.Errorf("failed to parse URL %v: %w", primaryURLRaw, err)
 	}
 
 	accountKey := os.Getenv("AZURE_STORAGE_ACCESS_KEY")
@@ -158,7 +159,8 @@ func (s *AzureBlobstore) CreateObject(ctx context.Context, container, name strin
 func (s *AzureBlobstore) DeleteObject(ctx context.Context, container, name string) error {
 	blobURL := s.serviceURL.NewContainerURL(container).NewBlockBlobURL(name)
 	if _, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{}); err != nil {
-		if terr, ok := err.(azblob.StorageError); ok && terr.ServiceCode() == azblob.ServiceCodeBlobNotFound {
+		var terr azblob.StorageError
+		if errors.As(err, &terr) && terr.ServiceCode() == azblob.ServiceCodeBlobNotFound {
 			// already deleted
 			return nil
 		}
diff --git a/internal/storage/filesystem_storage.go b/internal/storage/filesystem_storage.go
index abfc218..cad13ed 100644
--- a/internal/storage/filesystem_storage.go
+++ b/internal/storage/filesystem_storage.go
@@ -45,7 +45,7 @@ func NewFilesystemStorage(ctx context.Context, _ *Config) (Blobstore, error) {
 // contentType is ignored for this storage implementation.
 func (s *FilesystemStorage) CreateObject(ctx context.Context, folder, filename string, contents []byte, cacheable bool, contentType string) error {
 	pth := filepath.Join(folder, filename)
-	if err := ioutil.WriteFile(pth, contents, 0644); err != nil {
+	if err := ioutil.WriteFile(pth, contents, 0o600); err != nil {
 		return fmt.Errorf("failed to create object: %w", err)
 	}
 	return nil
diff --git a/internal/storage/storage.go b/internal/storage/storage.go
index e93cb90..7c1602c 100644
--- a/internal/storage/storage.go
+++ b/internal/storage/storage.go
@@ -46,8 +46,10 @@ type Blobstore interface {
 type BlobstoreFunc func(context.Context, *Config) (Blobstore, error)
 
 // blobstores is the list of registered blobstores.
-var blobstores = make(map[string]BlobstoreFunc)
-var blobstoresLock sync.RWMutex
+var (
+	blobstores     = make(map[string]BlobstoreFunc)
+	blobstoresLock sync.RWMutex
+)
 
 // RegisterBlobstore registers a new blobstore with the given name. If a blobstore
 // is already registered with the given name, it panics. Blobstores are usually
diff --git a/internal/utils/utils.go b/internal/utils/utils.go
index b32ea28..56b0a19 100644
--- a/internal/utils/utils.go
+++ b/internal/utils/utils.go
@@ -118,14 +118,14 @@ func GetSigningKey(tb testing.TB) *SigningKey {
 
 // IssueJWT generates a JWT as if it came from the
 // authorized health authority.
-func IssueJWT(t *testing.T, cfg *JWTConfig) (jwtText, hmacKey string) {
+func IssueJWT(t *testing.T, cfg *JWTConfig) (string, string) {
 	t.Helper()
 
 	hmacKeyBytes := make([]byte, 32)
 	if _, err := rand.Read(hmacKeyBytes); err != nil {
 		t.Fatal(err)
 	}
-	hmacKey = base64.StdEncoding.EncodeToString(hmacKeyBytes)
+	hmacKey := base64.StdEncoding.EncodeToString(hmacKeyBytes)
 
 	hmacBytes, err := vutil.CalculateExposureKeyHMAC(cfg.ExposureKeys, hmacKeyBytes)
 	if err != nil {
@@ -148,11 +148,12 @@ func IssueJWT(t *testing.T, cfg *JWTConfig) (jwtText, hmacKey string) {
 
 	token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
 	token.Header[verifyapi.KeyIDHeader] = cfg.HealthAuthorityKey.Version
-	jwtText, err = token.SignedString(cfg.Key)
+	jwtText, err := token.SignedString(cfg.Key)
 	if err != nil {
 		t.Fatal(err)
 	}
-	return
+
+	return jwtText, hmacKey
 }
 
 // InitializeVerificationDB links the vdb, HA and SigningKeys together
diff --git a/internal/verification/database/health_authority_db.go b/internal/verification/database/health_authority_db.go
index 7727ef0..a1afd4d 100644
--- a/internal/verification/database/health_authority_db.go
+++ b/internal/verification/database/health_authority_db.go
@@ -27,9 +27,7 @@ import (
 	pgx "github.com/jackc/pgx/v4"
 )
 
-var (
-	ErrHealthAuthorityNotFound = errors.New("health authority not found")
-)
+var ErrHealthAuthorityNotFound = errors.New("health authority not found")
 
 // HealthAuthorityDB allows for opreations against authorized health authorities
 // for diagnosis signature verification.
diff --git a/pkg/api/v1/verification_types.go b/pkg/api/v1/verification_types.go
index 182dd7b..6dc838c 100644
--- a/pkg/api/v1/verification_types.go
+++ b/pkg/api/v1/verification_types.go
@@ -52,13 +52,11 @@ const (
 	TransmissionRiskNegative          = 6
 )
 
-var (
-	ValidReportTypes = map[string]bool{
-		ReportTypeConfirmed: true,
-		ReportTypeClinical:  true,
-		ReportTypeNegative:  true,
-	}
-)
+var ValidReportTypes = map[string]bool{
+	ReportTypeConfirmed: true,
+	ReportTypeClinical:  true,
+	ReportTypeNegative:  true,
+}
 
 // VerificationClaims represents the accepted Claims portion of the verification certificate JWT.
 // This data is used to set data on the uploaded TEKs and will be reflected on export. See the export file format:
diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go
index 39a091b..3a00b22 100644
--- a/pkg/cache/cache.go
+++ b/pkg/cache/cache.go
@@ -106,7 +106,6 @@ func (c *Cache) WriteThruLookup(name string, primaryLookup Func) (interface{}, e
 		expiresAt: time.Now().Add(c.expireAfter).UnixNano(),
 	}
 	return newData, nil
-
 }
 
 // Lookup checks the cache for a non-expired object by the supplied key name.
diff --git a/pkg/cryptorand/cryptorand.go b/pkg/cryptorand/cryptorand.go
new file mode 100644
index 0000000..876ccf1
--- /dev/null
+++ b/pkg/cryptorand/cryptorand.go
@@ -0,0 +1,45 @@
+// Copyright 2021 Google 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.
+
+// Package cryptorand defines a rand.Source from crypto/rand.
+package cryptorand
+
+import (
+	crand "crypto/rand"
+	"encoding/binary"
+	"fmt"
+	mrand "math/rand"
+)
+
+// NewSource returns a new math/rand.Source that uses crypto/rand as the random
+// generation.
+func NewSource() mrand.Source64 {
+	return new(src)
+}
+
+type src struct{}
+
+func (s *src) Seed(seed int64) {}
+
+func (s *src) Int63() int64 {
+	return int64(s.Uint64() & ^uint64(1<<63))
+}
+
+func (s *src) Uint64() uint64 {
+	var v uint64
+	if err := binary.Read(crand.Reader, binary.BigEndian, &v); err != nil {
+		panic(fmt.Sprintf("failed to read random: %v", err))
+	}
+	return v
+}
diff --git a/pkg/keys/azure_keyvault.go b/pkg/keys/azure_keyvault.go
index e4412dd..4815001 100644
--- a/pkg/keys/azure_keyvault.go
+++ b/pkg/keys/azure_keyvault.go
@@ -44,8 +44,10 @@ func init() {
 }
 
 // Compile-time check to verify implements interface.
-var _ KeyManager = (*AzureKeyVault)(nil)
-var _ crypto.Signer = (*AzureKeyVaultSigner)(nil)
+var (
+	_ KeyManager    = (*AzureKeyVault)(nil)
+	_ crypto.Signer = (*AzureKeyVaultSigner)(nil)
+)
 
 // AzureKeyVault implements the keys.KeyManager interface and can be used to
 // sign export files.
@@ -251,7 +253,6 @@ func (v *AzureKeyVault) Decrypt(ctx context.Context, keyID string, ciphertext []
 	}
 
 	return plaintext, nil
-
 }
 
 // NewSigner creates a new signer that uses a key in HashiCorp Vault's transit
diff --git a/pkg/keys/filesystem.go b/pkg/keys/filesystem.go
index 078cf0a..66475ec 100644
--- a/pkg/keys/filesystem.go
+++ b/pkg/keys/filesystem.go
@@ -41,9 +41,11 @@ func init() {
 	RegisterManager("FILESYSTEM", NewFilesystem)
 }
 
-var _ EncryptionKeyManager = (*Filesystem)(nil)
-var _ KeyManager = (*Filesystem)(nil)
-var _ SigningKeyManager = (*Filesystem)(nil)
+var (
+	_ EncryptionKeyManager = (*Filesystem)(nil)
+	_ KeyManager           = (*Filesystem)(nil)
+	_ SigningKeyManager    = (*Filesystem)(nil)
+)
 
 // Filesystem is a key manager that uses the filesystem to store and retrieve
 // keys. It should only be used for local development and testing.
@@ -64,7 +66,7 @@ type Filesystem struct {
 func NewFilesystem(ctx context.Context, cfg *Config) (KeyManager, error) {
 	root := cfg.FilesystemRoot
 	if root != "" {
-		if err := os.MkdirAll(root, 0700); err != nil {
+		if err := os.MkdirAll(root, 0o700); err != nil {
 			return nil, err
 		}
 	}
@@ -264,7 +266,7 @@ func (k *Filesystem) CreateSigningKey(_ context.Context, parent, name string) (s
 	defer k.mu.Unlock()
 
 	pth := filepath.Join(k.root, parent, name)
-	if err := os.MkdirAll(pth, 0700); err != nil {
+	if err := os.MkdirAll(pth, 0o700); err != nil {
 		return "", fmt.Errorf("failed to create directory for key: %w", err)
 	}
 
@@ -290,7 +292,7 @@ func (k *Filesystem) CreateSigningKey(_ context.Context, parent, name string) (s
 	if err != nil {
 		return "", fmt.Errorf("failed to generate metadata file: %w", err)
 	}
-	if err := ioutil.WriteFile(metadataPath, b, 0600); err != nil {
+	if err := ioutil.WriteFile(metadataPath, b, 0o600); err != nil {
 		return "", fmt.Errorf("failed to create metadata file: %w", err)
 	}
 	return strings.TrimPrefix(pth, k.root), nil
@@ -304,7 +306,7 @@ func (k *Filesystem) CreateEncryptionKey(_ context.Context, parent, name string)
 	defer k.mu.Unlock()
 
 	pth := filepath.Join(k.root, parent, name)
-	if err := os.MkdirAll(pth, 0700); err != nil {
+	if err := os.MkdirAll(pth, 0o700); err != nil {
 		return "", fmt.Errorf("failed to create directory for key: %w", err)
 	}
 
@@ -330,7 +332,7 @@ func (k *Filesystem) CreateEncryptionKey(_ context.Context, parent, name string)
 	if err != nil {
 		return "", fmt.Errorf("failed to generate metadata file: %w", err)
 	}
-	if err := ioutil.WriteFile(metadataPath, b, 0600); err != nil {
+	if err := ioutil.WriteFile(metadataPath, b, 0o600); err != nil {
 		return "", fmt.Errorf("failed to create metadata file: %w", err)
 	}
 	return strings.TrimPrefix(pth, k.root), nil
@@ -359,7 +361,7 @@ func (k *Filesystem) CreateKeyVersion(_ context.Context, parent string) (string,
 			return "", fmt.Errorf("failed to marshal signing key: %w", err)
 		}
 		pth := filepath.Join(k.root, parent, strconv.FormatInt(time.Now().UnixNano(), 10))
-		if err := ioutil.WriteFile(pth, b, 0600); err != nil {
+		if err := ioutil.WriteFile(pth, b, 0o600); err != nil {
 			return "", fmt.Errorf("failed to write signing key to disk: %w", err)
 		}
 		return strings.TrimPrefix(pth, k.root), nil
@@ -369,7 +371,7 @@ func (k *Filesystem) CreateKeyVersion(_ context.Context, parent string) (string,
 			return "", fmt.Errorf("failed to generate encryption key: %w", err)
 		}
 		pth := filepath.Join(k.root, parent, strconv.FormatInt(time.Now().UnixNano(), 10))
-		if err := ioutil.WriteFile(pth, ek, 0600); err != nil {
+		if err := ioutil.WriteFile(pth, ek, 0o600); err != nil {
 			return "", fmt.Errorf("failed to write encryption key to disk: %w", err)
 		}
 		return strings.TrimPrefix(pth, k.root), nil
diff --git a/pkg/keys/google_cloud_kms.go b/pkg/keys/google_cloud_kms.go
index b95bbf4..49e60d8 100644
--- a/pkg/keys/google_cloud_kms.go
+++ b/pkg/keys/google_cloud_kms.go
@@ -19,6 +19,7 @@ package keys
 import (
 	"context"
 	"crypto"
+	"errors"
 	"fmt"
 	"time"
 
@@ -36,8 +37,10 @@ func init() {
 }
 
 // Compile-time check to verify implements interface.
-var _ KeyManager = (*GoogleCloudKMS)(nil)
-var _ SigningKeyManager = (*GoogleCloudKMS)(nil)
+var (
+	_ KeyManager        = (*GoogleCloudKMS)(nil)
+	_ SigningKeyManager = (*GoogleCloudKMS)(nil)
+)
 
 // GoogleCloudKMS implements the keys.KeyManager interface and can be used to sign
 // export files.
@@ -135,7 +138,7 @@ func (kms *GoogleCloudKMS) SigningKeyVersions(ctx context.Context, parent string
 	})
 	for {
 		resp, err := it.Next()
-		if err == iterator.Done {
+		if errors.Is(err, iterator.Done) {
 			break
 		}
 		if err != nil {
diff --git a/pkg/keys/hashicorp_vault.go b/pkg/keys/hashicorp_vault.go
index 2e3c5f8..ee0aac4 100644
--- a/pkg/keys/hashicorp_vault.go
+++ b/pkg/keys/hashicorp_vault.go
@@ -38,9 +38,11 @@ func init() {
 }
 
 // Compile-time check to verify implements interface.
-var _ KeyManager = (*HashiCorpVault)(nil)
-var _ SigningKeyManager = (*HashiCorpVault)(nil)
-var _ crypto.Signer = (*HashiCorpVaultSigner)(nil)
+var (
+	_ KeyManager        = (*HashiCorpVault)(nil)
+	_ SigningKeyManager = (*HashiCorpVault)(nil)
+	_ crypto.Signer     = (*HashiCorpVaultSigner)(nil)
+)
 
 // HashiCorpVault implements the keys.KeyManager interface and can be used to
 // sign export files and encrypt/decrypt data.
@@ -111,8 +113,6 @@ func (v *vaultKeyVersion) Signer(ctx context.Context) (crypto.Signer, error) {
 
 // SigningKeyVersions returns the signing keys for the given key name.
 func (v *HashiCorpVault) SigningKeyVersions(ctx context.Context, parent string) ([]SigningKeyVersion, error) {
-	var versions []SigningKeyVersion
-
 	pth := fmt.Sprintf("transit/keys/%s", parent)
 	result, err := v.client.Logical().Read(pth)
 	if err != nil {
@@ -136,6 +136,7 @@ func (v *HashiCorpVault) SigningKeyVersions(ctx context.Context, parent string)
 		return nil, fmt.Errorf("failed to decode result: %w", err)
 	}
 
+	versions := make([]SigningKeyVersion, 0, len(response.Versions))
 	for k, ver := range response.Versions {
 		publicKey, err := ParseECDSAPublicKey(ver.PublicKeyPEM)
 		if err != nil {
diff --git a/pkg/keys/keys.go b/pkg/keys/keys.go
index 33ba74c..dfaeb47 100644
--- a/pkg/keys/keys.go
+++ b/pkg/keys/keys.go
@@ -104,8 +104,10 @@ type EncryptionKeyManager interface {
 type KeyManagerFunc func(context.Context, *Config) (KeyManager, error)
 
 // managers is the list of registered key managers.
-var managers = make(map[string]KeyManagerFunc)
-var managersLock sync.RWMutex
+var (
+	managers     = make(map[string]KeyManagerFunc)
+	managersLock sync.RWMutex
+)
 
 // RegisterManager registers a new key manager with the given name. If a
 // manager is already registered with the given name, it panics. Managers are
diff --git a/pkg/observability/observability.go b/pkg/observability/observability.go
index 6991838..9f6d4a2 100644
--- a/pkg/observability/observability.go
+++ b/pkg/observability/observability.go
@@ -25,6 +25,7 @@ import (
 	"time"
 
 	"contrib.go.opencensus.io/integrations/ocsql"
+	"github.com/google/exposure-notifications-server/pkg/logging"
 	"go.opencensus.io/plugin/ocgrpc"
 	"go.opencensus.io/plugin/ochttp"
 	"go.opencensus.io/stats"
@@ -202,12 +203,16 @@ func WithBuildInfo(ctx context.Context, info BuildInfo) context.Context {
 //   // remaining of the function body.
 // }
 func RecordLatency(ctx context.Context, start time.Time, m *stats.Float64Measure, mutators ...*tag.Mutator) {
-	var additionalMutators []tag.Mutator
+	additionalMutators := make([]tag.Mutator, 0, len(mutators))
 	for _, t := range mutators {
 		additionalMutators = append(additionalMutators, *t)
 	}
+
 	// Calculate the millisecond number as float64. time.Duration.Millisecond()
 	// returns an integer.
 	latency := float64(time.Since(start)) / float64(time.Millisecond)
-	stats.RecordWithTags(ctx, additionalMutators, m.M(latency))
+	if err := stats.RecordWithTags(ctx, additionalMutators, m.M(latency)); err != nil {
+		logging.FromContext(ctx).Named("observability").
+			Errorw("failed to record latency", "error", err)
+	}
 }
diff --git a/pkg/observability/resource.go b/pkg/observability/resource.go
index d13931d..1d9904b 100644
--- a/pkg/observability/resource.go
+++ b/pkg/observability/resource.go
@@ -25,9 +25,7 @@ import (
 	"github.com/google/uuid"
 )
 
-var (
-	_ monitoredresource.Interface = (*stackdriverMonitoredResource)(nil)
-)
+var _ monitoredresource.Interface = (*stackdriverMonitoredResource)(nil)
 
 type stackdriverMonitoredResource struct {
 	Resource string
diff --git a/pkg/observability/stackdriver.go b/pkg/observability/stackdriver.go
index a76b13f..71daac7 100644
--- a/pkg/observability/stackdriver.go
+++ b/pkg/observability/stackdriver.go
@@ -64,14 +64,14 @@ func NewStackdriver(ctx context.Context, config *StackdriverConfig) (Exporter, e
 		},
 	}
 	exporter, err := stackdriver.NewExporter(options)
-
 	if err != nil {
 		return nil, fmt.Errorf("failed to create Stackdriver exporter: %w", err)
 	}
 	return &stackdriverExporter{
 		exporter: exporter,
 		config:   config,
-		options:  &options}, nil
+		options:  &options,
+	}, nil
 }
 
 func (e *stackdriverExporter) metricClient() (*monitoring.MetricClient, error) {
diff --git a/pkg/secrets/resolver.go b/pkg/secrets/resolver.go
index 4bd5496..3a0ce5f 100644
--- a/pkg/secrets/resolver.go
+++ b/pkg/secrets/resolver.go
@@ -109,7 +109,7 @@ func (r *secretResolver) resolve(ctx context.Context, envName, secretRef string)
 
 		secretFileName := r.filenameForSecret(envName + "." + secretRef)
 		secretFilePath := filepath.Join(r.dir, secretFileName)
-		if err := ioutil.WriteFile(secretFilePath, []byte(secretVal), 0600); err != nil {
+		if err := ioutil.WriteFile(secretFilePath, []byte(secretVal), 0o600); err != nil {
 			return "", fmt.Errorf("failed to write secret file for %q: %w", envName, err)
 		}
 
@@ -121,7 +121,7 @@ func (r *secretResolver) resolve(ctx context.Context, envName, secretRef string)
 
 // filenameForSecret returns the sha1 of the secret name.
 func (r *secretResolver) filenameForSecret(name string) string {
-	return fmt.Sprintf("%x", sha1.Sum([]byte(name)))
+	return fmt.Sprintf("%x", sha1.Sum([]byte(name))) //nolint:gosec
 }
 
 // ensureSecureDir creates the parent secretsDir with minimal permissions. If
@@ -133,11 +133,11 @@ func (r *secretResolver) ensureSecureDir() error {
 		return fmt.Errorf("failed to check if secure directory %q exists: %w", r.dir, err)
 	}
 	if os.IsNotExist(err) {
-		if err := os.MkdirAll(r.dir, 0700); err != nil {
+		if err := os.MkdirAll(r.dir, 0o700); err != nil {
 			return fmt.Errorf("failed to create secure directory %q: %w", r.dir, err)
 		}
 	} else {
-		if stat.Mode().Perm() != os.FileMode(0700) {
+		if stat.Mode().Perm() != os.FileMode(0o700) {
 			return fmt.Errorf("secure directory %q exists and is not restricted %v", r.dir, stat.Mode())
 		}
 	}
diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go
index 6365fc6..6e714ce 100644
--- a/pkg/secrets/secrets.go
+++ b/pkg/secrets/secrets.go
@@ -37,8 +37,10 @@ type SecretManager interface {
 type SecretManagerFunc func(context.Context, *Config) (SecretManager, error)
 
 // managers is the list of registered secret managers.
-var managers = make(map[string]SecretManagerFunc)
-var managersLock sync.RWMutex
+var (
+	managers     = make(map[string]SecretManagerFunc)
+	managersLock sync.RWMutex
+)
 
 // RegisterManager registers a new secret manager with the given name. If a
 // manager is already registered with the given name, it panics. Managers are
diff --git a/pkg/server/metrics.go b/pkg/server/metrics.go
index 12e8765..7efac0c 100644
--- a/pkg/server/metrics.go
+++ b/pkg/server/metrics.go
@@ -40,7 +40,7 @@ func ServeMetricsIfPrometheus(ctx context.Context) error {
 
 		exporter, err := prometheus.NewExporter(prometheus.Options{})
 		if err != nil {
-			return fmt.Errorf("failed to create prometheus exporter: %v", err)
+			return fmt.Errorf("failed to create prometheus exporter: %w", err)
 		}
 
 		go func() {
diff --git a/pkg/util/generate.go b/pkg/util/generate.go
index b0d6403..04bbf79 100644
--- a/pkg/util/generate.go
+++ b/pkg/util/generate.go
@@ -167,7 +167,7 @@ func RandomExposureKey(intervalNumber int32, intervalCount int32, transmissionRi
 	}
 	return v1.ExposureKey{
 		Key:              key,
-		IntervalNumber:   int32(intervalNumber),
+		IntervalNumber:   intervalNumber,
 		IntervalCount:    intervalCount,
 		TransmissionRisk: transmissionRisk,
 	}, nil
diff --git a/scripts/presubmit.sh b/scripts/presubmit.sh
index b38c309..e9d7e94 100755
--- a/scripts/presubmit.sh
+++ b/scripts/presubmit.sh
@@ -50,53 +50,8 @@ OUT="$(go test -i -tags=all ./... 2>&1)" || {
 }
 
 
-echo "🧹 Verify formatting"
-make fmtcheck || {
-  echo "✋ Found formatting errors."
-  exit 1
-}
-
-
-echo "🐝 Lint"
-make staticcheck || {
-  echo "✋ Found linter errors."
-  exit 1
-}
-
-
-echo "🦶 Verify bodyclose"
-make bodyclose || {
-  echo "✋ Found unclosed response bodies."
-  exit 1
-}
-
-
-echo "🐝 Verify spelling"
-make spellcheck || {
-  echo "✋ Found spelling errors."
-  exit 1
-}
-
-
-echo "🌌 Verify and tidy module"
-OUT="$(go mod verify 2>&1 && go mod tidy 2>&1)" || {
-  echo "✋ Error validating module"
-  echo "\n\n${OUT}\n\n"
-  exit 1
-}
-OUT="$(git diff go.mod)"
-if [ -n "${OUT}" ]; then
-  echo "✋ go.mod is out of sync - run 'go mod tidy'."
-  exit 1
-fi
-OUT="$(git diff go.sum)"
-if [ -n "${OUT}" ]; then
-  echo "✋ go.sum is out of sync - run 'go mod tidy'."
-  exit 1
-fi
-
-
 echo "🧪 Test"
 make test-acc
+
 echo "🔬 Test Coverage"
 make test-coverage
diff --git a/tools/example-verification-signing/main.go b/tools/example-verification-signing/main.go
index 4f111b5..7836c59 100644
--- a/tools/example-verification-signing/main.go
+++ b/tools/example-verification-signing/main.go
@@ -181,12 +181,16 @@ func main() {
 		// 3. Concatenate the two octet sequences in the order R and then S.
 		//	 	(Note that many ECDSA implementations will directly produce this
 		//	 	concatenation as their output.)
-		sig = append(rBytesPadded, sBytesPadded...)
+		sig = make([]byte, 0, len(rBytesPadded)+len(sBytesPadded))
+		sig = append(sig, rBytesPadded...)
+		sig = append(sig, sBytesPadded...)
 
 		// 4.  The resulting 64-octet sequence is the JWS Signature value.
 		response.VerificationCertificate = strings.Join([]string{signingString, jwt.EncodeSegment(sig)}, ".")
 		c.JSON(http.StatusOK, response)
 	})
 
-	router.Run()
+	if err := router.Run(); err != nil {
+		log.Fatal(err)
+	}
 }
diff --git a/tools/export-analyzer/main.go b/tools/export-analyzer/main.go
index 271dea1..f21fb58 100644
--- a/tools/export-analyzer/main.go
+++ b/tools/export-analyzer/main.go
@@ -72,11 +72,11 @@ func realMain() error {
 	}
 
 	var errors *multierror.Error
-	var results []*analysis
+	results := make([]*analysis, 0, len(matches))
 	for _, m := range matches {
 		result, err := analyzeOne(m, *showSig, *printJSON)
 		if err != nil {
-			errors = multierror.Append(errors, fmt.Errorf("%s: %s", m, err))
+			errors = multierror.Append(errors, fmt.Errorf("%s: %w", m, err))
 			continue
 		}
 		results = append(results, result)
diff --git a/tools/export-generate/main.go b/tools/export-generate/main.go
index 2c4acf1..d2e1a4a 100644
--- a/tools/export-generate/main.go
+++ b/tools/export-generate/main.go
@@ -211,7 +211,7 @@ func (e *exportFileWriter) writeFile() {
 	}
 	fileName := fmt.Sprintf(e.exportBatch.FilenameRoot+"%d-records-%d-of-%d"+filenameSuffix, e.totalKeys, e.curBatch, e.numBatches)
 	log.Printf("Creating %v", fileName)
-	err = ioutil.WriteFile(fileName, data, 0666)
+	err = ioutil.WriteFile(fileName, data, 0o600)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/tools/export-viz/main.go b/tools/export-viz/main.go
index 51eddb5..9ea076a 100644
--- a/tools/export-viz/main.go
+++ b/tools/export-viz/main.go
@@ -29,9 +29,7 @@ import (
 	exportpb "github.com/google/exposure-notifications-server/internal/pb/export"
 )
 
-var (
-	filePath = flag.String("file", "", "path to the export file")
-)
+var filePath = flag.String("file", "", "path to the export file")
 
 // Example usage - requires graphviz
 //
@@ -137,7 +135,7 @@ func sameReportType(a, b *exportpb.TemporaryExposureKey) bool {
 }
 
 func sameTransmissionRisk(a, b *exportpb.TemporaryExposureKey) bool {
-	//lint:ignore SA1019 may be set on v1 files.
+	//nolint:staticcheck // may be set on v1 files.
 	return a.GetTransmissionRiskLevel() == b.GetTransmissionRiskLevel()
 }
 
diff --git a/tools/exposure-client/main.go b/tools/exposure-client/main.go
index 8f56375..7961eb9 100644
--- a/tools/exposure-client/main.go
+++ b/tools/exposure-client/main.go
@@ -17,6 +17,7 @@ package main
 
 import (
 	"bytes"
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"flag"
@@ -24,12 +25,14 @@ import (
 	"io"
 	"io/ioutil"
 	"net/http"
-	"os"
 	"strings"
 	"time"
 
+	"github.com/google/exposure-notifications-server/internal/buildinfo"
 	verifyapi "github.com/google/exposure-notifications-server/pkg/api/v1"
+	"github.com/google/exposure-notifications-server/pkg/logging"
 	"github.com/google/exposure-notifications-server/pkg/util"
+	"github.com/sethvargo/go-signalcontext"
 )
 
 var (
@@ -41,14 +44,29 @@ var (
 )
 
 func main() {
-	if err := realMain(); err != nil {
-		fmt.Printf("failed to create exposures: %v\n", err)
-		os.Exit(1)
+	ctx, done := signalcontext.OnInterrupt()
+
+	logger := logging.NewLoggerFromEnv().
+		With("build_id", buildinfo.BuildID).
+		With("build_tag", buildinfo.BuildTag)
+	ctx = logging.WithLogger(ctx, logger)
+
+	defer func() {
+		done()
+		if r := recover(); r != nil {
+			logger.Fatalw("application panic", "panic", r)
+		}
+	}()
+
+	err := realMain(ctx)
+	done()
+
+	if err != nil {
+		logger.Fatal(err)
 	}
-	fmt.Printf("success!\n")
 }
 
-func realMain() error {
+func realMain(ctx context.Context) error {
 	flag.Parse()
 
 	exposureKeys := util.GenerateExposureKeys(*numKeys, *transmissionRiskFlag, false)
@@ -75,13 +93,13 @@ func realMain() error {
 	}
 	fmt.Printf("generated json: \n%s\n", body)
 
-	if _, err := sendRequest(bytes.NewReader(body)); err != nil {
+	if _, err := sendRequest(ctx, bytes.NewReader(body)); err != nil {
 		return fmt.Errorf("failed to send first request: %w", err)
 	}
 
 	if *twice {
 		time.Sleep(1 * time.Second)
-		if _, err := sendRequest(bytes.NewReader(body)); err != nil {
+		if _, err := sendRequest(ctx, bytes.NewReader(body)); err != nil {
 			return fmt.Errorf("failed to send second request: %w", err)
 		}
 	}
@@ -89,9 +107,9 @@ func realMain() error {
 	return nil
 }
 
-func sendRequest(data io.Reader) ([]byte, error) {
+func sendRequest(ctx context.Context, data io.Reader) ([]byte, error) {
 	url := strings.ReplaceAll(*host+"/v1/publish", "//v1", "/v1")
-	req, err := http.NewRequest("POST", url, data)
+	req, err := http.NewRequestWithContext(ctx, "POST", url, data)
 	if err != nil {
 		return nil, fmt.Errorf("failed to build request: %w", err)
 	}
diff --git a/tools/sign/main.go b/tools/sign/main.go
index 24b4900..eb7de20 100644
--- a/tools/sign/main.go
+++ b/tools/sign/main.go
@@ -34,9 +34,7 @@ import (
 	"github.com/sethvargo/go-signalcontext"
 )
 
-var (
-	messageToSign = flag.String("message", "hello world", "string message to sign")
-)
+var messageToSign = flag.String("message", "hello world", "string message to sign")
 
 func main() {
 	ctx, done := signalcontext.OnInterrupt()
diff --git a/tools/unwrap-signature/main.go b/tools/unwrap-signature/main.go
index f0dea6b..db9d529 100644
--- a/tools/unwrap-signature/main.go
+++ b/tools/unwrap-signature/main.go
@@ -53,7 +53,7 @@ func main() {
 	log.Printf("Data: \n%v", teksl)
 	sig := teksl.Signatures[0].Signature
 
-	err = ioutil.WriteFile(*outFile, sig, 0600)
+	err = ioutil.WriteFile(*outFile, sig, 0o600)
 	if err != nil {
 		log.Fatalf("unable to write output file: %v", err)
 	}


Test patch:
diff --git a/docs/playbooks/playbook_test.go b/docs/playbooks/playbook_test.go
index b9f0b63..d533bf7 100644
--- a/docs/playbooks/playbook_test.go
+++ b/docs/playbooks/playbook_test.go
@@ -53,7 +53,7 @@ func allPlaybookNames(t *testing.T) []string {
 	if err != nil {
 		t.Fatalf("failed to find all playbooks: %s", err)
 	}
-	var ret []string
+	ret := make([]string, 0, len(files))
 	for _, x := range files {
 		basename := filepath.Base(x)
 		ret = append(ret, basename[:len(basename)-len(".md")])
@@ -71,7 +71,7 @@ func allAlertNames(t *testing.T) []string {
 	if diag.HasErrors() {
 		t.Fatalf("failed to decode body: %v", diag)
 	}
-	var ret []string
+	ret := make([]string, 0, len(c.Resources))
 	for _, res := range c.Resources {
 		if res.Type != "google_monitoring_alert_policy" {
 			continue
@@ -103,7 +103,7 @@ func setDiff(xs, ys []string) []string {
 			delete(s1, k)
 		}
 	}
-	var ret []string
+	ret := make([]string, 0, len(s1))
 	for k := range s1 {
 		ret = append(ret, k)
 	}
diff --git a/internal/authorizedapp/database/authorized_app_test.go b/internal/authorizedapp/database/authorized_app_test.go
index 3da8f59..2aa5eef 100644
--- a/internal/authorizedapp/database/authorized_app_test.go
+++ b/internal/authorizedapp/database/authorized_app_test.go
@@ -296,5 +296,4 @@ func TestListAuthorizedApps(t *testing.T) {
 	if diff := cmp.Diff(apps, got); diff != "" {
 		t.Errorf("mismatch (-want, +got):\n%s", diff)
 	}
-
 }
diff --git a/internal/database/connection_test.go b/internal/database/connection_test.go
index a2e4ebb..18febde 100644
--- a/internal/database/connection_test.go
+++ b/internal/database/connection_test.go
@@ -55,7 +55,11 @@ func TestDBValues(t *testing.T) {
 	}
 
 	for _, tc := range testCases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			got := dbValues(&tc.config)
 			if diff := cmp.Diff(tc.want, got); diff != "" {
 				t.Errorf("mismatch (-want, +got):\n%s", diff)
diff --git a/internal/export/batcher_test.go b/internal/export/batcher_test.go
index 358bf69..5abf2b2 100644
--- a/internal/export/batcher_test.go
+++ b/internal/export/batcher_test.go
@@ -105,7 +105,11 @@ func TestMakeBatchRanges(t *testing.T) {
 	}
 
 	for _, tc := range testCases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			nowT := fromSimpleTime(t, now)
 			latestEndT := fromSimpleTime(t, tc.latestEnd)
 
@@ -154,7 +158,7 @@ func toSimpleTime(t *testing.T, tm time.Time) string {
 
 func toSimpleBatchRange(t *testing.T, batches []batchRange) []simpleBatchRange {
 	t.Helper()
-	var simple []simpleBatchRange
+	simple := make([]simpleBatchRange, 0, len(batches))
 	for _, br := range batches {
 		simple = append(simple, simpleBatchRange{start: toSimpleTime(t, br.start), end: toSimpleTime(t, br.end)})
 	}
diff --git a/internal/export/database/export_test.go b/internal/export/database/export_test.go
index b9836f6..735d0e4 100644
--- a/internal/export/database/export_test.go
+++ b/internal/export/database/export_test.go
@@ -867,7 +867,7 @@ func TestAddExportFileSkipsDuplicates(t *testing.T) {
 	ef.BucketName = "bucket-2"
 	err = testDB.InTx(ctx, pgx.ReadCommitted, func(tx pgx.Tx) error {
 		if err := addExportFile(ctx, tx, ef); err != nil {
-			if err == database.ErrKeyConflict {
+			if errors.Is(err, database.ErrKeyConflict) {
 				return nil // Expected result.
 			}
 			return err
diff --git a/internal/export/server_test.go b/internal/export/server_test.go
index d502e04..10191bb 100644
--- a/internal/export/server_test.go
+++ b/internal/export/server_test.go
@@ -71,7 +71,11 @@ func TestNewServer(t *testing.T) {
 	}
 
 	for _, tc := range testCases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			got, err := NewServer(&Config{}, tc.env)
 			if tc.err != nil {
 				if err.Error() != tc.err.Error() {
diff --git a/internal/export/worker_test.go b/internal/export/worker_test.go
index 3cd8a32..c4778b6 100644
--- a/internal/export/worker_test.go
+++ b/internal/export/worker_test.go
@@ -163,7 +163,10 @@ func TestBatchExposures(t *testing.T) {
 	}
 
 	for _, tc := range tests {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
 
 			ctx := project.TestContext(t)
 			testDB, _ := testDatabaseInstance.NewDatabase(t)
diff --git a/internal/exportimport/database/exportimport_test.go b/internal/exportimport/database/exportimport_test.go
index 3ec04f3..6f606e7 100644
--- a/internal/exportimport/database/exportimport_test.go
+++ b/internal/exportimport/database/exportimport_test.go
@@ -152,7 +152,7 @@ func TestAddImportFiles(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	var want []*model.ImportFile
+	want := make([]*model.ImportFile, 0, len(filenames))
 	for _, fname := range filenames {
 		want = append(want,
 			&model.ImportFile{
diff --git a/internal/federationin/federationin_test.go b/internal/federationin/federationin_test.go
index 3b1ee34..c4e6000 100644
--- a/internal/federationin/federationin_test.go
+++ b/internal/federationin/federationin_test.go
@@ -143,6 +143,8 @@ func (sdb *syncDB) startFederationSync(ctx context.Context, query *model.Federat
 func TestFederationPull(t *testing.T) {
 	t.Parallel()
 
+	ctx := project.TestContext(t)
+
 	batchTime := time.Now().Truncate(time.Second)
 	// Make all items have reasonable interval numbers based on test time.
 	intervalNumber := publishmodel.IntervalNumber(batchTime.Add(-2 * 24 * time.Hour))
@@ -151,7 +153,7 @@ func TestFederationPull(t *testing.T) {
 	ccc = setIntervalNumber(ccc, intervalNumber)
 	ddd = setIntervalNumber(ddd, intervalNumber)
 
-	testCases := []struct {
+	cases := []struct {
 		name           string
 		batchSize      int
 		fetchResponses []*federation.FederationFetchResponse
@@ -407,9 +409,12 @@ func TestFederationPull(t *testing.T) {
 		*/
 	}
 
-	for _, tc := range testCases {
+	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
-			ctx := project.TestContext(t)
+			t.Parallel()
+
 			query := &model.FederationInQuery{
 				QueryID: queryID,
 			}
diff --git a/internal/federationout/federationout_test.go b/internal/federationout/federationout_test.go
index e4f989e..3a79eb3 100644
--- a/internal/federationout/federationout_test.go
+++ b/internal/federationout/federationout_test.go
@@ -72,13 +72,15 @@ func addDaysSinceOnset(e *model.Exposure, daysSince int32) *model.Exposure {
 	return e
 }
 
-func reviseExposure(e *model.Exposure, newReportType string, clearOnset bool) *model.Exposure {
+func reviseExposure(tb testing.TB, e *model.Exposure, newReportType string, clearOnset bool) *model.Exposure {
 	e.SetRevisedReportType(newReportType)
 	if e.HasDaysSinceSymptomOnset() && !clearOnset {
 		e.SetRevisedDaysSinceSymptomOnset(*e.DaysSinceSymptomOnset)
 	}
 	e.SetRevisedTransmissionRisk(model.ReportTypeTransmissionRisk(newReportType, 0))
-	e.SetRevisedAt(e.CreatedAt.Add(time.Second))
+	if err := e.SetRevisedAt(e.CreatedAt.Add(time.Second)); err != nil {
+		tb.Fatal(err)
+	}
 	return e
 }
 
@@ -133,7 +135,9 @@ func (t *testIterator) provideInput(_ context.Context, _ publishdb.IterateExposu
 func TestFetch(t *testing.T) {
 	t.Parallel()
 
-	testCases := []struct {
+	ctx := project.TestContext(t)
+
+	cases := []struct {
 		name              string
 		includeRegions    []string
 		excludeRegions    []string
@@ -234,7 +238,7 @@ func TestFetch(t *testing.T) {
 				addDaysSinceOnset(makeExposure(aaa, "confirmed", "US", false), 2),
 			},
 			revisedIterations: []interface{}{
-				reviseExposure(addDaysSinceOnset(makeExposure(bbb, "likely", "US", true), 1), "confirmed", false),
+				reviseExposure(t, addDaysSinceOnset(makeExposure(bbb, "likely", "US", true), 1), "confirmed", false),
 			},
 			want: &federation.FederationFetchResponse{
 				Keys: []*federation.ExposureKey{
@@ -284,7 +288,7 @@ func TestFetch(t *testing.T) {
 				addDaysSinceOnset(makeExposure(aaa, "likely", "US", false), 2),
 			},
 			revisedIterations: []interface{}{
-				reviseExposure(addDaysSinceOnset(makeExposure(aaa, "likely", "US", false), 2), "negative", true),
+				reviseExposure(t, addDaysSinceOnset(makeExposure(aaa, "likely", "US", false), 2), "negative", true),
 			},
 			want: &federation.FederationFetchResponse{
 				Keys: []*federation.ExposureKey{
@@ -338,7 +342,7 @@ func TestFetch(t *testing.T) {
 			},
 			revisedIterations: []interface{}{
 				// In this test, we shouldn't get here because of the timeout in the initial set.
-				reviseExposure(addDaysSinceOnset(makeExposure(aaa, "likely", "US", true), 2), "confirmed", true),
+				reviseExposure(t, addDaysSinceOnset(makeExposure(aaa, "likely", "US", true), 2), "confirmed", true),
 			},
 			want: &federation.FederationFetchResponse{
 				Keys: []*federation.ExposureKey{
@@ -389,9 +393,9 @@ func TestFetch(t *testing.T) {
 			},
 			revisedIterations: []interface{}{
 				// In this test, we shouldn't get here because of the timeout in the initial set.
-				reviseExposure(addDaysSinceOnset(makeExposure(aaa, "likely", "US", true), -1), "confirmed", false),
+				reviseExposure(t, addDaysSinceOnset(makeExposure(aaa, "likely", "US", true), -1), "confirmed", false),
 				timeout{},
-				reviseExposure(addDaysSinceOnset(makeExposure(bbb, "likely", "US", true), -1), "confirmed", false),
+				reviseExposure(t, addDaysSinceOnset(makeExposure(bbb, "likely", "US", true), -1), "confirmed", false),
 			},
 			want: &federation.FederationFetchResponse{
 				Keys: []*federation.ExposureKey{
@@ -505,9 +509,12 @@ func TestFetch(t *testing.T) {
 		},
 	}
 
-	for _, tc := range testCases {
+	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
-			ctx := project.TestContext(t)
+			t.Parallel()
+
 			env := serverenv.New(ctx)
 			server := Server{
 				env: env,
@@ -561,7 +568,7 @@ func TestRawToken(t *testing.T) {
 func TestRawTokenErrors(t *testing.T) {
 	t.Parallel()
 
-	testCases := []struct {
+	cases := []struct {
 		name  string
 		mdMap map[string][]string
 	}{
@@ -587,11 +594,14 @@ func TestRawTokenErrors(t *testing.T) {
 		},
 	}
 
-	for _, tc := range testCases {
+	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
 			ctx := metadata.NewIncomingContext(project.TestContext(t), tc.mdMap)
-			_, gotErr := rawToken(ctx)
-			if gotErr == nil {
+			if _, err := rawToken(ctx); err == nil {
 				t.Errorf("missing error response")
 			}
 		})
@@ -602,7 +612,7 @@ func TestRawTokenErrors(t *testing.T) {
 func TestIntersect(t *testing.T) {
 	t.Parallel()
 
-	testCases := []struct {
+	cases := []struct {
 		name string
 		aa   []string
 		bb   []string
@@ -646,10 +656,13 @@ func TestIntersect(t *testing.T) {
 		},
 	}
 
-	for _, tc := range testCases {
+	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
-			got := intersect(tc.aa, tc.bb)
+			t.Parallel()
 
+			got := intersect(tc.aa, tc.bb)
 			if diff := cmp.Diff(tc.want, got); diff != "" {
 				t.Errorf("mismatch (-want, +got):\n%s", diff)
 			}
@@ -661,7 +674,7 @@ func TestIntersect(t *testing.T) {
 func TestUnion(t *testing.T) {
 	t.Parallel()
 
-	testCases := []struct {
+	cases := []struct {
 		name string
 		aa   []string
 		bb   []string
@@ -705,10 +718,13 @@ func TestUnion(t *testing.T) {
 		},
 	}
 
-	for _, tc := range testCases {
+	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
-			got := union(tc.aa, tc.bb)
+			t.Parallel()
 
+			got := union(tc.aa, tc.bb)
 			if diff := cmp.Diff(tc.want, got); diff != "" {
 				t.Errorf("mismatch (-want, +got):\n%s", diff)
 			}
diff --git a/internal/integration/integration_test.go b/internal/integration/integration_test.go
index cbc3147..b7f91d9 100644
--- a/internal/integration/integration_test.go
+++ b/internal/integration/integration_test.go
@@ -156,7 +156,7 @@ func TestEndToEnd(t *testing.T) {
 
 			// Try to marshal the result as JSON to verify its API compatible
 			if _, err := json.Marshal(key); err != nil {
-				return fmt.Errorf("failed to marshal as json: %v", err)
+				return fmt.Errorf("failed to marshal as json: %w", err)
 			}
 
 			if got, want := *key.BatchSize, int32(1); got != want {
diff --git a/internal/jsonutil/unmarshal_test.go b/internal/jsonutil/unmarshal_test.go
index 73fa1b7..12e411e 100644
--- a/internal/jsonutil/unmarshal_test.go
+++ b/internal/jsonutil/unmarshal_test.go
@@ -80,6 +80,7 @@ func TestEmptyBody(t *testing.T) {
 	}
 	unmarshalTestHelper(t, invalidJSON, errors, http.StatusBadRequest)
 }
+
 func TestMultipleJson(t *testing.T) {
 	t.Parallel()
 
@@ -130,10 +131,10 @@ func TestInvalidStructure(t *testing.T) {
 		`{"badField": "doesn't exist"}`,
 	}
 	errors := []string{
-		`invalid value temporaryExposureKeys at position 28`,
-		`invalid value temporaryExposureKeys at position 31`,
-		`invalid value appPackageName at position 22`,
-		`invalid value regions at position 16`,
+		`invalid value "temporaryExposureKeys" at position 28`,
+		`invalid value "temporaryExposureKeys" at position 31`,
+		`invalid value "appPackageName" at position 22`,
+		`invalid value "regions" at position 16`,
 		`unknown field "badField"`,
 	}
 	unmarshalTestHelper(t, invalidJSON, errors, http.StatusBadRequest)
@@ -142,7 +143,7 @@ func TestInvalidStructure(t *testing.T) {
 func TestValidPublishMessage(t *testing.T) {
 	t.Parallel()
 
-	intervalNumber := int32(time.Date(2020, 04, 17, 20, 04, 01, 1, time.UTC).Unix() / 600)
+	intervalNumber := int32(time.Date(2020, 4, 17, 20, 4, 1, 1, time.UTC).Unix() / 600)
 	json := `{"temporaryExposureKeys": [
 		  {"key": "ABC", "rollingStartNumber": %v, "rollingPeriod": 144, "TransmissionRisk": 2},
 		  {"key": "DEF", "rollingStartNumber": %v, "rollingPeriod": 122, "TransmissionRisk": 2},
diff --git a/internal/jwks/jwks_test.go b/internal/jwks/jwks_test.go
index f6771ba..0910040 100644
--- a/internal/jwks/jwks_test.go
+++ b/internal/jwks/jwks_test.go
@@ -37,10 +37,13 @@ func TestMain(m *testing.M) {
 	m.Run()
 }
 
-var key1 = `{"kid":"r2v1","kty":"EC","crv":"P-256","x":"qcMMcLX1Z2afVAzypTMw1g3KN_OcdgvRDwOgpDWiswU","y":"RjK8Hc7pLLO_JADNhwZIxCXjCH95VHuWPoKVaCGkXiA"}`
-var key2 = `{"kid":"r2v2","kty":"EC","crv":"P-256","x":"F2MgtKg_cm-JfcJlrEUJMgXqXq1vHWRPMbBWEjzmN0U","y":"4U6g0nX9mVOGaHL8kYX10gL4Fsj-wNb4V9GMSJ7iLKk"}`
-var enc1 = `MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqcMMcLX1Z2afVAzypTMw1g3KN/Oc
+var (
+	key1 = `{"kid":"r2v1","kty":"EC","crv":"P-256","x":"qcMMcLX1Z2afVAzypTMw1g3KN_OcdgvRDwOgpDWiswU","y":"RjK8Hc7pLLO_JADNhwZIxCXjCH95VHuWPoKVaCGkXiA"}`
+	key2 = `{"kid":"r2v2","kty":"EC","crv":"P-256","x":"F2MgtKg_cm-JfcJlrEUJMgXqXq1vHWRPMbBWEjzmN0U","y":"4U6g0nX9mVOGaHL8kYX10gL4Fsj-wNb4V9GMSJ7iLKk"}`
+	enc1 = `MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqcMMcLX1Z2afVAzypTMw1g3KN/Oc
 dgvRDwOgpDWiswVGMrwdzukss78kAM2HBkjEJeMIf3lUe5Y+gpVoIaReIA==`
+)
+
 var enc2 = `MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEF2MgtKg/cm+JfcJlrEUJMgXqXq1v
 HWRPMbBWEjzmN0XhTqDSdf2ZU4ZocvyRhfXSAvgWyP7A1vhX0YxInuIsqQ==`
 
@@ -123,25 +126,25 @@ func TestUpdateHA(t *testing.T) {
 	//
 	// Again, each test tests individual pieces of the service, and then an
 	// "end-to-end" test is run where the DB is validated.
-	for i, test := range tests {
-		test := test
+	for _, tc := range tests {
+		tc := tc
 
-		t.Run(test.name, func(t *testing.T) {
+		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
 
 			// Start a local server to serve JSON data for the test.
 			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-				fmt.Fprintf(w, test.resp)
+				fmt.Fprintf(w, tc.resp)
 				w.Header().Set("Content-Type", "application/json")
 			}))
 			defer ts.Close()
 
-			// Set up the test.
+			// Set up the tc.
 			ctx := project.TestContext(t)
 			testDB, _ := testDatabaseInstance.NewDatabase(t)
 			mgr, err := NewManager(testDB, time.Minute, 5*time.Second)
 			if err != nil {
-				t.Fatalf("[%d] unexpected error: %v", i, err)
+				t.Fatalf("unexpected error: %v", err)
 			}
 			jwksURI := ts.URL
 			ha := &model.HealthAuthority{JwksURI: &jwksURI}
@@ -149,10 +152,10 @@ func TestUpdateHA(t *testing.T) {
 			// Test networking.
 			rxKeys, err := mgr.getKeys(ctx, ha)
 			if err != nil {
-				t.Fatalf("[%d] unexpected error: %v", i, err)
+				t.Fatalf("unexpected error: %v", err)
 			}
-			if string(rxKeys) != test.resp {
-				t.Fatalf("[%d] expected %v, got %v", i, test.resp, rxKeys)
+			if string(rxKeys) != tc.resp {
+				t.Fatalf("expected %v, got %v", tc.resp, rxKeys)
 			}
 
 			// Test the encoding of the keys/versions. (basically, can we decode the
@@ -161,71 +164,71 @@ func TestUpdateHA(t *testing.T) {
 			var versions map[string]string
 			encoded, versions, err = parseKeys(rxKeys)
 			if err != nil {
-				t.Fatalf("[%d] unexpected error: %v", i, err)
+				t.Fatalf("unexpected error: %v", err)
 			}
-			if !reflect.DeepEqual(encoded, test.encoded) {
-				t.Fatalf("[%d] encoded strings aren't equal expected %v, got %v", i, test.encoded, encoded)
+			if !reflect.DeepEqual(encoded, tc.encoded) {
+				t.Fatalf("encoded strings aren't equal expected %v, got %v", tc.encoded, encoded)
 			}
-			if !reflect.DeepEqual(versions, test.versions) {
-				t.Fatalf("[%d] versions aren't equal expected %v, got %v", i, test.versions, versions)
+			if !reflect.DeepEqual(versions, tc.versions) {
+				t.Fatalf("versions aren't equal expected %v, got %v", tc.versions, versions)
 			}
 
 			// Test we have correctly identified if keys are deleted or new, etc.
-			deadKeys, newKeys := findKeyMods(&test.ha, encoded)
-			if !reflect.DeepEqual(deadKeys, test.deadKeys) {
-				t.Fatalf("[%d] dead keys aren't equal expected %v, got %v", i, test.deadKeys, deadKeys)
+			deadKeys, newKeys := findKeyMods(&tc.ha, encoded)
+			if !reflect.DeepEqual(deadKeys, tc.deadKeys) {
+				t.Fatalf("dead keys aren't equal expected %v, got %v", tc.deadKeys, deadKeys)
 			}
-			if !reflect.DeepEqual(newKeys, test.newKeys) {
-				t.Fatalf("[%d] new keys aren't equal expected %v, got %v", i, test.newKeys, newKeys)
+			if !reflect.DeepEqual(newKeys, tc.newKeys) {
+				t.Fatalf("new keys aren't equal expected %v, got %v", tc.newKeys, newKeys)
 			}
 
 			//
 			// Now test end-to-end.
 			//
-			test.ha.JwksURI = &jwksURI
+			tc.ha.JwksURI = &jwksURI
 
 			// Add the HealthAuthority & Keys to the DB. Note, we need to remove all
 			// keys from the testing HealthAuthority before adding it to the DB as it's
 			// checked for empty. Also the function we're calling below (updateHA)
 			// expects the keys to be empty in the HealthAuthority.
 			var keys []*model.HealthAuthorityKey
-			keys, test.ha.Keys = test.ha.Keys, nil
+			keys, tc.ha.Keys = tc.ha.Keys, nil
 			haDB := hadb.New(mgr.db)
-			test.ha.Issuer, test.ha.Audience, test.ha.Name = "ISSUER", "AUDIENCE", "NAME"
-			if err := haDB.AddHealthAuthority(ctx, &test.ha); err != nil {
-				t.Fatalf("[%d] error adding the HealthAuthority, %v", i, err)
+			tc.ha.Issuer, tc.ha.Audience, tc.ha.Name = "ISSUER", "AUDIENCE", "NAME"
+			if err := haDB.AddHealthAuthority(ctx, &tc.ha); err != nil {
+				t.Fatalf("error adding the HealthAuthority, %v", err)
 			}
 			for _, key := range keys {
-				if err := haDB.AddHealthAuthorityKey(ctx, &test.ha, key); err != nil {
-					t.Errorf("[%d] error adding key: %v", i, err)
+				if err := haDB.AddHealthAuthorityKey(ctx, &tc.ha, key); err != nil {
+					t.Errorf("error adding key: %v", err)
 				}
 			}
 
 			// Now, run the whole flow for a HealthAuthority.
-			if err := mgr.updateHA(ctx, &test.ha); err != nil {
-				t.Fatalf("[%d] error updating: %v", i, err)
+			if err := mgr.updateHA(ctx, &tc.ha); err != nil {
+				t.Fatalf("error updating: %v", err)
 			}
 
 			// Check the DB.
-			if ha, err := haDB.GetHealthAuthorityByID(ctx, test.ha.ID); err != nil {
-				t.Fatalf("[%d] error retreiving HealthAuthority: %v", i, err)
+			if ha, err := haDB.GetHealthAuthorityByID(ctx, tc.ha.ID); err != nil {
+				t.Fatalf("error retreiving HealthAuthority: %v", err)
 			} else {
 				// Check the resultant keys.
-				if len(ha.Keys) != len(test.resKeys) {
-					t.Fatalf("[%d] key lengths different %d, expected %d", i, len(ha.Keys), len(test.resKeys))
+				if len(ha.Keys) != len(tc.resKeys) {
+					t.Fatalf("key lengths different %d, expected %d", len(ha.Keys), len(tc.resKeys))
 				}
 				for j := range ha.Keys {
-					if key := ha.Keys[j].PublicKeyPEM; key != test.resKeys[j] {
-						t.Errorf("[%d] wrong key[%d] %q, expected %q", i, j, key, test.resKeys[j])
+					if key := ha.Keys[j].PublicKeyPEM; key != tc.resKeys[j] {
+						t.Errorf("wrong key %q, expected %q", key, tc.resKeys[j])
 					}
 				}
 
 				// Check to see if we've deleted keys as needed as well, (ie the From time is
 				// populated).
 				var emptyTime time.Time
-				for _, j := range test.deadKeys {
+				for _, j := range tc.deadKeys {
 					if delTime := ha.Keys[j].From; reflect.DeepEqual(emptyTime, delTime) {
-						t.Errorf("[%d:%d] key not deleted %v", i, j, delTime)
+						t.Errorf("key not deleted %v", delTime)
 					}
 				}
 			}
@@ -244,10 +247,12 @@ func TestStrip(t *testing.T) {
 		{enc1, enc1},
 		{encodeKey(enc1), enc1},
 	}
-	for i, test := range tests {
-		k2 := strings.ReplaceAll(test.k2, "\n", "")
-		if stripped := stripKey(test.k1); stripped != k2 {
-			t.Errorf("[%d] compareKeys(%q) = %q, want %q", i, test.k1, stripped, k2)
+	for _, tc := range tests {
+		tc := tc
+
+		k2 := strings.ReplaceAll(tc.k2, "\n", "")
+		if stripped := stripKey(tc.k1); stripped != k2 {
+			t.Errorf("compareKeys(%q) = %q, want %q", tc.k1, stripped, k2)
 		}
 	}
 }
diff --git a/internal/keyrotation/rotate_test.go b/internal/keyrotation/rotate_test.go
index edaca2b..d89a619 100644
--- a/internal/keyrotation/rotate_test.go
+++ b/internal/keyrotation/rotate_test.go
@@ -166,6 +166,7 @@ func TestRotateKeys(t *testing.T) {
 			}
 
 			for _, k := range tc.keys {
+				k := k
 				if err := testInsertRawKey(ctx, t, testDB, &k); err != nil {
 					t.Error("Failed to insert keys: ", err)
 				}
diff --git a/internal/middleware/maintenance_test.go b/internal/middleware/maintenance_test.go
index 7270ec8..c655707 100644
--- a/internal/middleware/maintenance_test.go
+++ b/internal/middleware/maintenance_test.go
@@ -29,6 +29,8 @@ func (t *testConfig) MaintenanceMode() bool {
 }
 
 func TestHandle_Enabled(t *testing.T) {
+	t.Parallel()
+
 	responder := ProcessMaintenance(&testConfig{true})
 
 	r := &http.Request{}
@@ -46,6 +48,8 @@ func TestHandle_Enabled(t *testing.T) {
 }
 
 func TestHandle_Disabled(t *testing.T) {
+	t.Parallel()
+
 	responder := ProcessMaintenance(&testConfig{false})
 
 	r := &http.Request{}
diff --git a/internal/mirror/mirror_test.go b/internal/mirror/mirror_test.go
index 16ef81a..a8a2194 100644
--- a/internal/mirror/mirror_test.go
+++ b/internal/mirror/mirror_test.go
@@ -283,7 +283,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		}))
 		t.Cleanup(ts.Close)
 
-		_, err = s.downloadIndex(&mirrormodel.Mirror{
+		_, err = s.downloadIndex(ctx, &mirrormodel.Mirror{
 			IndexFile: ts.URL,
 		})
 
@@ -312,7 +312,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		}))
 		t.Cleanup(ts.Close)
 
-		_, err = s.downloadIndex(&mirrormodel.Mirror{
+		_, err = s.downloadIndex(ctx, &mirrormodel.Mirror{
 			IndexFile: ts.URL,
 		})
 		if err == nil {
@@ -340,7 +340,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		}))
 		t.Cleanup(ts.Close)
 
-		_, err = s.downloadIndex(&mirrormodel.Mirror{
+		_, err = s.downloadIndex(ctx, &mirrormodel.Mirror{
 			IndexFile: ts.URL,
 		})
 		if got, want := err.Error(), "response exceeds 1 bytes"; !strings.Contains(got, want) {
@@ -361,7 +361,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
 		t.Cleanup(ts.Close)
 
-		results, err := s.downloadIndex(&mirrormodel.Mirror{
+		results, err := s.downloadIndex(ctx, &mirrormodel.Mirror{
 			IndexFile: ts.URL,
 		})
 		if err != nil {
@@ -386,7 +386,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		}
 
 		ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-			now := int(time.Now().UTC().Second())
+			now := time.Now().UTC().Second()
 
 			for i := 1; i <= 50; i++ {
 				for j := 1; j <= 5; j++ {
@@ -396,7 +396,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 		}))
 		t.Cleanup(ts.Close)
 
-		results, err := s.downloadIndex(&mirrormodel.Mirror{
+		results, err := s.downloadIndex(ctx, &mirrormodel.Mirror{
 			IndexFile: ts.URL,
 		})
 		if err != nil {
@@ -430,7 +430,7 @@ func TestServer_DownloadIndex(t *testing.T) {
 			"https://example.com/path",
 			"https://example.com/path/",
 		} {
-			results, err := s.downloadIndex(&mirrormodel.Mirror{
+			results, err := s.downloadIndex(ctx, &mirrormodel.Mirror{
 				IndexFile:  ts.URL,
 				ExportRoot: root,
 			})
diff --git a/internal/project/trim_test.go b/internal/project/trim_test.go
index 79b4515..bb1c791 100644
--- a/internal/project/trim_test.go
+++ b/internal/project/trim_test.go
@@ -19,6 +19,8 @@ import (
 )
 
 func TestTrimSpaceAndNonPrintable_unicode(t *testing.T) {
+	t.Parallel()
+
 	extraChars := "state\uFEFF"
 	want := "state"
 	got := TrimSpaceAndNonPrintable(extraChars)
@@ -29,6 +31,8 @@ func TestTrimSpaceAndNonPrintable_unicode(t *testing.T) {
 }
 
 func TestTrimSpaceAndNonPrintable_space(t *testing.T) {
+	t.Parallel()
+
 	extraChars := " state  \r\t"
 	want := "state"
 	got := TrimSpaceAndNonPrintable(extraChars)
@@ -39,6 +43,8 @@ func TestTrimSpaceAndNonPrintable_space(t *testing.T) {
 }
 
 func TestTrimSpace_unicode(t *testing.T) {
+	t.Parallel()
+
 	extraChars := "state\uFEFF"
 	want := "state"
 	got := TrimSpace(extraChars)
@@ -49,6 +55,8 @@ func TestTrimSpace_unicode(t *testing.T) {
 }
 
 func TestTrimSpace_space(t *testing.T) {
+	t.Parallel()
+
 	extraChars := " state  \r\t"
 	want := "state"
 	got := TrimSpace(extraChars)
diff --git a/internal/publish/database/exposure_test.go b/internal/publish/database/exposure_test.go
index 8d1d574..be6ffcf 100644
--- a/internal/publish/database/exposure_test.go
+++ b/internal/publish/database/exposure_test.go
@@ -37,9 +37,7 @@ import (
 	"github.com/google/go-cmp/cmp/cmpopts"
 )
 
-var (
-	ignoreUnexportedExposure = cmpopts.IgnoreUnexported(model.Exposure{})
-)
+var ignoreUnexportedExposure = cmpopts.IgnoreUnexported(model.Exposure{})
 
 func TestReadExposures(t *testing.T) {
 	t.Parallel()
diff --git a/internal/publish/database/performance_test_utils.go b/internal/publish/database/performance_test_utils.go
index d70a7bf..5e53910 100644
--- a/internal/publish/database/performance_test_utils.go
+++ b/internal/publish/database/performance_test_utils.go
@@ -35,14 +35,17 @@ func executeBulkInsertExposure(ctx context.Context, tx pgx.Tx, expos []*model.Ex
 		if exp.FederationSyncID != 0 {
 			syncID = &exp.FederationSyncID
 		}
-		inputRows = append(inputRows, []interface{}{encodeExposureKey(exp.ExposureKey), exp.TransmissionRisk,
+		inputRows = append(inputRows, []interface{}{
+			encodeExposureKey(exp.ExposureKey), exp.TransmissionRisk,
 			exp.AppPackageName, exp.Regions, exp.Traveler, exp.IntervalNumber, exp.IntervalCount,
 			exp.CreatedAt, exp.LocalProvenance, syncID,
-			exp.HealthAuthorityID, exp.ReportType, exp.DaysSinceSymptomOnset})
+			exp.HealthAuthorityID, exp.ReportType, exp.DaysSinceSymptomOnset,
+		})
 	}
 
 	copyCount, err := tx.CopyFrom(ctx, pgx.Identifier{"public", "exposure"},
-		[]string{"exposure_key",
+		[]string{
+			"exposure_key",
 			"transmission_risk",
 			"app_package_name",
 			"regions",
@@ -54,9 +57,10 @@ func executeBulkInsertExposure(ctx context.Context, tx pgx.Tx, expos []*model.Ex
 			"sync_id",
 			"health_authority_id",
 			"report_type",
-			"days_since_symptom_onset"}, pgx.CopyFromRows(inputRows))
+			"days_since_symptom_onset",
+		}, pgx.CopyFromRows(inputRows))
 	if err != nil {
-		return 0, fmt.Errorf("unexpected error for Bulk Insert: %v", err)
+		return 0, fmt.Errorf("unexpected error for Bulk Insert: %w", err)
 	}
 	if int(copyCount) != len(inputRows) {
 		return 0, fmt.Errorf("expected Bulk Insert to return %d copied rows, but got %d", len(inputRows), copyCount)
diff --git a/internal/publish/database/performance_test_utils_test.go b/internal/publish/database/performance_test_utils_test.go
index 9445f2b..cc957a7 100644
--- a/internal/publish/database/performance_test_utils_test.go
+++ b/internal/publish/database/performance_test_utils_test.go
@@ -31,7 +31,8 @@ func TestBulkInsertExposures(t *testing.T) {
 		{
 			name:      "No Exposures",
 			exposures: []*model.Exposure{},
-			want:      0},
+			want:      0,
+		},
 		{
 			name: "Few Exposures",
 			exposures: []*model.Exposure{
@@ -51,7 +52,8 @@ func TestBulkInsertExposures(t *testing.T) {
 					Regions:        []string{"MX", "CA"},
 				},
 			},
-			want: 3},
+			want: 3,
+		},
 	}
 
 	ctx := project.TestContext(t)
diff --git a/internal/publish/model/exposure_model_test.go b/internal/publish/model/exposure_model_test.go
index 41cd1d3..761af1f 100644
--- a/internal/publish/model/exposure_model_test.go
+++ b/internal/publish/model/exposure_model_test.go
@@ -356,7 +356,8 @@ func TestPublishValidation(t *testing.T) {
 				maxIntervalStartAge: maxAge,
 				truncateWindow:      time.Hour,
 				maxSymptomOnsetDays: maxSymptomOnsetDays,
-				debugReleaseSameDay: c.sameDay})
+				debugReleaseSameDay: c.sameDay,
+			})
 			if err != nil {
 				t.Fatalf("unexpected error: %v", err)
 			}
@@ -435,8 +436,8 @@ func TestStillValidKey(t *testing.T) {
 	}
 
 	for _, tc := range cases {
-
 		tc := tc
+
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
 
@@ -846,7 +847,7 @@ func TestTransform(t *testing.T) {
 					},
 				},
 				HealthAuthorityID:    appPackage,
-				SymptomOnsetInterval: int32(intervalNumber + +verifyapi.MaxIntervalCount),
+				SymptomOnsetInterval: intervalNumber + +verifyapi.MaxIntervalCount,
 			},
 			Regions: wantRegions,
 			Claims: &verification.VerifiedClaims{
@@ -1373,7 +1374,9 @@ func TestExposureRevisionFields(t *testing.T) {
 	if e.HasBeenRevised() {
 		t.Error("reports revised before revisedAt is set")
 	}
-	e.SetRevisedAt(revTime)
+	if err := e.SetRevisedAt(revTime); err != nil {
+		t.Fatal(err)
+	}
 	e.SetRevisedReportType(revType)
 	e.SetRevisedDaysSinceSymptomOnset(5)
 	e.SetRevisedTransmissionRisk(2)
@@ -1886,7 +1889,7 @@ func TestExposureFromExportFile(t *testing.T) {
 	validTEK := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
 	invalidTEK := []byte{0, 1}
 
-	validInterval := int32(IntervalNumber(timeutils.UTCMidnight(time.Now()).Add(-24 * time.Hour)))
+	validInterval := IntervalNumber(timeutils.UTCMidnight(time.Now()).Add(-24 * time.Hour))
 
 	config := &ExportImportConfig{
 		DefaultReportType:         verifyapi.ReportTypeConfirmed,
diff --git a/internal/publish/platform_test.go b/internal/publish/platform_test.go
index fe87a5c..25e3f64 100644
--- a/internal/publish/platform_test.go
+++ b/internal/publish/platform_test.go
@@ -66,5 +66,4 @@ func TestPlatform(t *testing.T) {
 			}
 		})
 	}
-
 }
diff --git a/internal/publish/publish_test.go b/internal/publish/publish_test.go
index 69347a4..5488529 100644
--- a/internal/publish/publish_test.go
+++ b/internal/publish/publish_test.go
@@ -72,9 +72,7 @@ const (
 	useV1Alpha1
 )
 
-var (
-	versions = []version{useV1, useV1Alpha1}
-)
+var versions = []version{useV1, useV1Alpha1}
 
 type nameAssigner struct {
 	baseAPK  string
@@ -423,6 +421,7 @@ func TestPublishWithBypass(t *testing.T) {
 	}
 
 	for _, ver := range versions {
+		ver := ver
 		addVer := "v1_"
 		if ver == useV1Alpha1 {
 			addVer = "v1Alpha1_"
@@ -552,7 +551,7 @@ func TestPublishWithBypass(t *testing.T) {
 				if tc.ContentType != "" {
 					contentType = tc.ContentType
 				}
-				request, err := http.NewRequest("POST", "", strings.NewReader(string(jsonString)))
+				request, err := http.NewRequestWithContext(ctx, "POST", "", strings.NewReader(string(jsonString)))
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -721,7 +720,6 @@ func TestPublishWithBypass(t *testing.T) {
 								t.Errorf("mismatch (-want, +got):\n%s", diff)
 							}
 						}
-
 					} else {
 						if !strings.Contains(response.ErrorMessage, tc.Error) {
 							t.Errorf("missing error text '%v', got '%+v'", tc.Error, response)
@@ -1073,7 +1071,7 @@ func TestKeyRevision(t *testing.T) {
 					t.Fatal(err)
 				}
 
-				request, err := http.NewRequest("POST", "", strings.NewReader(string(jsonString)))
+				request, err := http.NewRequestWithContext(ctx, "POST", "", strings.NewReader(string(jsonString)))
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -1137,7 +1135,7 @@ func TestKeyRevision(t *testing.T) {
 					t.Fatal(err)
 				}
 
-				request, err := http.NewRequest("POST", "", strings.NewReader(string(jsonString)))
+				request, err := http.NewRequestWithContext(ctx, "POST", "", strings.NewReader(string(jsonString)))
 				if err != nil {
 					t.Fatal(err)
 				}
diff --git a/internal/publish/stats_test.go b/internal/publish/stats_test.go
index 18899ab..0413eb8 100644
--- a/internal/publish/stats_test.go
+++ b/internal/publish/stats_test.go
@@ -141,7 +141,7 @@ func TestRetrieveMetrics(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	httpRequest, err := http.NewRequest("POST", "", strings.NewReader(string(jsonString)))
+	httpRequest, err := http.NewRequestWithContext(ctx, "POST", "", strings.NewReader(string(jsonString)))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -291,7 +291,7 @@ func TestRetrieveMetrics_AuthErrors(t *testing.T) {
 			if err != nil {
 				t.Fatal(err)
 			}
-			httpRequest, err := http.NewRequest("POST", "", strings.NewReader(string(jsonString)))
+			httpRequest, err := http.NewRequestWithContext(ctx, "POST", "", strings.NewReader(string(jsonString)))
 			if err != nil {
 				t.Fatal(err)
 			}
diff --git a/internal/setup/setup_test.go b/internal/setup/setup_test.go
index bcb326b..85db9c5 100644
--- a/internal/setup/setup_test.go
+++ b/internal/setup/setup_test.go
@@ -39,12 +39,14 @@ func TestMain(m *testing.M) {
 	m.Run()
 }
 
-var _ setup.AuthorizedAppConfigProvider = (*testConfig)(nil)
-var _ setup.BlobstoreConfigProvider = (*testConfig)(nil)
-var _ setup.DatabaseConfigProvider = (*testConfig)(nil)
-var _ setup.KeyManagerConfigProvider = (*testConfig)(nil)
-var _ setup.SecretManagerConfigProvider = (*testConfig)(nil)
-var _ setup.ObservabilityExporterConfigProvider = (*testConfig)(nil)
+var (
+	_ setup.AuthorizedAppConfigProvider         = (*testConfig)(nil)
+	_ setup.BlobstoreConfigProvider             = (*testConfig)(nil)
+	_ setup.DatabaseConfigProvider              = (*testConfig)(nil)
+	_ setup.KeyManagerConfigProvider            = (*testConfig)(nil)
+	_ setup.SecretManagerConfigProvider         = (*testConfig)(nil)
+	_ setup.ObservabilityExporterConfigProvider = (*testConfig)(nil)
+)
 
 type testConfig struct {
 	Database *database.Config
diff --git a/internal/storage/google_cloud_storage_test.go b/internal/storage/google_cloud_storage_test.go
index 8ffc736..ee8588c 100644
--- a/internal/storage/google_cloud_storage_test.go
+++ b/internal/storage/google_cloud_storage_test.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 	"crypto/rand"
 	"crypto/sha256"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -102,7 +103,7 @@ func testGoogleCloudStorageObject(tb testing.TB, r io.Reader) string {
 
 	// Schedule cleanup.
 	tb.Cleanup(func() {
-		if err := client.Bucket(bucket).Object(name).Delete(ctx); err != nil && err != storage.ErrObjectNotExist {
+		if err := client.Bucket(bucket).Object(name).Delete(ctx); err != nil && !errors.Is(err, storage.ErrObjectNotExist) {
 			tb.Fatalf("failed cleaning up %s: %v", name, err)
 		}
 	})
@@ -227,7 +228,7 @@ func TestGoogleCloudStorage_DeleteObject(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			if _, err := client.Bucket(tc.bucket).Object(tc.object).Attrs(ctx); err != storage.ErrObjectNotExist {
+			if _, err := client.Bucket(tc.bucket).Object(tc.object).Attrs(ctx); !errors.Is(err, storage.ErrObjectNotExist) {
 				t.Errorf("expected object %v to be deleted", tc.object)
 			}
 		})
diff --git a/internal/verification/phaverify_test.go b/internal/verification/phaverify_test.go
index e32249f..548dbab 100644
--- a/internal/verification/phaverify_test.go
+++ b/internal/verification/phaverify_test.go
@@ -97,6 +97,8 @@ func TestVerifyCertificate(t *testing.T) {
 	for iteration := 0; iteration < 2; iteration++ {
 		for version := 0; version <= 1; version++ {
 			for _, tc := range cases {
+				iteration := iteration
+				version := version
 				tc := tc
 
 				vname := "v1alpha1"
diff --git a/pkg/api/v1/stats_types_test.go b/pkg/api/v1/stats_types_test.go
index 1454746..f73566b 100644
--- a/pkg/api/v1/stats_types_test.go
+++ b/pkg/api/v1/stats_types_test.go
@@ -22,6 +22,8 @@ import (
 )
 
 func TestTotal(t *testing.T) {
+	t.Parallel()
+
 	p := &PublishRequests{
 		UnknownPlatform: 6,
 		Android:         22,
diff --git a/pkg/api/v1alpha1/verification_types_test.go b/pkg/api/v1alpha1/verification_types_test.go
index a7f0117..669c584 100644
--- a/pkg/api/v1alpha1/verification_types_test.go
+++ b/pkg/api/v1alpha1/verification_types_test.go
@@ -22,6 +22,8 @@ import (
 )
 
 func TestNewVerificationClaims(t *testing.T) {
+	t.Parallel()
+
 	got := NewVerificationClaims()
 	want := &VerificationClaims{
 		TransmissionRisks: []TransmissionRiskOverride{},
diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go
index 75cb66a..f9f8344 100644
--- a/pkg/cache/cache_test.go
+++ b/pkg/cache/cache_test.go
@@ -169,7 +169,7 @@ func TestConcurrentReaders(t *testing.T) {
 		go func() {
 			gotCache, err := cache.WriteThruLookup("foo", lookerUpper)
 			if err != nil {
-				done <- fmt.Errorf("routine: %v got unexpected error: %v", ver, err)
+				done <- fmt.Errorf("routine: %v got unexpected error: %w", ver, err)
 				return
 			}
 			got, ok := gotCache.(*order)
diff --git a/pkg/keys/ecdsa_pem_test.go b/pkg/keys/ecdsa_pem_test.go
index e31f05f..9b82ad3 100644
--- a/pkg/keys/ecdsa_pem_test.go
+++ b/pkg/keys/ecdsa_pem_test.go
@@ -35,7 +35,7 @@ func TestParseECDSAPublicKey_DecodeError(t *testing.T) {
 func TestParseECDSAPublicKey_WrongKeyType(t *testing.T) {
 	t.Parallel()
 
-	pk, err := rsa.GenerateKey(rand.Reader, 1024)
+	pk, err := rsa.GenerateKey(rand.Reader, 4096)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/pkg/keys/filesystem_test.go b/pkg/keys/filesystem_test.go
index 651333d..458274b 100644
--- a/pkg/keys/filesystem_test.go
+++ b/pkg/keys/filesystem_test.go
@@ -127,7 +127,7 @@ func TestFilesystem_NewSigner(t *testing.T) {
 			keyID: "banana",
 			setup: func(dir string) error {
 				pth := filepath.Join(dir, "banana")
-				return ioutil.WriteFile(pth, []byte("dafd"), 0600)
+				return ioutil.WriteFile(pth, []byte("dafd"), 0o600)
 			},
 			err: "failed to parse signing key",
 		},
@@ -145,7 +145,7 @@ func TestFilesystem_NewSigner(t *testing.T) {
 				}
 
 				pth := filepath.Join(dir, "apple")
-				return ioutil.WriteFile(pth, b, 0600)
+				return ioutil.WriteFile(pth, b, 0o600)
 			},
 		},
 	}
@@ -211,7 +211,7 @@ func TestFilesystem_EncryptDecrypt(t *testing.T) {
 			keyID: "banana",
 			setup: func(fs *Filesystem) error {
 				dir := filepath.Join(fs.root, "banana")
-				return os.MkdirAll(dir, 0700)
+				return os.MkdirAll(dir, 0o700)
 			},
 			err: "no key versions",
 		},
diff --git a/pkg/logging/logger_test.go b/pkg/logging/logger_test.go
index 6083003..3c72629 100644
--- a/pkg/logging/logger_test.go
+++ b/pkg/logging/logger_test.go
@@ -85,7 +85,11 @@ func TestLevelToZapLevls(t *testing.T) {
 	}
 
 	for _, tc := range cases {
+		tc := tc
+
 		t.Run(tc.input, func(t *testing.T) {
+			t.Parallel()
+
 			got := levelToZapLevel(tc.input)
 			if diff := cmp.Diff(tc.want, got); diff != "" {
 				t.Fatalf("mismatch (-want, +got):\n%s", diff)
diff --git a/pkg/secrets/json_expander_test.go b/pkg/secrets/json_expander_test.go
index 450bb78..897199a 100644
--- a/pkg/secrets/json_expander_test.go
+++ b/pkg/secrets/json_expander_test.go
@@ -25,15 +25,7 @@ func TestJSONExpander_GetSecretValue(t *testing.T) {
 
 	ctx := project.TestContext(t)
 
-	testSM := &testSecretManager{}
-
-	sm, err := WrapJSONExpander(ctx, testSM)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	testSM.value = "test"
-	testCases := []struct {
+	cases := []struct {
 		testName      string
 		secretName    string
 		secretValue   string
@@ -125,22 +117,33 @@ func TestJSONExpander_GetSecretValue(t *testing.T) {
 			err:           true,
 		},
 	}
-	for _, tt := range testCases {
-		t.Run(tt.testName, func(t *testing.T) {
-			testSM.value = tt.secretValue
-			actualValue, err := sm.GetSecretValue(ctx, tt.secretName)
+	for _, tc := range cases {
+		tc := tc
+
+		t.Run(tc.testName, func(t *testing.T) {
+			t.Parallel()
+
+			testSM := &testSecretManager{}
+			testSM.value = "test"
+
+			sm, err := WrapJSONExpander(ctx, testSM)
 			if err != nil {
-				if !tt.err {
+				t.Fatal(err)
+			}
+
+			testSM.value = tc.secretValue
+			actualValue, err := sm.GetSecretValue(ctx, tc.secretName)
+			if err != nil {
+				if !tc.err {
 					t.Errorf("got error: %w, did not expect one", err)
 				}
 			}
-			if tt.err && err == nil {
+			if tc.err && err == nil {
 				t.Errorf("expected to error, but did not, actualValue: %s", actualValue)
 			}
-			if tt.expectedValue != actualValue {
-				t.Errorf("expected %s, got %s", tt.expectedValue, actualValue)
+			if tc.expectedValue != actualValue {
+				t.Errorf("expected %s, got %s", tc.expectedValue, actualValue)
 			}
 		})
 	}
-
 }
diff --git a/testing/enclient/enclient.go b/testing/enclient/enclient.go
deleted file mode 100644
index b55d4c7..0000000
--- a/testing/enclient/enclient.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2020 Google 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.
-
-// Package enclient is a client for making requests against the exposure
-// notification server.
-package enclient
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"net/http"
-	"time"
-
-	verifyapi "github.com/google/exposure-notifications-server/pkg/api/v1alpha1"
-)
-
-const (
-	// httpTimeout is the maximum amount of time to wait for a response.
-	httpTimeout = 30 * time.Second
-)
-
-type Interval int32
-
-// PostRequest requests to the specified url. This methods attempts to serialize
-// data argument as a json.
-func PostRequest(url string, data interface{}) (*http.Response, error) {
-	request := bytes.NewBuffer(JSONRequest(data))
-	r, err := http.NewRequest("POST", url, request)
-	if err != nil {
-		return nil, err
-	}
-	r.Header.Set("Content-Type", "application/json")
-	client := &http.Client{Timeout: httpTimeout}
-	resp, err := client.Do(r)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode != http.StatusOK {
-		// Return error upstream.
-		body, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			return nil, fmt.Errorf("failed to copy error body (%d): %w", resp.StatusCode, err)
-		}
-		return resp, fmt.Errorf("post request failed with status: %v\n%v", resp.StatusCode, body)
-	}
-
-	return resp, nil
-}
-
-// JSONRequest serializes the given argument to json.
-func JSONRequest(data interface{}) []byte {
-	jsonData, err := json.Marshal(data)
-	if err != nil {
-		log.Fatalf("unable to marshal json payload")
-	}
-	return jsonData
-}
-
-// NowInterval returns the Interval for the current moment of tme.
-func NowInterval() Interval {
-	return NewInterval(time.Now().Unix())
-}
-
-// NewInterval creates a new interval for the UNIX epoch given.
-func NewInterval(time int64) Interval {
-	return Interval(int32(time / 600))
-}
-
-// ExposureKey creates an exposure key.
-func ExposureKey(key string, intervalNumber Interval, intervalCount int32, transmissionRisk int) verifyapi.ExposureKey {
-	return verifyapi.ExposureKey{
-		Key:              key,
-		IntervalNumber:   int32(intervalNumber),
-		IntervalCount:    intervalCount,
-		TransmissionRisk: transmissionRisk,
-	}
-}