Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ scripts/*
*.log
bin
coverage
playwright-report
test-results
**/playwright-report
**/test-results
web/node_modules
web/dist
multispeed
Expand Down
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ APP_ALLOWED_CUSTOM_SERVER_URLS=
# upload one separately obtained Linux amd64 Ookla executable into the writable
# /data mount. Never expose this unauthenticated endpoint to an untrusted network.
APP_ALLOW_OOKLA_BINARY_UPLOAD=false
# Optional Prometheus/OpenMetrics endpoint at /metrics. It follows the same
# trusted-host policy and has no separate authentication.
APP_METRICS_ENABLED=false
# compose.yaml deliberately fixes APP_DATA_DIR=/data so the database and
# managed provider files always use the persistent ./data mount.
APP_LOG_LEVEL=INFO
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ jobs:
- name: Install locked dependencies
run: npm ci --no-audit --no-fund

- name: Verify generated OpenAPI types
working-directory: .
shell: bash
run: |
npm --prefix web run generate:api-types
git diff --exit-code -- web/src/lib/openapi
test -z "$(git status --porcelain --untracked-files=all -- web/src/lib/openapi)"

- name: Lint
run: npm run lint

Expand All @@ -104,6 +112,15 @@ jobs:
- name: Production build
run: npm run build

- name: Upload Dependabot frontend candidate
if: github.event_name == 'pull_request' && github.actor == 'dependabot[bot]'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dependabot-frontend-dist-${{ github.event.pull_request.number }}
path: internal/frontend/dist
if-no-files-found: error
retention-days: 1

- name: Verify committed embedded frontend is current
working-directory: .
shell: bash
Expand Down
108 changes: 108 additions & 0 deletions .github/workflows/dependabot-frontend-assets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Refresh Dependabot frontend assets

on:
workflow_run:
workflows:
- CI
types:
- completed

permissions:
actions: read
contents: write
pull-requests: read

concurrency:
group: dependabot-frontend-assets-${{ github.event.workflow_run.id }}
cancel-in-progress: false

jobs:
refresh:
if: >-
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.actor.login == 'dependabot[bot]'
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Validate originating pull request
id: pull-request
uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0
with:
script: |
const run = context.payload.workflow_run
const reference = run.pull_requests?.[0]
if (!reference?.number) {
core.setFailed('The CI run is not associated with a pull request.')
return
}
const { data: pull } = await github.rest.pulls.get({
...context.repo,
pull_number: reference.number,
})
const valid = pull.state === 'open' &&
pull.base.ref === 'main' &&
pull.head.repo?.full_name === `${context.repo.owner}/${context.repo.repo}` &&
pull.user?.login === 'dependabot[bot]' &&
pull.head.ref.startsWith('dependabot/npm_and_yarn/web/') &&
pull.head.sha === run.head_sha
if (!valid) {
core.setFailed('The workflow run is not an eligible same-repository Dependabot npm pull request.')
return
}
const files = await github.paginate(github.rest.pulls.listFiles, {
...context.repo,
pull_number: pull.number,
per_page: 100,
})
const allowed = files.every(({ filename }) =>
filename === 'web/package.json' ||
filename === 'web/package-lock.json' ||
filename.startsWith('internal/frontend/dist/'))
if (!allowed) {
core.setFailed('The Dependabot pull request changes files outside the approved frontend dependency and generated-asset paths.')
return
}
core.setOutput('number', String(pull.number))
core.setOutput('head-ref', pull.head.ref)
core.setOutput('head-sha', pull.head.sha)

- name: Check out the validated Dependabot commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ steps.pull-request.outputs.head-ref }}
fetch-depth: 1

- name: Download unprivileged frontend build
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: dependabot-frontend-dist-${{ steps.pull-request.outputs.number }}
path: .dependabot-frontend-dist
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}

