diff --git a/CHANGELOG.md b/CHANGELOG.md
index 73f341f..4d1dcd2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,20 @@ The format is **not** based on [Keep a Changelog][kec], since the project **does
[kec]: https://keepachangelog.com/en/1.0.0/
[sem]: https://semver.org/spec/v2.0.0.html
+## AGDNS-3491 / Build 1109
+
+- The new environment variable `CATEGORY_FILTER_ENABLED` has been added.
+
+- The environment variable `CATEGORY_FILTER_INDEX_URL` is no longer required if `CATEGORY_FILTER_ENABLED` is set to `0`.
+
+## AGDNS-3435 / Build 1102
+
+- The new required environment variable `CATEGORY_FILTER_INDEX_URL` has been added.
+
+## AGDNS-3410 / Build 1095
+
+- The environment variable `PROFILES_CACHE_INTERVAL` has been added.
+
## AGDNS-3287 / Build 1081
- Profiles’ file cache version has been incremented to support custom block-page data.
diff --git a/Makefile b/Makefile
index 1dc57a0..879b10a 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ BRANCH = $${BRANCH:-$$(git rev-parse --abbrev-ref HEAD)}
GOAMD64 = v1
GOPROXY = https://proxy.golang.org|direct
GOTELEMETRY = off
-GOTOOLCHAIN = go1.25.3
+GOTOOLCHAIN = go1.25.5
RACE = 0
REVISION = $${REVISION:-$$(git rev-parse --short HEAD)}
VERSION = 0
diff --git a/doc/development.md b/doc/development.md
index db14a4b..fa6217c 100644
--- a/doc/development.md
+++ b/doc/development.md
@@ -191,11 +191,16 @@ If you're using an OS different from Linux, you also need to make these changes:
- Remove the `interface_listeners` section.
- Remove `bind_interfaces` from the `default_dns` server configuration and replace it with `bind_addresses`.
+
+
```sh
env \
ADULT_BLOCKING_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/adult_blocking.txt' \
BILLSTAT_URL='grpc://localhost:6062' \
BLOCKED_SERVICE_INDEX_URL='https://adguardteam.github.io/HostlistsRegistry/assets/services.json' \
+ CATEGORY_FILTER_INDEX_URL='https://filters.adtidy.org/dns/category/filters.json' \
CONSUL_ALLOWLIST_URL='https://raw.githubusercontent.com/ameshkov/stuff/master/DNS/consul_allowlist.json' \
CONFIG_PATH='./config.yaml' \
FILTER_INDEX_URL='https://adguardteam.github.io/HostlistsRegistry/assets/filters.json' \
diff --git a/doc/environment.md b/doc/environment.md
index 51e67ae..0284d03 100644
--- a/doc/environment.md
+++ b/doc/environment.md
@@ -12,6 +12,8 @@ AdGuard DNS uses [environment variables][wiki-env] to store some of the more sen
- [`BILLSTAT_URL`](#BILLSTAT_URL)
- [`BLOCKED_SERVICE_ENABLED`](#BLOCKED_SERVICE_ENABLED)
- [`BLOCKED_SERVICE_INDEX_URL`](#BLOCKED_SERVICE_INDEX_URL)
+- [`CATEGORY_FILTER_ENABLED`](#CATEGORY_FILTER_ENABLED)
+- [`CATEGORY_FILTER_INDEX_URL`](#CATEGORY_FILTER_INDEX_URL)
- [`CONFIG_PATH`](#CONFIG_PATH)
- [`CONSUL_ALLOWLIST_URL`](#CONSUL_ALLOWLIST_URL)
- [`CONSUL_DNSCHECK_KV_URL`](#CONSUL_DNSCHECK_KV_URL)
@@ -144,6 +146,20 @@ The HTTP(S) URL of the blocked service index file server. See the [external HTTP
[ext-blocked]: externalhttp.md#filters-blocked-services
+## `CATEGORY_FILTER_ENABLED`
+
+Then set to `1`, enable the category filter. When set to `0`, disable it.
+
+**Default:** `0`.
+
+## `CATEGORY_FILTER_INDEX_URL`
+
+The HTTP(S) URL or a hostless file URI (e.g. `file:///tmp/category_filters.json`) of the category filtering rule index file server. See the [external HTTP API requirements section][ext-category-lists] on the expected format of the response.
+
+**Default:** No default value, the variable is required if `CATEGORY_FILTER_ENABLED` is set to `1`.
+
+[ext-category-lists]: externalhttp.md#category-filters-lists
+
## `CONFIG_PATH`
The path to the configuration file.
@@ -374,6 +390,14 @@ The API key to use when authenticating queries to the profiles API, if any. The
**Default:** **Unset.**
+## `PROFILES_CACHE_INTERVAL`
+
+The interval between profiles cache file updates, as a human-readable duration. Setting this variable to a value less than [refresh interval][conf-backend-refresh_interval] makes no sense, as the configured variable is checked only on the refresh intervals.
+
+**Default:** No default value, the variable is **required** if `PROFILES_CACHE_PATH` is set to a non-`none` value.
+
+[conf-backend-refresh_interval]: configuration.md#backend-refresh_interval
+
## `PROFILES_CACHE_PATH`
The path to the profile cache file:
diff --git a/doc/externalhttp.md b/doc/externalhttp.md
index 900cfb4..a9f3d76 100644
--- a/doc/externalhttp.md
+++ b/doc/externalhttp.md
@@ -16,6 +16,7 @@ AdGuard DNS uses information from external HTTP APIs for filtering and other pie
- [Consul key-value storage](#consul)
- [Filtering](#filters)
- [Blocked services](#filters-blocked-services)
+ - [Category filters rule lists](#category-filters-lists)
- [Filtering rule lists](#filters-lists)
- [Safe search](#filters-safe-search)
- [Proxied linked IP and dynamic DNS (DDNS) Endpoints](#backend-linkip)
@@ -99,6 +100,22 @@ This endpoint, defined by [`BLOCKED_SERVICE_INDEX_URL`][env-services], must resp
All properties must be filled with valid IDs and rules. Additional fields in objects are ignored.
+### Category filters rule lists
+
+This endpoint, defined by [`CATEGORY_FILTER_INDEX_URL`][env-category-filters], must respond with a `200 OK` response code and a JSON document in the following format:
+
+```json
+{
+ "filters": {
+ "my_category_name": {
+ "downloadUrl": "https://cdn.example.com/assets/category/my_category_name.txt"
+ }
+ }
+}
+```
+
+All properties must be filled with valid IDs and URLs. Additional fields in objects are ignored.
+
### Filtering rule lists
This endpoint, defined by [`FILTER_INDEX_URL`][env-filters], must respond with a `200 OK` response code and a JSON document in the following format:
@@ -128,10 +145,11 @@ These endpoints, defined by [`GENERAL_SAFE_SEARCH_URL`][env-general] and [`YOUTU
|youtubei.googleapis.com^$dnsrewrite=NOERROR;CNAME;restrictmoderate.youtube.com
```
-[env-filters]: environment.md#FILTER_INDEX_URL
-[env-general]: environment.md#GENERAL_SAFE_SEARCH_URL
-[env-services]: environment.md#BLOCKED_SERVICE_INDEX_URL
-[env-youtube]: environment.md#YOUTUBE_SAFE_SEARCH_URL
+[env-category-filters]: environment.md#CATEGORY_FILTER_INDEX_URL
+[env-filters]: environment.md#FILTER_INDEX_URL
+[env-general]: environment.md#GENERAL_SAFE_SEARCH_URL
+[env-services]: environment.md#BLOCKED_SERVICE_INDEX_URL
+[env-youtube]: environment.md#YOUTUBE_SAFE_SEARCH_URL