- name: Replace only embedded frontend assets
shell: bash
env:
HEAD_REF: ${{ steps.pull-request.outputs.head-ref }}
HEAD_SHA: ${{ steps.pull-request.outputs.head-sha }}
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "${HEAD_SHA}"
test -f .dependabot-frontend-dist/index.html
test -z "$(find .dependabot-frontend-dist -type l -print -quit)"
rsync --archive --delete .dependabot-frontend-dist/ internal/frontend/dist/
mapfile -t changed < <(
{ git diff --name-only; git ls-files --others --exclude-standard; } | sort -u
)
test "${#changed[@]}" -gt 0
for path in "${changed[@]}"; do
case "${path}" in
internal/frontend/dist/*) ;;
*) printf 'Refusing unexpected changed path: %s\n' "${path}" >&2; exit 1 ;;
esac
done
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add -- internal/frontend/dist
git commit -m 'chore(web): refresh embedded frontend assets'
git push origin "HEAD:${HEAD_REF}"
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to MultiSpeed are documented here. The project follows [Sema

## [Unreleased]

## [1.1.0] - 2026-08-17

### Added

- Add opt-in Prometheus metrics for HTTP traffic and persisted application state at `/metrics`.
- Generate frontend API models from OpenAPI and enforce generated-contract drift in CI.
- Run automated WCAG A/AA accessibility scans across the primary operator pages.

### Changed

- Reject malformed boolean environment values instead of silently treating them as false.
- Automatically refresh committed frontend assets for eligible same-repository Dependabot npm pull requests through a privilege-separated workflow.

### Security

- Upgrade the build toolchain to Go 1.26.6 and the patched LibreSpeed overlay to `golang.org/x/net` v0.56.0.
Expand Down Expand Up @@ -87,7 +100,8 @@ All notable changes to MultiSpeed are documented here. The project follows [Sema
- Non-root read-only container with all capabilities dropped and `no-new-privileges`.
- Ookla Speedtest CLI is never downloaded or redistributed by the project image; in-app acceptance remains separate from installation and licensing permission.

[Unreleased]: https://github.com/dude2k/MultiSpeed/compare/v1.0.4...HEAD
[Unreleased]: https://github.com/dude2k/MultiSpeed/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/dude2k/MultiSpeed/compare/v1.0.4...v1.1.0
[1.0.4]: https://github.com/dude2k/MultiSpeed/compare/v1.0.3...v1.0.4
[1.0.3]: https://github.com/dude2k/MultiSpeed/compare/v1.0.2...v1.0.3
[1.0.2]: https://github.com/dude2k/MultiSpeed/compare/v1.0.1...v1.0.2
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ ENV APP_LISTEN_ADDR=127.0.0.1:8787 \
LIBRESPEED_BINARY=/usr/local/bin/librespeed-cli \
OOKLA_BINARY=/data/providers/ookla/speedtest \
APP_ALLOW_OOKLA_BINARY_UPLOAD=false \
APP_METRICS_ENABLED=false \
ACCEPT_OOKLA_EULA=false

USER 10001:10001
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ Process configuration is intentionally small; persisted runtime settings are man
| `APP_TRUSTED_HOSTS` | empty | empty | Comma-separated exact proxy/LAN DNS names or IPs; wildcard listeners already accept unicast IP literals but require explicit DNS names to prevent DNS rebinding |
| `APP_ALLOWED_CUSTOM_SERVER_URLS` | empty | empty | Comma-separated exact LibreSpeed custom backend base URLs; empty disables custom URLs, and plain HTTP additionally requires the task's explicit insecure opt-in |
| `APP_ALLOW_OOKLA_BINARY_UPLOAD` | `false` | `false` | Enables bounded upload and execution validation of one operator-supplied Linux amd64 Ookla executable; no authentication, trusted private networks only |
| `APP_METRICS_ENABLED` | `false` | `false` | Enables the Prometheus/OpenMetrics endpoint at `/metrics`; protected by the listener's trusted-host policy but not by separate authentication |
| `APP_DATA_DIR` | `/data` | `/data` (fixed by supplied Compose) | Database and managed-provider directory; keep the `/data` mount writable |
| `APP_LOG_LEVEL` | `INFO` | `INFO` | `DEBUG`, `INFO`, `WARN`, or `ERROR` |
| `APP_SHUTDOWN_TIMEOUT` | `20s` | `20s` | Graceful shutdown deadline |
Expand All @@ -186,7 +187,7 @@ Process configuration is intentionally small; persisted runtime settings are man
| `OOKLA_BINARY` | `/data/providers/ookla/speedtest` | `/data/providers/ookla/speedtest` | Managed or externally supplied Ookla executable path |
| `ACCEPT_OOKLA_EULA` | `false` | `false` | Legacy-named headless override authorizing non-interactive `--accept-license`/`--accept-gdpr`; technical gate only, never a license grant |

No environment-variable values are exposed by the system API.
Boolean variables reject malformed values instead of silently falling back. No environment-variable values are exposed by the system API.

## Development

Expand Down
3 changes: 2 additions & 1 deletion cmd/multispeed/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ func run() error {
api.BuildInfo{Version: version, GitCommit: gitCommit, BuildTime: buildTime},
api.HTTPPolicy{ListenAddress: configuration.ListenAddress, TrustedHosts: configuration.TrustedHosts,
OoklaEULAEnvironmentAccepted: configuration.AcceptOoklaEULA, DataDirectory: configuration.DataDirectory,
OoklaBinaryPath: configuration.OoklaBinary, AllowOoklaBinaryUpload: configuration.AllowOoklaBinaryUpload})
OoklaBinaryPath: configuration.OoklaBinary, AllowOoklaBinaryUpload: configuration.AllowOoklaBinaryUpload,
MetricsEnabled: configuration.MetricsEnabled})
httpServer := &http.Server{Addr: configuration.ListenAddress, Handler: apiServer.Handler(), ReadHeaderTimeout: 10 * time.Second, ReadTimeout: 30 * time.Second, IdleTimeout: 2 * time.Minute, MaxHeaderBytes: 32 << 10}
serveErrors := make(chan error, 1)
go func() {
Expand Down
1 change: 1 addition & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ services:
APP_TRUSTED_HOSTS: ${APP_TRUSTED_HOSTS:-}
APP_ALLOWED_CUSTOM_SERVER_URLS: ${APP_ALLOWED_CUSTOM_SERVER_URLS:-}
APP_ALLOW_OOKLA_BINARY_UPLOAD: ${APP_ALLOW_OOKLA_BINARY_UPLOAD:-false}
APP_METRICS_ENABLED: ${APP_METRICS_ENABLED:-false}
APP_DATA_DIR: /data
APP_LOG_LEVEL: ${APP_LOG_LEVEL:-INFO}
APP_SHUTDOWN_TIMEOUT: ${APP_SHUTDOWN_TIMEOUT:-20s}
Expand Down
4 changes: 4 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ curl --fail http://127.0.0.1:8787/api/v1/readyz

`healthz` indicates that the process is alive. `readyz` additionally reflects startup dependencies such as migrations/database access. The Docker healthcheck targets the configured local listener.

## Metrics

Set `APP_METRICS_ENABLED=true` to expose Prometheus/OpenMetrics data at `/metrics`. The endpoint includes bounded route-template HTTP labels, request duration and in-flight counts, Go/process metrics, and current task, result, and active-run gauges. It follows the same trusted-host checks as the UI, but MultiSpeed does not add separate metrics authentication; restrict scraping to a trusted network or an authenticating reverse proxy. Leave it disabled when it is not needed.

## Reverse proxy

MultiSpeed does not implement authentication. For remote access, use a separate operator-managed reverse proxy with TLS and authentication, bind MultiSpeed to loopback, and preserve streaming for `/api/v1/events`. Add the public DNS name to `APP_TRUSTED_HOSTS` and forward that hostname consistently so same-origin mutation validation remains effective. The backend rejects an explicit Host port different from `APP_LISTEN_ADDR`; configure the proxy's upstream `Host` header without the external port (for example, an Nginx `$host`) or with the backend listen port. Do not add permissive CORS headers.
Expand Down
1 change: 1 addition & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ npm ci
npm run lint
npm run typecheck
npm run test
npm run generate:api-types
npm run build
```

Expand Down
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ go 1.26.0
require (
github.com/go-chi/chi/v5 v5.3.1
github.com/google/uuid v1.6.0
github.com/prometheus/client_golang v1.24.0
github.com/robfig/cron/v3 v3.0.1
modernc.org/sqlite v1.56.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.70.0 // indirect
github.com/prometheus/procfs v0.21.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/sys v0.47.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
modernc.org/libc v1.74.4 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
Expand Down
34 changes: 34 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 h1:LMLX+LgTNWpfvCBdFebv6EsYotImrt/Ppc5cXIriCSo=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3/go.mod h1:jl5iWTm0/hd5PjEYEOuwAJ57L/CibdZfrqZ5XA5GrCk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ=
github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.24.0 h1:5XStIklKuAtJSNpdD3s8XJj/Yv78IQmE1kbNk87JrAI=
github.com/prometheus/client_golang v1.24.0/go.mod h1:QcsNdotprC2nS4BTM2ucbcqxd2CeXTEa9jW7zHO9iDE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.70.0 h1:bcpru3tWPVnxGnETLgOV5jbp/JRXgYEyv65CuBLAMMI=
github.com/prometheus/common v0.70.0/go.mod h1:S/SFasQmgGiYH6C81LKCtYa8QACgthGg5zxL2udV7SY=
github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI=
github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
Expand All @@ -24,6 +54,10 @@ golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.29.1 h1:MKgdCV3WykTSPqpVrnxdEDS0HEd2FHpKZDzxzU5LyeI=
modernc.org/cc/v4 v4.29.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU=
Expand Down
1 change: 1 addition & 0 deletions internal/api/host_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type HTTPPolicy struct {
DataDirectory string
OoklaBinaryPath string
AllowOoklaBinaryUpload bool
MetricsEnabled bool
}

type hostPolicy struct {
Expand Down
Loading
Loading