1
1
mirror of https://github.com/privacyguides/privacyguides.org.git synced 2025-12-14 16:22:14 +00:00

Compare commits

..

2 Commits

256 changed files with 2953 additions and 5221 deletions

View File

@@ -1,5 +1,10 @@
# SPDX-FileCopyrightText: 2025 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
:1337 {
reverse_proxy /articles/* http://127.0.0.1:8001
reverse_proxy /videos/* http://127.0.0.1:8002
reverse_proxy /en/* http://127.0.0.1:8000
redir / /en/
}

View File

@@ -1,7 +1,11 @@
// SPDX-FileCopyrightText: 2025 Jonah Aragon <jonah@privacyguides.org>
//
// SPDX-License-Identifier: MIT
// For format details, see https://aka.ms/devcontainer.json.
{
"name": "Privacy Guides",
"image": "ghcr.io/privacyguides/privacyguides.org:sha-5648a3f",
"image": "ghcr.io/privacyguides/privacyguides.org:sha-55c050b",
// "build": {
// "dockerfile": "../Dockerfile",
// "context": ".."
@@ -19,6 +23,10 @@
"8001": {
"label": "Articles",
"onAutoForward": "silent"
},
"8002": {
"label": "Videos",
"onAutoForward": "silent"
}
},
"otherPortsAttributes": {
@@ -48,10 +56,24 @@
"group": "Live server"
}
},
{
"label": "Videos",
"type": "shell",
"command": "mkdocs serve --config-file=mkdocs.videos.yml --dev-addr=localhost:8002",
"group": "test",
"runOptions": {
"runOn": "folderOpen"
},
"presentation": {
"reveal": "always",
"panel": "dedicated",
"group": "Live server"
}
},
{
"label": "Main",
"type": "shell",
"command": "./run.sh --cmd=mkdocs --insiders",
"command": "./run.sh --cmd=mkdocs --insiders --production",
"group": "test",
"runOptions": {
"runOn": "folderOpen"

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
# EditorConfig is awesome: https://EditorConfig.org

22
.gitattributes vendored
View File

@@ -1,22 +1,6 @@
# Copyright (c) 2020-2023 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2020 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
# Auto detect text files and perform LF normalization
* text=auto

4
.github/CODEOWNERS vendored
View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2019 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
# Org
/docs/about/ @jonaharagon

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2023 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2023 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC0-1.0
name: "Content Correction"
description: Report any inaccurate, incorrect, or outdated information on the website.

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2023 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2023 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC0-1.0
name: "Website Issue"
description: Report a bug with the website.

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2020-2023 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2020 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC0-1.0
blank_issues_enabled: false
contact_links:

View File

@@ -0,0 +1,4 @@
SPDX-FileCopyrightText: 2017 Contributors to Privacy Guides <https://www.privacyguides.org>
SPDX-FileCopyrightText: 2020 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: MIT OR CC0-1.0

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🛠️ Build Blog
on:
@@ -90,7 +94,7 @@ jobs:
echo "MAIN_SITE_ABOUT_URL=https://www.privacyguides.org/en/about/"
echo "MAIN_SITE_RECOMMENDATIONS_URL=https://www.privacyguides.org/en/tools/"
echo "MAIN_SITE_KNOWLEDGE_BASE_URL=https://www.privacyguides.org/en/basics/why-privacy-matters/"
echo "ARTICLES_SITE_BASE_URL=https://www.privacyguides.org/posts/tag/articles/"
echo "ARTICLES_SITE_BASE_URL=https://www.privacyguides.org/articles/"
echo "VIDEOS_SITE_BASE_URL=https://www.privacyguides.org/videos/"
} >> "$GITHUB_ENV"

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: ☁️ Build Container
# Configures this workflow to run every release.

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🛠️ Build PR Preview
on:
@@ -72,13 +76,15 @@ jobs:
continue-on-error: false
privileged: ${{ fromJSON(needs.metadata.outputs.privileged) }}
strict: true
secrets:
RO_DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}
build_i18n:
if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:build i18n') }}
needs: [submodule, metadata]
strategy:
matrix:
lang: [es, fr, he, it, nl, ru, zh-Hant, zh-TW]
lang: [es, fr, he, it, nl, ru, zh-Hant]
fail-fast: false
uses: ./.github/workflows/build.yml
with:
@@ -99,21 +105,24 @@ jobs:
continue-on-error: true
privileged: ${{ fromJSON(needs.metadata.outputs.privileged) }}
build_zimfile:
if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:build zimfile') }}
build_videos:
if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:build videos') }}
needs: [submodule, metadata]
uses: ./.github/workflows/build-zimfile.yml
uses: ./.github/workflows/build-videos.yml
with:
ref: ${{github.event.pull_request.head.ref}}
repo: ${{github.event.pull_request.head.repo.full_name}}
continue-on-error: true
privileged: ${{ fromJSON(needs.metadata.outputs.privileged) }}
combine_build:
needs: [build_english, build_i18n, build_blog]
needs: [build_english, build_i18n, build_blog, build_videos]
if: |
(always() && !cancelled() && !failure()) &&
needs.build_english.result == 'success' &&
(needs.build_i18n.result == 'success' || needs.build_i18n.result == 'skipped') &&
(needs.build_blog.result == 'success' || needs.build_blog.result == 'skipped')
(needs.build_blog.result == 'success' || needs.build_blog.result == 'skipped') &&
(needs.build_videos.result == 'success' || needs.build_videos.result == 'skipped')
runs-on: ubuntu-latest
steps:
@@ -135,5 +144,5 @@ jobs:
cleanup:
if: ${{ always() }}
needs: [build_english, build_i18n, build_blog, build_zimfile]
needs: [build_english, build_i18n, build_blog, build_videos]
uses: privacyguides/.github/.github/workflows/cleanup.yml@main

120
.github/workflows/build-videos.yml vendored Normal file
View File

@@ -0,0 +1,120 @@
# SPDX-FileCopyrightText: 2025 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🛠️ Build Videos
on:
workflow_call:
inputs:
ref:
required: true
type: string
repo:
required: true
type: string
context:
type: string
default: deploy-preview
continue-on-error:
type: boolean
default: true
privileged:
type: boolean
default: true
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
continue-on-error: ${{ inputs.continue-on-error }}
permissions:
contents: read
steps:
- name: Add GitHub Token to Environment
run: |
echo "GH_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_ENV"
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download Submodules
uses: actions/download-artifact@v4
with:
pattern: repo-*
path: modules
- name: Move mkdocs-material-insiders to mkdocs-material
if: inputs.privileged
run: |
rmdir modules/mkdocs-material
mv modules/repo-mkdocs-material-insiders modules/mkdocs-material
- name: Move brand submodule to theme/assets/brand
run: |
rmdir theme/assets/brand
mv modules/repo-brand theme/assets/brand
- name: Install Python (pipenv)
if: inputs.privileged
uses: actions/setup-python@v5
with:
cache: "pipenv"
- name: Install Python (no pipenv)
if: ${{ !inputs.privileged }}
uses: actions/setup-python@v5
- name: Install Python Dependencies
if: inputs.privileged
run: |
pip install pipenv
pipenv install
sudo apt install pngquant
- name: Install Python Dependencies (Unprivileged)
if: ${{ !inputs.privileged }}
run: |
pip install mkdocs-material mkdocs-rss-plugin mkdocs-glightbox mkdocs-macros-plugin
sudo apt install pngquant
- name: Set base navigation URLs for production build
if: inputs.context == 'production'
run: |
{
echo "MAIN_SITE_BASE_URL=https://www.privacyguides.org/en/"
echo "MAIN_SITE_ABOUT_URL=https://www.privacyguides.org/en/about/"
echo "MAIN_SITE_RECOMMENDATIONS_URL=https://www.privacyguides.org/en/tools/"
echo "MAIN_SITE_KNOWLEDGE_BASE_URL=https://www.privacyguides.org/en/basics/why-privacy-matters/"
echo "ARTICLES_SITE_BASE_URL=https://www.privacyguides.org/articles/"
echo "VIDEOS_SITE_BASE_URL=https://www.privacyguides.org/videos/"
} >> "$GITHUB_ENV"
- name: Build Website (Privileged)
if: inputs.privileged
run: |
pipenv run mkdocs build --config-file mkdocs.videos.yml
- name: Build Website (Unprivileged)
if: ${{ !inputs.privileged }}
run: |
BUILD_INSIDERS=false mkdocs build --config-file mkdocs.videos.yml
- name: Package Website
run: |
tar -czf site-build-videos.tar.gz site
- name: Upload Site
uses: actions/upload-artifact@v4
with:
name: site-build-videos.tar.gz
path: site-build-videos.tar.gz
retention-days: 1

View File

@@ -1,594 +0,0 @@
name: 🥝 Build Zimfile
on:
workflow_call:
inputs:
ref:
required: true
type: string
repo:
required: true
type: string
permissions:
contents: read
env:
VIDEOS_SITE_BASE_URL: https://www.privacyguides.org/videos/
HOMEPAGE_CTA_ABOUT_LINK: about.html
HOMEPAGE_CTA_DONATE_LINK: about/donate.html
BUILD_OFFLINE: true
PRODUCTION: true
CARDS: false
GITREVISIONDATE: false
GITAUTHORS: false
jobs:
package_eng:
runs-on: ubuntu-latest
permissions:
contents: read
env:
LANGUAGE_SWITCHER: false
MAIN_SITE_BASE_URL: /en/index.html
MAIN_SITE_ABOUT_URL: /en/about.html
MAIN_SITE_RECOMMENDATIONS_URL: /en/tools.html
MAIN_SITE_KNOWLEDGE_BASE_URL: /en/basics/why-privacy-matters.html
ARTICLES_SITE_BASE_URL: /articles/index.html
steps:
- name: Add GitHub Token to Environment
run: |
echo "GH_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_ENV"
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download Submodules
uses: actions/download-artifact@v4
with:
pattern: repo-*
path: modules
- name: Move mkdocs-material-insiders to mkdocs-material
run: |
rmdir modules/mkdocs-material
mv modules/repo-mkdocs-material-insiders modules/mkdocs-material
- name: Move brand submodule to theme/assets/brand
run: |
rmdir theme/assets/brand
mv modules/repo-brand theme/assets/brand
- name: Install Python (pipenv)
uses: actions/setup-python@v5
with:
cache: "pipenv"
- name: Install Python Dependencies
run: |
pip install pipenv
pipenv install
sudo apt install pngquant
- name: Generate Donating Members List
continue-on-error: true
run: |
pip install requests
python tools/generate-members.py > includes/members.md
- name: Build English
run: |
./run.sh --build --production --insiders --offline --lang=en
- name: Delete Unreferenced Assets
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/en/assets
SEARCH_DIR: site/en
- name: Run generate-topics.sh for top posts
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
--count=3
- name: Run generate-topics.sh for latest posts
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
--count=12
- name: Build Articles
run: |
pipenv run mkdocs build --config-file mkdocs.blog.yml
- name: Delete Unreferenced Assets
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/articles/assets
SEARCH_DIR: site/articles
- name: Remove Duplicate Files
run: |
cd site && bash ../tools/symlink-duplicates.sh
ln -s en/index.html index.html
ln -s en/about/notices.html license
cd ..
- name: Set zimfile name
run: |
echo "ZIMFILE_NAME=privacyguides.org_en_all_$(date +%Y)-$(date +%m).zim" >> "$GITHUB_ENV"
- name: Create ZIM File
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimwriterfs \
-w index.html \
-I en/assets/brand/logos/png/square/pg-yellow.png \
-l eng \
-t "Privacy Guides" \
-d "Your central privacy and security resource to protect yourself online." \
-c "Privacy Guides" \
-p "Privacy Guides" \
-e "https://www.privacyguides.org" \
-n "privacyguides.org_en_all" \
/data/site/ /data/${{ env.ZIMFILE_NAME }}
- name: Upload ZIM File
uses: actions/upload-artifact@v4
with:
path: ${{ env.ZIMFILE_NAME }}
name: ${{ env.ZIMFILE_NAME }}
compression-level: 0
- name: Run zimcheck
uses: addnab/docker-run-action@v3
continue-on-error: true
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimcheck /data/${{ env.ZIMFILE_NAME }}
package_eng_kb:
runs-on: ubuntu-latest
permissions:
contents: read
env:
LANGUAGE_SWITCHER: false
ARTICLES_SITE_BASE_URL: https://www.privacyguides.org/posts/tag/articles/
steps:
- name: Add GitHub Token to Environment
run: |
echo "GH_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_ENV"
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download Submodules
uses: actions/download-artifact@v4
with:
pattern: repo-*
path: modules
- name: Move mkdocs-material-insiders to mkdocs-material
run: |
rmdir modules/mkdocs-material
mv modules/repo-mkdocs-material-insiders modules/mkdocs-material
- name: Move brand submodule to theme/assets/brand
run: |
rmdir theme/assets/brand
mv modules/repo-brand theme/assets/brand
- name: Install Python (pipenv)
uses: actions/setup-python@v5
with:
cache: "pipenv"
- name: Install Python Dependencies
run: |
pip install pipenv
pipenv install
sudo apt install pngquant
- name: Generate Donating Members List
continue-on-error: true
run: |
pip install requests
python tools/generate-members.py > includes/members.md
- name: Build English
run: |
./run.sh --build --production --insiders --offline --lang=en
- name: Run generate-topics.sh for top posts
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
--count=3
- name: Run generate-topics.sh for latest posts
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
--count=12
- name: Delete Unreferenced Assets
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/en/assets
SEARCH_DIR: site/en
- name: Remove Duplicate Files
run: |
cd site && bash ../tools/symlink-duplicates.sh
ln -s en/index.html index.html
ln -s en/about/notices.html license
cd ..
- name: Set zimfile name
run: |
echo "ZIMFILE_NAME=privacyguides.org_en_kb_$(date +%Y)-$(date +%m).zim" >> "$GITHUB_ENV"
- name: Create ZIM File
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimwriterfs \
-w index.html \
-I en/assets/brand/logos/png/square/pg-yellow.png \
-l eng \
-t "Privacy Guides" \
-d "Knowledge base articles and recommendations from Privacy Guides." \
-c "Privacy Guides" \
-p "Privacy Guides" \
-e "https://www.privacyguides.org" \
-n "privacyguides.org_en_kb" \
/data/site/ /data/${{ env.ZIMFILE_NAME }}
- name: Upload ZIM File
uses: actions/upload-artifact@v4
with:
path: ${{ env.ZIMFILE_NAME }}
name: ${{ env.ZIMFILE_NAME }}
compression-level: 0
- name: Run zimcheck
uses: addnab/docker-run-action@v3
continue-on-error: true
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimcheck /data/${{ env.ZIMFILE_NAME }}
package_eng_articles:
runs-on: ubuntu-latest
permissions:
contents: read
env:
MAIN_SITE_BASE_URL: https://www.privacyguides.org/en/
MAIN_SITE_ABOUT_URL: https://www.privacyguides.org/en/about/
MAIN_SITE_RECOMMENDATIONS_URL: https://www.privacyguides.org/en/tools/
MAIN_SITE_KNOWLEDGE_BASE_URL: https://www.privacyguides.org/en/basics/
steps:
- name: Add GitHub Token to Environment
run: |
echo "GH_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_ENV"
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download Submodules
uses: actions/download-artifact@v4
with:
pattern: repo-*
path: modules
- name: Move mkdocs-material-insiders to mkdocs-material
run: |
rmdir modules/mkdocs-material
mv modules/repo-mkdocs-material-insiders modules/mkdocs-material
- name: Move brand submodule to theme/assets/brand
run: |
rmdir theme/assets/brand
mv modules/repo-brand theme/assets/brand
- name: Install Python (pipenv)
uses: actions/setup-python@v5
with:
cache: "pipenv"
- name: Install Python Dependencies
run: |
pip install pipenv
pipenv install
sudo apt install pngquant
- name: Build Articles
run: |
pipenv run mkdocs build --config-file mkdocs.blog.yml
- name: Delete Unreferenced Assets
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/articles/assets
SEARCH_DIR: site/articles
- name: Remove Duplicate Files
run: |
cd site && bash ../tools/symlink-duplicates.sh
ln -s articles/index.html index.html
cd ..
- name: Set zimfile name
run: |
echo "ZIMFILE_NAME=privacyguides.org_en_articles_$(date +%Y)-$(date +%m).zim" >> "$GITHUB_ENV"
- name: Create ZIM File
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimwriterfs \
-w index.html \
-I articles/assets/brand/logos/png/square/pg-yellow.png \
-l eng \
-t "Privacy Guides" \
-d "Long-form articles from the Privacy Guides team and other contributors." \
-c "Privacy Guides" \
-p "Privacy Guides" \
-e "https://www.privacyguides.org" \
-n "privacyguides.org_en_articles" \
/data/site/ /data/${{ env.ZIMFILE_NAME }}
- name: Upload ZIM File
uses: actions/upload-artifact@v4
with:
path: ${{ env.ZIMFILE_NAME }}
name: ${{ env.ZIMFILE_NAME }}
compression-level: 0
- name: Run zimcheck
uses: addnab/docker-run-action@v3
continue-on-error: true
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimcheck /data/${{ env.ZIMFILE_NAME }}
build_mul:
runs-on: ubuntu-latest
continue-on-error: true
permissions:
contents: read
env:
MAIN_SITE_BASE_URL: /en/index.html
MAIN_SITE_ABOUT_URL: /en/about.html
MAIN_SITE_RECOMMENDATIONS_URL: /en/tools.html
MAIN_SITE_KNOWLEDGE_BASE_URL: /en/basics/why-privacy-matters.html
ARTICLES_SITE_BASE_URL: /articles/index.html
strategy:
matrix:
lang: [en, es, fr, he, it, nl, ru, zh-Hant]
steps:
- name: Add GitHub Token to Environment
run: |
echo "GH_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_ENV"
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download Submodules
uses: actions/download-artifact@v4
with:
pattern: repo-*
path: modules
- name: Move mkdocs-material-insiders to mkdocs-material
run: |
rmdir modules/mkdocs-material
mv modules/repo-mkdocs-material-insiders modules/mkdocs-material
- name: Move brand submodule to theme/assets/brand
run: |
rmdir theme/assets/brand
mv modules/repo-brand theme/assets/brand
- name: Copy Translation Files
if: matrix.lang != 'en'
run: |
cp -rl modules/repo-i18n/i18n .
cp -rl modules/repo-i18n/includes .
- name: Install Python (pipenv)
uses: actions/setup-python@v5
with:
cache: "pipenv"
- name: Install Python Dependencies
run: |
pip install pipenv
pipenv install
sudo apt install pngquant
- name: Generate Donating Members List
continue-on-error: true
run: |
pip install requests
python tools/generate-members.py > includes/members.md
- name: Build Website
run: |
./run.sh --build --production --insiders --offline --lang=${{ matrix.lang }}
- name: Run generate-topics.sh for top posts
if: matrix.lang == 'en'
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
--count=3
- name: Run generate-topics.sh for latest posts
if: matrix.lang == 'en'
run: |
bash tools/generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
--count=12
- name: Delete Unreferenced Assets
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/${{ matrix.lang }}/assets
SEARCH_DIR: site/${{ matrix.lang }}
- name: Build Articles
if: matrix.lang == 'en'
run: |
pipenv run mkdocs build --config-file mkdocs.blog.yml
- name: Delete Unreferenced Assets
if: matrix.lang == 'en'
run: |
bash tools/delete-unreferenced.sh
env:
ASSETS_DIR: site/articles/assets
SEARCH_DIR: site/articles
- name: Package Website
run: |
tar -czf site-zimready-${{ matrix.lang }}.tar.gz site
- name: Upload Site
uses: actions/upload-artifact@v4
with:
name: site-zimready-${{ matrix.lang }}.tar.gz
path: site-zimready-${{ matrix.lang }}.tar.gz
retention-days: 1
compression-level: 0
package_mul:
runs-on: ubuntu-latest
needs: [build_mul]
permissions:
contents: read
steps:
- name: Download Repository
uses: actions/checkout@v4
with:
repository: ${{ inputs.repo }}
ref: ${{ inputs.ref }}
persist-credentials: "false"
fetch-depth: 0
- name: Download All Sites
uses: actions/download-artifact@v4
with:
pattern: site-zimready-*
merge-multiple: true
- name: List Files (for debugging)
run: |
for file in *.tar.gz; do tar -zxf "$file"; done
ls -la site/
- name: Remove Duplicate Files
run: |
cd site && bash ../tools/symlink-duplicates.sh
ln -s en/index.html index.html
ln -s en/about/notices.html license
cd ..
- name: Set zimfile name
run: |
echo "ZIMFILE_NAME=privacyguides.org_mul_all_$(date +%Y)-$(date +%m).zim" >> "$GITHUB_ENV"
- name: Create ZIM File
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimwriterfs \
-w index.html \
-I en/assets/brand/logos/png/square/pg-yellow.png \
-l mul \
-t "Privacy Guides" \
-d "Your central privacy and security resource to protect yourself online." \
-c "Privacy Guides" \
-p "Privacy Guides" \
-e "https://www.privacyguides.org" \
-n "privacyguides.org_mul_all" \
/data/site/ /data/${{ env.ZIMFILE_NAME }}
- name: Upload ZIM File
uses: actions/upload-artifact@v4
with:
path: ${{ env.ZIMFILE_NAME }}
name: ${{ env.ZIMFILE_NAME }}
compression-level: 0
- name: Run zimcheck
uses: addnab/docker-run-action@v3
continue-on-error: true
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimcheck /data/${{ env.ZIMFILE_NAME }}

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2021 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🛠️ Build Website
on:
@@ -30,6 +34,9 @@ on:
cache:
type: boolean
default: true
secrets:
RO_DISCOURSE_API_KEY:
required: false
permissions:
contents: read
@@ -62,7 +69,7 @@ jobs:
echo "MAIN_SITE_ABOUT_URL=https://www.privacyguides.org/en/about/"
echo "MAIN_SITE_RECOMMENDATIONS_URL=https://www.privacyguides.org/en/tools/"
echo "MAIN_SITE_KNOWLEDGE_BASE_URL=https://www.privacyguides.org/en/basics/why-privacy-matters/"
echo "ARTICLES_SITE_BASE_URL=https://www.privacyguides.org/posts/tag/articles/"
echo "ARTICLES_SITE_BASE_URL=https://www.privacyguides.org/articles/"
echo "VIDEOS_SITE_BASE_URL=https://www.privacyguides.org/videos/"
} >> "$GITHUB_ENV"
@@ -157,6 +164,19 @@ jobs:
social-cache-${{ inputs.repo }}-${{ inputs.lang }}-
social-cache-privacyguides/privacyguides.org-${{ inputs.lang }}-
- name: Restore Optimize Plugin Cache
uses: actions/cache/restore@v4
id: optimize_cache_restore
if: inputs.cache
with:
key: optimize-cache-${{ inputs.repo }}-${{ hashfiles('.cache/plugin/optimize/manifest.json') }}
path: |
.cache/plugin/optimize
restore-keys: |
optimize-cache-${{ inputs.repo }}-
optimize-cache-privacyguides/privacyguides.org-
optimize-cache-
- name: Install Python Dependencies
if: inputs.privileged
run: |
@@ -173,9 +193,11 @@ jobs:
- name: Generate Donating Members List
continue-on-error: true
env:
DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}
run: |
pip install requests
python tools/generate-members.py > includes/members.md
python generate-members.py > includes/members.md
- name: Build Website
run: |
@@ -184,7 +206,7 @@ jobs:
- name: Run generate-topics.sh for top posts
if: inputs.lang == 'en'
run: |
bash tools/generate-topics.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
@@ -193,7 +215,7 @@ jobs:
- name: Run generate-topics.sh for latest posts
if: inputs.lang == 'en'
run: |
bash tools/generate-topics.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
@@ -224,6 +246,16 @@ jobs:
.cache/plugin/social/manifest.json
.cache/plugin/social/assets
- name: Find Optimize Plugin Cache
uses: actions/cache/restore@v4
if: steps.optimize_cache_restore.outputs.cache-hit != 'true' && inputs.cache
id: optimize_cache_test
with:
key: optimize-cache-privacyguides/privacyguides.org-${{ hashfiles('.cache/plugin/optimize/manifest.json') }}
lookup-only: true
path: |
.cache/plugin/optimize
- name: Save Privacy Plugin Cache
uses: actions/cache/save@v4
if: steps.privacy_cache_test.outputs.cache-hit != 'true' && inputs.cache
@@ -240,6 +272,13 @@ jobs:
.cache/plugin/social/manifest.json
.cache/plugin/social/assets
- name: Save Optimize Plugin Cache
uses: actions/cache/save@v4
if: steps.optimize_cache_test.outputs.cache-hit != 'true' && inputs.cache
with:
key: optimize-cache-${{ inputs.repo }}-${{ hashfiles('.cache/plugin/optimize/manifest.json') }}
path: .cache/plugin/optimize
- name: Upload Site
uses: actions/upload-artifact@v4
with:
@@ -254,3 +293,47 @@ jobs:
name: members.md
path: includes/members.md
retention-days: 1
offline_package:
if: inputs.config == 'offline' && inputs.lang == 'en'
needs: build
runs-on: ubuntu-latest
continue-on-error: ${{ inputs.continue-on-error }}
permissions:
contents: read
steps:
- uses: actions/download-artifact@v4
with:
name: site-offline-en.tar.gz
- run: |
tar -xzf site-offline-en.tar.gz
tar -czf offline.tar.gz site/en
zip -r -q offline.zip site/en
- name: Upload tar.gz file
uses: actions/upload-artifact@v4
with:
name: offline.tar.gz
path: offline.tar.gz
- name: Upload zip file
uses: actions/upload-artifact@v4
with:
name: offline.zip
path: offline.zip
- name: Create ZIM File
uses: addnab/docker-run-action@v3
with:
image: ghcr.io/openzim/zim-tools:3.1.3
options: -v ${{ github.workspace }}:/data
run: |
zimwriterfs -w index.html -I assets/brand/logos/png/square/pg-yellow.png -l eng -t "Privacy Guides" -d "Your central privacy and security resource to protect yourself online." -c "Privacy Guides" -p "Jonah Aragon" -n "Privacy Guides" -e "https://github.com/privacyguides/privacyguides.org" /data/site/en /data/offline-privacy_guides.zim
- name: Upload ZIM file
uses: actions/upload-artifact@v4
with:
name: offline-privacy_guides.zim
path: offline-privacy_guides.zim

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2021-2025 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2021 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 📦 Immediate Releases
@@ -27,6 +11,7 @@ on:
- "main"
paths:
- "blog/**"
- "videos/**"
concurrency:
group: release-deployment
@@ -60,8 +45,19 @@ jobs:
continue-on-error: false
context: production
build_videos:
needs: submodule
permissions:
contents: read
uses: ./.github/workflows/build-videos.yml
with:
repo: ${{ github.repository }}
ref: ${{ github.ref }}
continue-on-error: false
context: production
deploy:
needs: [build_blog]
needs: [build_blog, build_videos]
uses: privacyguides/webserver/.github/workflows/deploy-garage.yml@main
with:
environment: production
@@ -71,5 +67,5 @@ jobs:
cleanup:
if: ${{ always() }}
needs: [build_blog]
needs: [build_blog, build_videos]
uses: privacyguides/.github/.github/workflows/cleanup.yml@main

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2022 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2022 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🪞 Push to Mirrors

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 📦 PR Preview
on:
@@ -89,6 +93,18 @@ jobs:
echo "sha=$(cat metadata/SHA)" >> "$GITHUB_OUTPUT"
echo "privileged=$(cat metadata/PRIVILEGED)" >> "$GITHUB_OUTPUT"
deploy_netlify:
needs: metadata
permissions:
contents: read
uses: privacyguides/webserver/.github/workflows/deploy-netlify-preview.yml@main
with:
netlify_alias: ${{ needs.metadata.outputs.pr_number }}
netlify_site_id: ${{ vars.NETLIFY_SITE }}
secrets:
NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
deploy_garage:
needs: metadata
permissions:

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2021-2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2021 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 📦 Release
@@ -50,8 +34,8 @@ jobs:
needs: submodule
strategy:
matrix:
lang: [en, es, fr, he, it, nl, ru, zh-Hant, zh-TW]
build: [build]
lang: [en, es, fr, he, it, nl, ru, zh-Hant]
build: [build, offline]
permissions:
contents: read
uses: ./.github/workflows/build.yml
@@ -63,6 +47,8 @@ jobs:
context: production
continue-on-error: false
cache: false
secrets:
RO_DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}
build_blog:
needs: submodule
@@ -75,18 +61,20 @@ jobs:
continue-on-error: false
context: production
build_zimfile:
build_videos:
needs: submodule
permissions:
contents: read
uses: ./.github/workflows/build-zimfile.yml
uses: ./.github/workflows/build-videos.yml
with:
repo: ${{ github.repository }}
ref: ${{ github.ref }}
continue-on-error: false
context: production
release:
name: Create release notes
needs: [build, build_zimfile]
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
@@ -94,20 +82,21 @@ jobs:
steps:
- uses: actions/download-artifact@v4
with:
pattern: "*.zim"
pattern: offline*
merge-multiple: true
- name: Create release notes
uses: ncipollo/release-action@v1
with:
generateReleaseNotes: true
artifacts: "*.zim"
artifacts: "offline.zip,offline.tar.gz,offline-privacy_guides.zim"
makeLatest: true
deploy:
needs: [build, build_blog]
needs: [build, build_blog, build_videos]
uses: privacyguides/webserver/.github/workflows/deploy-all.yml@main
secrets:
NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
PROD_MINIO_KEY_ID: ${{ secrets.PROD_MINIO_KEY_ID }}
PROD_MINIO_SECRET_KEY: ${{ secrets.PROD_MINIO_SECRET_KEY }}
PROD_GARAGE_KEY_ID: ${{ secrets.PROD_GARAGE_KEY_ID }}
@@ -121,5 +110,5 @@ jobs:
cleanup:
if: ${{ always() }}
needs: [build, build_blog, build_zimfile]
needs: [build, build_blog, build_videos]
uses: privacyguides/.github/.github/workflows/cleanup.yml@main

16
.github/workflows/reuse.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2020 Free Software Foundation Europe e.V.
# SPDX-License-Identifier: CC0-1.0
name: 📋 REUSE Compliance Check
permissions:
contents: read
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v4

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 📦 Manual Test Build

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🤖 Linting

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 🔄 Update Discussions
@@ -57,7 +41,7 @@ jobs:
- name: Run generate-topics.sh for top posts
run: |
bash tools/generate-topics.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
@@ -65,7 +49,7 @@ jobs:
- name: Run generate-topics.sh for latest posts
run: |
bash tools/generate-topics.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2022-2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2022 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
name: 💬 Crowdin Upload

4
.gitignore vendored
View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2019 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
site
/i18n/
/includes/*.*.*

View File

@@ -15,7 +15,6 @@ Jonah Aragon <jonah@privacyguides.org> <jonah@triplebit.net>
Jonah Aragon <jonah@privacyguides.org> <jonah@privacytools.io>
Jonah Aragon <jonah@privacyguides.org> <github@aragon.science>
Jordan Warne <jordan@privacyguides.org> <jw@omg.lol>
Jordan Warne <jordan@privacyguides.org> <contact@jordanwarne.net>
Justin Ehrenhofer <justin.ehrenhofer@gmail.com> <12520755+SamsungGalaxyPlayer@users.noreply.github.com>
Mare Polaris <ph00lt0@privacyguides.org> <15004290+ph00lt0@users.noreply.github.com>
Niek de Wilde <niek@privacyguides.org> <github.ef27z@simplelogin.com>

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2022 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2022 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
default: true
line-length: false

View File

@@ -1,22 +1,6 @@
// Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
//
// SPDX-License-Identifier: MIT
{
"recommendations": [

View File

@@ -316,6 +316,7 @@ cryptofs
siv-mode
cryptolib-swift
cryptomator-objc-cryptor
Picocrypt
VeraCrypt
TrueCrypt
cryptoprocessor
@@ -568,5 +569,3 @@ allowlisted
MyMonero
Monero-LWS
OkCupid
Anom
misgendering

25
.vscode/settings.json vendored
View File

@@ -1,22 +1,6 @@
// Copyright (c) 2024 Jonah Aragon <jonah@triplebit.net>
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
//
// SPDX-License-Identifier: MIT
{
"git.ignoreLimitWarning": true,
@@ -115,6 +99,5 @@
"editor.formatOnSave": true,
"[github-actions-workflow]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"python-envs.pythonProjects": []
}
}

View File

@@ -1 +0,0 @@
https://www.privacyguides.org/funding.json

View File

@@ -1,22 +1,6 @@
# Copyright (c) 2022-2024 Jonah Aragon <jonah@triplebit.net>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-FileCopyrightText: 2022 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
cff-version: 1.2.0
title: Privacy Guides

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT
FROM python:3.12-slim-bookworm AS base
LABEL org.opencontainers.image.source="https://github.com/privacyguides/privacyguides.org"
@@ -31,7 +35,7 @@ COPY Pipfile .
COPY Pipfile.lock .
# Install all Python dependencies into a projectlocal virtual environment at /.venv
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy --dev
####################################################
# Stage: nodejs-deps

427
LICENSE
View File

@@ -1,427 +0,0 @@
Attribution-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public licenses.
Notwithstanding, Creative Commons may elect to apply one of its public
licenses to material it publishes and in those instances will be
considered the “Licensor.” The text of the Creative Commons public
licenses is dedicated to the public domain under the CC0 Public Domain
Dedication. Except for the limited purpose of indicating that material
is shared under a Creative Commons public license or as otherwise
permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the public
licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@@ -1,22 +0,0 @@
MIT License
Copyright (c) 2019 - 2024 Jonah Aragon <jonah@triplebit.net>
Copyright (c) 2020 - 2024 Privacy Guides contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

170
LICENSES/CC-BY-SA-4.0.txt Normal file
View File

@@ -0,0 +1,170 @@
Creative Commons Attribution-ShareAlike 4.0 International
Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.
Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensors permission is not necessary for any reasonfor example, because of any applicable exception or limitation to copyrightthen that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.
Creative Commons Attribution-ShareAlike 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
Section 1 Definitions.
a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
e. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
i. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights under this Public License.
k. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
Section 2 Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
A. reproduce and Share the Licensed Material, in whole or in part; and
B. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
3. Term. The term of this Public License is specified in Section 6(a).
4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
5. Downstream recipients.
A. Offer from the Licensor Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
B. Additional offer from the Licensor Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapters License You apply.
C. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this Public License.
3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
Section 3 License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified form), You must:
A. retain the following if it is supplied by the Licensor with the Licensed Material:
i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of warranties;
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
b. ShareAlike.In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply.
1. The Adapters License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply.
Section 4 Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
Section 5 Disclaimer of Warranties and Limitation of Liability.
a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
Section 6 Term and Termination.
a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
2. upon express reinstatement by the Licensor.
c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
Section 7 Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
Section 8 Interpretation.
a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
Creative Commons may be contacted at creativecommons.org.

121
LICENSES/CC0-1.0.txt Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@@ -0,0 +1,11 @@
# Fair Use or No Assertion!
We believe that the logos and other images we've obtained from third-party providers are either in the public domain or fair use.
In a nutshell, legal fair use doctrine allows the use of copyrighted images in order to identify the subject for purposes of public comment.
However, these logos and other images may still be subject to trademark laws in one or more jurisdictions.
Before using this content, please ensure that it is used to identify the entity or organization that owns the trademark and that you have the right to use it under the laws which apply in the circumstances of your intended use.
**When copying this content from this website, you are solely responsible for ensuring that you do not infringe someone else's trademark or copyright.**

View File

@@ -0,0 +1,19 @@
Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

18
LICENSES/MIT.txt Normal file
View File

@@ -0,0 +1,18 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

21
Pipfile
View File

@@ -1,22 +1,6 @@
# Copyright (c) 2022-2024 Jonah Aragon <jonah@triplebit.net>
# SPDX-FileCopyrightText: 2022 Jonah Aragon <jonah@privacyguides.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
[[source]]
url = "https://pypi.org/simple"
@@ -34,6 +18,7 @@ mkdocs-glightbox = "*"
[dev-packages]
scour = "~=0.38"
reuse = "*"
[requires]
python_version = "3.12"

662
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "4707be3ca5e170a9f90dc4dc36c99880bdc9d78df9387779096f23246a63ee0a"
"sha256": "57110d51ec1806b11961bf3e99a82ae5d84c99c7b092ff4a37273a68a09f3fd6"
},
"pipfile-spec": 6,
"requires": {
@@ -64,11 +64,11 @@
},
"certifi": {
"hashes": [
"sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407",
"sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"
"sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6",
"sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"
],
"markers": "python_version >= '3.7'",
"version": "==2025.8.3"
"markers": "python_version >= '3.6'",
"version": "==2025.4.26"
},
"cffi": {
"hashes": [
@@ -145,88 +145,101 @@
},
"charset-normalizer": {
"hashes": [
"sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91",
"sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0",
"sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154",
"sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601",
"sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884",
"sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07",
"sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c",
"sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64",
"sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe",
"sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f",
"sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432",
"sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc",
"sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa",
"sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9",
"sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae",
"sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19",
"sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d",
"sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e",
"sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4",
"sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7",
"sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312",
"sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92",
"sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31",
"sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c",
"sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f",
"sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99",
"sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b",
"sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15",
"sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392",
"sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f",
"sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8",
"sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491",
"sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0",
"sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc",
"sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0",
"sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f",
"sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a",
"sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40",
"sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927",
"sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849",
"sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce",
"sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14",
"sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05",
"sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c",
"sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c",
"sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a",
"sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc",
"sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34",
"sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9",
"sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096",
"sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14",
"sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30",
"sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b",
"sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b",
"sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942",
"sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db",
"sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5",
"sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b",
"sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce",
"sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669",
"sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0",
"sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018",
"sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93",
"sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe",
"sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049",
"sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a",
"sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef",
"sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2",
"sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca",
"sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16",
"sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f",
"sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb",
"sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1",
"sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557",
"sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37",
"sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7",
"sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72",
"sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c",
"sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"
"sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4",
"sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45",
"sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7",
"sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0",
"sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7",
"sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d",
"sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d",
"sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0",
"sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184",
"sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db",
"sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b",
"sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64",
"sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b",
"sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8",
"sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff",
"sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344",
"sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58",
"sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e",
"sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471",
"sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148",
"sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a",
"sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836",
"sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e",
"sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63",
"sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c",
"sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1",
"sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01",
"sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366",
"sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58",
"sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5",
"sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c",
"sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2",
"sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a",
"sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597",
"sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b",
"sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5",
"sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb",
"sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f",
"sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0",
"sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941",
"sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0",
"sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86",
"sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7",
"sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7",
"sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455",
"sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6",
"sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4",
"sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0",
"sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3",
"sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1",
"sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6",
"sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981",
"sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c",
"sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980",
"sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645",
"sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7",
"sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12",
"sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa",
"sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd",
"sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef",
"sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f",
"sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2",
"sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d",
"sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5",
"sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02",
"sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3",
"sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd",
"sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e",
"sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214",
"sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd",
"sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a",
"sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c",
"sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681",
"sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba",
"sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f",
"sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a",
"sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28",
"sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691",
"sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82",
"sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a",
"sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027",
"sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7",
"sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518",
"sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf",
"sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b",
"sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9",
"sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544",
"sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da",
"sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509",
"sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f",
"sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a",
"sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"
],
"markers": "python_version >= '3.7'",
"version": "==3.4.3"
"version": "==3.4.2"
},
"click": {
"hashes": [
@@ -262,11 +275,11 @@
},
"filelock": {
"hashes": [
"sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58",
"sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"
"sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2",
"sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"
],
"markers": "python_version >= '3.9'",
"version": "==3.19.1"
"version": "==3.18.0"
},
"ghp-import": {
"hashes": [
@@ -285,11 +298,11 @@
},
"gitpython": {
"hashes": [
"sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c",
"sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"
"sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110",
"sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.45"
"version": "==3.1.44"
},
"hjson": {
"hashes": [
@@ -323,11 +336,11 @@
},
"markdown": {
"hashes": [
"sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280",
"sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a"
"sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc",
"sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"
],
"markers": "python_version >= '3.9'",
"version": "==3.9"
"version": "==3.8"
},
"markupsafe": {
"hashes": [
@@ -422,12 +435,12 @@
},
"mkdocs-git-authors-plugin": {
"hashes": [
"sha256:28421a99c3e872a8e205674bb80ec48524838243e5f59eaf9bd97df103e38901",
"sha256:29d1973b2835663d79986fb756e02f1f0ff3fe35c278e993206bd3c550c205e4"
"sha256:acdacc8452db90a94d9c395a230b16965a9f2f51e0a6eef182ac7d3e02e394fb",
"sha256:e19f0252ead3d626fd73e15bb56d6675704c3b62aa569ebc363f791291b8f60e"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==0.10.0"
"version": "==0.9.5"
},
"mkdocs-git-revision-date-localized-plugin": {
"hashes": [
@@ -440,21 +453,20 @@
},
"mkdocs-glightbox": {
"hashes": [
"sha256:7d78a5b045f2479f61b0bbb17742ba701755c56b013e70ac189c9d87a91e80bf",
"sha256:f47af0daff164edf8d36e553338425be3aab6e34b987d9cbbc2ae7819a98cb01"
"sha256:392b34207bf95991071a16d5f8916d1d2f2cd5d5bb59ae2997485ccd778c70d9",
"sha256:e0107beee75d3eb7380ac06ea2d6eac94c999eaa49f8c3cbab0e7be2ac006ccf"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==0.5.1"
"version": "==0.4.0"
},
"mkdocs-macros-plugin": {
"hashes": [
"sha256:01b6003fbe9b55fdc97c0abb66f811d65abfd291dcf70f277990165553faa99a",
"sha256:c52351295efdbdbb37a9f0ea639719055ddb64a00115457289940e85696a81d9"
"sha256:02432033a5b77fb247d6ec7924e72fc4ceec264165b1644ab8d0dc159c22ce59",
"sha256:17c7fd1a49b94defcdb502fd453d17a1e730f8836523379d21292eb2be4cb523"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==1.3.9"
"version": "==1.3.7"
},
"mkdocs-material": {
"extras": [
@@ -482,68 +494,73 @@
},
"msgpack": {
"hashes": [
"sha256:196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8",
"sha256:1abfc6e949b352dadf4bce0eb78023212ec5ac42f6abfd469ce91d783c149c2a",
"sha256:1b13fe0fb4aac1aa5320cd693b297fe6fdef0e7bea5518cbc2dd5299f873ae90",
"sha256:1d75f3807a9900a7d575d8d6674a3a47e9f227e8716256f35bc6f03fc597ffbf",
"sha256:2fbbc0b906a24038c9958a1ba7ae0918ad35b06cb449d398b76a7d08470b0ed9",
"sha256:33be9ab121df9b6b461ff91baac6f2731f83d9b27ed948c5b9d1978ae28bf157",
"sha256:353b6fc0c36fde68b661a12949d7d49f8f51ff5fa019c1e47c87c4ff34b080ed",
"sha256:36043272c6aede309d29d56851f8841ba907a1a3d04435e43e8a19928e243c1d",
"sha256:3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0",
"sha256:3a89cd8c087ea67e64844287ea52888239cbd2940884eafd2dcd25754fb72232",
"sha256:40eae974c873b2992fd36424a5d9407f93e97656d999f43fca9d29f820899084",
"sha256:4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5",
"sha256:435807eeb1bc791ceb3247d13c79868deb22184e1fc4224808750f0d7d1affc1",
"sha256:4835d17af722609a45e16037bb1d4d78b7bdf19d6c0128116d178956618c4e88",
"sha256:4a28e8072ae9779f20427af07f53bbb8b4aa81151054e882aee333b158da8752",
"sha256:4d3237b224b930d58e9d83c81c0dba7aacc20fcc2f89c1e5423aa0529a4cd142",
"sha256:4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac",
"sha256:4fd6b577e4541676e0cc9ddc1709d25014d3ad9a66caa19962c4f5de30fc09ef",
"sha256:500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323",
"sha256:5692095123007180dca3e788bb4c399cc26626da51629a31d40207cb262e67f4",
"sha256:5fd1b58e1431008a57247d6e7cc4faa41c3607e8e7d4aaf81f7c29ea013cb458",
"sha256:61abccf9de335d9efd149e2fff97ed5974f2481b3353772e8e2dd3402ba2bd57",
"sha256:61e35a55a546a1690d9d09effaa436c25ae6130573b6ee9829c37ef0f18d5e78",
"sha256:6640fd979ca9a212e4bcdf6eb74051ade2c690b862b679bfcb60ae46e6dc4bfd",
"sha256:6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69",
"sha256:6f64ae8fe7ffba251fecb8408540c34ee9df1c26674c50c4544d72dbf792e5ce",
"sha256:71ef05c1726884e44f8b1d1773604ab5d4d17729d8491403a705e649116c9558",
"sha256:77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd",
"sha256:78426096939c2c7482bf31ef15ca219a9e24460289c00dd0b94411040bb73ad2",
"sha256:79c408fcf76a958491b4e3b103d1c417044544b68e96d06432a189b43d1215c8",
"sha256:7a17ac1ea6ec3c7687d70201cfda3b1e8061466f28f686c24f627cae4ea8efd0",
"sha256:7da8831f9a0fdb526621ba09a281fadc58ea12701bc709e7b8cbc362feabc295",
"sha256:870b9a626280c86cff9c576ec0d9cbcc54a1e5ebda9cd26dab12baf41fee218c",
"sha256:88d1e966c9235c1d4e2afac21ca83933ba59537e2e2727a999bf3f515ca2af26",
"sha256:88daaf7d146e48ec71212ce21109b66e06a98e5e44dca47d853cbfe171d6c8d2",
"sha256:8a8b10fdb84a43e50d38057b06901ec9da52baac6983d3f709d8507f3889d43f",
"sha256:8b17ba27727a36cb73aabacaa44b13090feb88a01d012c0f4be70c00f75048b4",
"sha256:8b65b53204fe1bd037c40c4148d00ef918eb2108d24c9aaa20bc31f9810ce0a8",
"sha256:8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9",
"sha256:96decdfc4adcbc087f5ea7ebdcfd3dee9a13358cae6e81d54be962efc38f6338",
"sha256:996f2609ddf0142daba4cefd767d6db26958aac8439ee41db9cc0db9f4c4c3a6",
"sha256:9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a",
"sha256:a32747b1b39c3ac27d0670122b57e6e57f28eefb725e0b625618d1b59bf9d1e0",
"sha256:a494554874691720ba5891c9b0b39474ba43ffb1aaf32a5dac874effb1619e1a",
"sha256:a8ef6e342c137888ebbfb233e02b8fbd689bb5b5fcc59b34711ac47ebd504478",
"sha256:ae497b11f4c21558d95de9f64fff7053544f4d1a17731c866143ed6bb4591238",
"sha256:b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7",
"sha256:b8f93dcddb243159c9e4109c9750ba5b335ab8d48d9522c5308cd05d7e3ce600",
"sha256:ba0c325c3f485dc54ec298d8b024e134acf07c10d494ffa24373bea729acf704",
"sha256:bb29aaa613c0a1c40d1af111abf025f1732cab333f96f285d6a93b934738a68a",
"sha256:bba1be28247e68994355e028dcd668316db30c1f758d3241a7b903ac78dcd285",
"sha256:cb643284ab0ed26f6957d969fe0dd8bb17beb567beb8998140b5e38a90974f6c",
"sha256:d182dac0221eb8faef2e6f44701812b467c02674a322c739355c39e94730cdbf",
"sha256:d275a9e3c81b1093c060c3837e580c37f47c51eca031f7b5fb76f7b8470f5f9b",
"sha256:d8b55ea20dc59b181d3f47103f113e6f28a5e1c89fd5b67b9140edb442ab67f2",
"sha256:da8f41e602574ece93dbbda1fab24650d6bf2a24089f9e9dbb4f5730ec1e58ad",
"sha256:e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b",
"sha256:f5be6b6bc52fad84d010cb45433720327ce886009d862f46b26d4d154001994b",
"sha256:f6d58656842e1b2ddbe07f43f56b10a60f2ba5826164910968f5933e5178af75"
"sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b",
"sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf",
"sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca",
"sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330",
"sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f",
"sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f",
"sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39",
"sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247",
"sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b",
"sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c",
"sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7",
"sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044",
"sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6",
"sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b",
"sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0",
"sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2",
"sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468",
"sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7",
"sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734",
"sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434",
"sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325",
"sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1",
"sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846",
"sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88",
"sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420",
"sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e",
"sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2",
"sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59",
"sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb",
"sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68",
"sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915",
"sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f",
"sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701",
"sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b",
"sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d",
"sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa",
"sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d",
"sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd",
"sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc",
"sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48",
"sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb",
"sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74",
"sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b",
"sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346",
"sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e",
"sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6",
"sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5",
"sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f",
"sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5",
"sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b",
"sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c",
"sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f",
"sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec",
"sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8",
"sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5",
"sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d",
"sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e",
"sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e",
"sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870",
"sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f",
"sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96",
"sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c",
"sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd",
"sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788"
],
"markers": "python_version >= '3.8'",
"version": "==1.1.1"
"version": "==1.1.0"
},
"packaging": {
"hashes": [
@@ -655,11 +672,11 @@
},
"platformdirs": {
"hashes": [
"sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85",
"sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"
"sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc",
"sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"
],
"markers": "python_version >= '3.9'",
"version": "==4.4.0"
"version": "==4.3.8"
},
"pycparser": {
"hashes": [
@@ -769,77 +786,11 @@
},
"requests": {
"hashes": [
"sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6",
"sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"
"sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760",
"sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"
],
"markers": "python_version >= '3.9'",
"version": "==2.32.5"
},
"selectolax": {
"hashes": [
"sha256:0933659b4250b91317ccd78167e6804389cdaf7ed86c5d034b058a550d23110f",
"sha256:0a98c3f3d8fffb175456cb06096bc78103ddf6a209bea6392e0e4ea4e25aca71",
"sha256:15679e9935ccf6c480a34baf8fe217c2b2023e0df18799f0232032dc8ac66d41",
"sha256:21de62b5093b1cb6c5d4cab0bef5f708b9ee1483b640d42be9d955becfcd287a",
"sha256:24f3f5de4051ca33ea769c8a99798c7e30e6500e090e363d5fcd3382b1ae8dfa",
"sha256:25cfccfefc41361ab8a07f15a224524a4a8b77dfa7d253b34bbd397e45856734",
"sha256:28696fa4581765c705e15d05dfba464334f5f9bcb3eac9f25045f815aec6fbc1",
"sha256:29e71fbd58b90d2920ef91a940680cb5331710fe397925ce9d10c3f2f086bf27",
"sha256:2bfe4327215a20af4197c5b7e3729a9552fb324bb57250dc7e7abfa0f848a463",
"sha256:2f5c3523ad5199a4fb9b95b6e24ff9222d3605023ca394b23f7dd910e7536daf",
"sha256:3625057ba0eab766db555f753959cc2759ec8ac49cded7c5f4d507d80fdf9433",
"sha256:38462ae369897f71da287f1282079c11f1b878b99a4d1d509d1116ce05226d88",
"sha256:394d356ea611a7853c13c910a57c1a80a8356f9c920aa8168b3f8aaa62e433d8",
"sha256:3e5354d805dd76b4b38002f58e6ae2e7b429ac311bf3601992a6662d2bc86911",
"sha256:3f58dca53d2d3dc18dfd2cb9210a5625f32598db24e3f857f5be58f21a8f3b88",
"sha256:45682905dd88e268bb5906ce2c3927e89f77b910824a6f64419bfec482cd67be",
"sha256:47587db7cef411d22f8224cf2926aacdb326c4c838d386035229f16ccc2d8d26",
"sha256:484274f73839f9a143f4c13ce1b0a0123b5d64be22f967a1dc202a9a78687d67",
"sha256:50b18a262ea01ca5522f9a30c28ecadb004be88296f6bd2ace21464f89a3cbcc",
"sha256:5388c56456272b2c241fc1906db9cc993984cafdad936cb5e061e3af0c44144e",
"sha256:558a0c665538bfd0549c40c4ea46523a77e8eae09f4e678191cf54c31c17517c",
"sha256:565304311e45c582e85ec525b0646aede6f8db1f22bc08786e94f7b6552d4311",
"sha256:6abdd8357f1c105c1add01a9f0373511fa832548b2e2778b00a8ba2a4508d6ed",
"sha256:6c684d66a0f8e48786ef6d79b9e1e84cb1ffd0835232b4033bed37cf978d1303",
"sha256:6d3f373efd1db18ac9b2222de2668aaa366a1f0b560241eab128f3ca68e8add1",
"sha256:6ff48efe4364c8148a553a4105773a0accee9cc25e0f2a40ddac44d18a5a3000",
"sha256:7073e3bcdc60ebdb5f8777c79b465471ec000ab556134da4e00f037d3321a2ec",
"sha256:7c10452a3a14ee7aa49afb141c3725ef7ba930d5b5391798daf2e053c414a158",
"sha256:8377c317bf1d5fd6ccc56dfb5a0928bbcbea3e800b7af54761cfbbb99dc94cb9",
"sha256:85aeae54f055cf5451828a21fbfecac99b8b5c27ec29fd10725b631593a7c9a3",
"sha256:90c435bc49395344abdaed80d98079466e8c8b6469118cec5cc9cae4dce8bcad",
"sha256:912a1fc03157ebd066d8f59ae9ca2412ef95c7101a51590327c23071b02c97c7",
"sha256:97b9971bb37b54ef4440134f22792d15c9ee12d890a526a7fe0b376502240143",
"sha256:9858fef96e4e332fa64102f0ab1ecf8f88a9ea46a82d379fb421c8f736b60090",
"sha256:9c969626b2295702076f50aac91e44c3bba639fa2e1a612bf6ae254bf29b4d57",
"sha256:a3d44a295416b79815d2858ed4ccb71bf3b63087483a5d3705daa837c9dcf44d",
"sha256:ac940963c52f13cdf5d7266a979744949b660d367ce669efa073b557f6e09a18",
"sha256:aecf29641a4b092331d081fb59f12f6b3fd236c16b48ef6e86419454df787ae1",
"sha256:af5cd03298cd75cb0fbf712d6ae4f8aca9c13a226d2821ca82f51cc9b33b032f",
"sha256:b0c9005e9089a6b0c6fb6a9f691ddbbb10a3a23ebeff54393980340f3dbcdb99",
"sha256:bc1676cd243812ca6ddd79ad53997996535e27db17fda3d440b470bb322f5959",
"sha256:bd99ff0f5a6c017c471635d4ee45b61d25f24689331e407147b2cf5e36892480",
"sha256:bdd1e63735f2fb8485fb6b9f4fe30d6c030930f438f46a4a62bd9886ab3c7fd9",
"sha256:be12a160b1feacd3db1ea2274dcb70dfa9b123b7a1216849eec7b48b6783e903",
"sha256:bf14ca824c4c9fd9b0534d0f316657495ffcedbaf77690be335242c688512b86",
"sha256:c198a1d3693aeccf1c45871bf3fee4bd46428fa99cdb9f3dfee20e1b48c363c7",
"sha256:c6b569fa67a122bfd7f0776c1c922daf122fb4502c8116a903c6168742b84db9",
"sha256:cfb803d6bbe0ef3c8847cf5a01167cc428c0d9179946e1c994cc6178b5332d1a",
"sha256:d0a6d8e02c6b9ba951d7b5a5dd2788a1d4bbdedc89782a4de165f1a87c4168ac",
"sha256:d458db7fee5f6b1ce75664ce8a009343c0aac1993a7b844a997cfea3ad0ea77b",
"sha256:d4ecc262db7afb0087e679176043178dc59791fce56659f62775a96d60596f1d",
"sha256:d6a1cd0518fa7656ea1683c4b2d3b5a98306753f364da9f673517847e1680a3e",
"sha256:db734ba4ef44fa3b57ad9374fd7ccfc7815c0ae5cfcbd5ee25fe8587092618d1",
"sha256:deeab93386b6c9a75052515f5b9e7e3dd623c585871c0c2b3126970ff902603b",
"sha256:dfee3340e8c89dd25a7dd621940b928960e4c9a70c4830d208f29b0adf288743",
"sha256:e13befacff5f78102aa11465055ecb6d4b35f89663e36f271f2b506bcab14112",
"sha256:e3112f05a34bf36d36ecc51520b1d98c4667b54a3f123dffef5072273e89a360",
"sha256:e7f4cc1b7ce9691559decfd5db7cc500e71a9f6ccfe76c054f284c184a1d1dc9",
"sha256:e9e4690894f406863e25ba49da27e1a6fda9bfc21b0b315c399d3093be080e81",
"sha256:ea52e0c128e8e89f98ab0ccaabbc853677de5730729a3351da595976131b66e0",
"sha256:edd2760699c60dde7d847aebd81f02035f7bddcd0ad3db8e73326dfc84a2dc8f"
],
"version": "==0.3.29"
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
"six": {
"hashes": [
@@ -883,11 +834,11 @@
},
"urllib3": {
"hashes": [
"sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760",
"sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"
"sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466",
"sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"
],
"markers": "python_version >= '3.9'",
"version": "==2.5.0"
"version": "==2.4.0"
},
"watchdog": {
"hashes": [
@@ -934,6 +885,229 @@
}
},
"develop": {
"attrs": {
"hashes": [
"sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3",
"sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"
],
"markers": "python_version >= '3.8'",
"version": "==25.3.0"
},
"binaryornot": {
"hashes": [
"sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061",
"sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4"
],
"version": "==0.4.4"
},
"boolean.py": {
"hashes": [
"sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95",
"sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9"
],
"version": "==5.0"
},
"chardet": {
"hashes": [
"sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7",
"sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"
],
"markers": "python_version >= '3.7'",
"version": "==5.2.0"
},
"charset-normalizer": {
"hashes": [
"sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91",
"sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0",
"sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154",
"sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601",
"sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884",
"sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07",
"sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c",
"sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64",
"sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe",
"sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f",
"sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432",
"sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc",
"sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa",
"sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9",
"sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae",
"sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19",
"sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d",
"sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e",
"sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4",
"sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7",
"sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312",
"sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92",
"sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31",
"sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c",
"sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f",
"sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99",
"sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b",
"sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15",
"sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392",
"sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f",
"sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8",
"sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491",
"sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0",
"sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc",
"sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0",
"sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f",
"sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a",
"sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40",
"sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927",
"sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849",
"sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce",
"sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14",
"sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05",
"sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c",
"sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c",
"sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a",
"sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc",
"sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34",
"sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9",
"sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096",
"sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14",
"sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30",
"sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b",
"sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b",
"sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942",
"sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db",
"sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5",
"sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b",
"sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce",
"sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669",
"sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0",
"sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018",
"sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93",
"sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe",
"sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049",
"sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a",
"sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef",
"sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2",
"sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca",
"sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16",
"sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f",
"sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb",
"sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1",
"sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557",
"sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37",
"sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7",
"sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72",
"sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c",
"sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"
],
"markers": "python_version >= '3.7'",
"version": "==3.4.3"
},
"click": {
"hashes": [
"sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202",
"sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"
],
"markers": "python_version >= '3.10'",
"version": "==8.2.1"
},
"jinja2": {
"hashes": [
"sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
"sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.6"
},
"license-expression": {
"hashes": [
"sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4",
"sha256:73448f0aacd8d0808895bdc4b2c8e01a8d67646e4188f887375398c761f340fd"
],
"markers": "python_version >= '3.9'",
"version": "==30.4.4"
},
"markupsafe": {
"hashes": [
"sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
"sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
"sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
"sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
"sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
"sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
"sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
"sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
"sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
"sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
"sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
"sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
"sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
"sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
"sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
"sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
"sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
"sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
"sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
"sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
"sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
"sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
"sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
"sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
"sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
"sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
"sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
"sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
"sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
"sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
"sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
"sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
"sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
"sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
"sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
"sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
"sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
"sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
"sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
"sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
"sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
"sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
"sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
"sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
"sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
"sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
"sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
"sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
"sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
"sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
"sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
"sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
"sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
"sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
"sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
"sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
"sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
"sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
"sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
"sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
"sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
],
"markers": "python_version >= '3.9'",
"version": "==3.0.2"
},
"python-debian": {
"hashes": [
"sha256:3ada9b83a3d671b58081782c0969cffa0102f6ce433fbbc7cf21275b8b5cc771",
"sha256:8f137c230c1d9279c2ac892b35915068b2aca090c9fd3da5671ff87af32af12c"
],
"markers": "python_version >= '3.7'",
"version": "==1.0.1"
},
"reuse": {
"hashes": [
"sha256:7a680f00324e87a72061677a892d8cbabfddf7adcf7a5376aeeed2d78995bbbb",
"sha256:878016ae5dd29c10bad4606d6676c12a268c12aa9fcfea66403598e16eed085c"
],
"index": "pypi",
"markers": "python_version >= '3.9' and python_version < '4.0'",
"version": "==5.0.2"
},
"scour": {
"hashes": [
"sha256:6881ec26660c130c5ecd996ac6f6b03939dd574198f50773f2508b81a68e0daf"
@@ -948,6 +1122,14 @@
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.17.0"
},
"tomlkit": {
"hashes": [
"sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1",
"sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"
],
"markers": "python_version >= '3.8'",
"version": "==0.13.3"
}
}
}

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2019 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
-->
<!-- markdownlint-disable MD041 MD045 -->
<div align="center">
<a href="https://www.privacyguides.org">
@@ -42,7 +48,7 @@
**Privacy Guides** is a socially motivated website that provides information for protecting your data security and privacy. Our mission is to inform the public about the value of digital privacy, and global government initiatives which aim to monitor your online activity. We are a non-profit collective operated entirely by volunteer team members and contributors. Our website is free of advertisements and not affiliated with any of the listed providers.
The current list of team members can be found on [the executive committee page](https://www.privacyguides.org/en/about/#executive-committee). Additionally, [many people](#contributors) have made contributions to the project, and you can too!
The current list of team members can be found [here](https://www.privacyguides.org/en/about/#executive-committee). Additionally, [many people](#contributors) have made contributions to the project, and you can too!
*Featured on: [Tweakers](https://tweakers.net/reviews/10568/op-zoek-naar-privacyvriendelijke-tools-niek-de-wilde-van-privacy-guides.html), [The New York Times](https://nytimes.com/wirecutter/guides/online-security-social-media-privacy), [Wired](https://wired.com/story/firefox-mozilla-2022), and [Fast Company](https://www.fastcompany.com/91167564/mozilla-wants-you-to-love-firefox-again).*
@@ -63,7 +69,9 @@ All contributors to the site are listed [here](#contributors). If you have contr
## Mirrors
- **GitHub Pages:** [privacyguides.github.io/privacyguides.org](https://privacyguides.github.io/privacyguides.org/en/)
- **Netlify (AWS):** [illustrious-bavarois-56cf30.netlify.app](https://illustrious-bavarois-56cf30.netlify.app/en/)
- **BunnyCDN:** [privacyguides-org-production.b-cdn.net](https://privacyguides-org-production.b-cdn.net/en/)
- **Hetzner:** [direct.privacyguides.org](https://direct.privacyguides.org/en/) (discouraged!)
### Alternative Networks
@@ -82,20 +90,10 @@ All contributors to the site are listed [here](#contributors). If you have contr
## License
Copyright &copy; 2019 - 2024 [Privacy Guides contributors](#contributors).
Privacy Guides content is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International Public License](/LICENSE), and the underlying source code used to format and display that content on [www.privacyguides.org](https://www.privacyguides.org) is licensed under the [MIT License](/LICENSE-CODE).
Generally speaking, **content** can be found in the [`/docs`](/docs), [`/theme/assets/img`](/theme/assets/img) and [`/includes`](/includes) folders; and **source code** and configuration files can be found in the [`/config`](/config) and [`/theme`](/theme) folders, and in the root of this repository. Any source code snippets contained within documentation files are [MIT Licensed](/LICENSE-CODE). Please contact us if you require clarification on any of these terms.
These licenses do not apply to any work where another license is otherwise noted.
**Logos** in the [`/theme/assets/img`](/theme/assets/img) folder may not be original works of Privacy Guides and therefore cannot be (re)licensed by us. We believe that these logos obtained from third-party providers are either in the public domain or **fair use**. In a nutshell, legal [fair use doctrine](https://copyright.gov/fair-use/more-info.html) allows the use of copyrighted images in order to identify the subject for purposes of public comment. However, these logos and other images may still be subject to trademark laws in one or more jurisdictions. Before using this content, please ensure that it is used to identify the entity or organization that owns the trademark and that you have the right to use it under the laws which apply in the circumstances of your intended use. *When copying content from this website, you are solely responsible for ensuring that you do not infringe someone else's trademark or copyright.*
This repository is [REUSE compliant](https://reuse.software/), meaning each file is individually annotated with copyright information. Typically, most content you would read on the site is [**CC BY-SA 4.0**](LICENSES/CC-BY-SA-4.0.txt). You must always check the copyright license information in each file you copy before using it in your own work. If you are confused about who owns the copyright for a particular file or what license it is available under, please email <jonah@privacyguides.org>.
You may comply with our license terms in any reasonable manner, but not in any way that suggests Privacy Guides endorses you or your use. You **may not** use the Privacy Guides branding in your own project without express approval from this project. Privacy Guides's brand trademarks include the "Privacy Guides" wordmark and shield logo.
When you contribute to this repository you are doing so under the above licenses, and you are granting Privacy Guides a perpetual, worldwide, non-exclusive, transferable, royalty-free, irrevocable license with the right to sublicense such rights through multiple tiers of sublicensees, to reproduce, modify, display, perform and distribute your contribution as part of our project.
## Developing
The only supported method of building and previewing this website locally is by running the automatic dev container. The easiest way to do this in your web browser without installing any software is to use [GitHub Codespaces](https://codespaces.new/privacyguides/privacyguides.org). To build the website locally, you will need the following software:
@@ -115,7 +113,7 @@ Committing to this repository requires [signing your commits](https://docs.githu
It is required to create a GitHub release to publish the current site to privacyguides.org. The current `main` branch can be previewed at [https://main.staging.privacyguides.dev](https://main.staging.privacyguides.dev) prior to release.
1. Create a new tag: `git tag -s YYYY.MM.DD -m 'Some message'`
- Tag numbering: `YYYY.MM.DD` - if two+ releases are published on the same day, append short commit to the next release, e.g. `YYYY.MM.DD-6aa14e8`
- Tag numbering: `YYYY.MM.DD` - if two+ releases are published on the same day, append short commit sha to next release, e.g. `YYYY.MM.DD-6aa14e8`
- Enable GPG tag signing by default (`git config tag.gpgSign true`) to avoid missing signatures
2. Push the tag to GitHub: `git push --tags`
3. A GitHub Release will be automatically created and deployed to the live site.
@@ -612,7 +610,7 @@ Privacy Guides wouldn't be possible without these wonderful people ([emoji key](
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of **any** kind welcome, including contributions to Privacy Guides outside this repo, and contributions that aren't content related (like sharing ideas for Privacy Guides, promoting the project, answering questions on the forum, etc.).
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of **any** kind welcome, including contributions to Privacy Guides outside of this repo, and contributions that aren't content related (like sharing ideas for Privacy Guides, promoting the project, answering questions on the forum, etc.).
CLI to generate this table:

70
REUSE.toml Normal file
View File

@@ -0,0 +1,70 @@
version = 1
# Computer-generated files and other files which cannot be copyrighted
[[annotations]]
path = [
".all-contributorsrc",
".allowed_signers",
".gitmodules",
".mailmap",
".python-version",
"Pipfile.lock",
".vscode/.empty-schema.json",
".vscode/ltex.dictionary.en-US.txt",
".vscode/ltex.hiddenFalsePositives.en-US.txt",
"blog/tags.md",
"includes/contributors.md",
"videos/playlists.md"
]
precedence = "override"
SPDX-FileCopyrightText = "NONE"
SPDX-License-Identifier = "CC0-1.0"
# Privacy Guides Paid Work - Fria
[[annotations]]
path = [
"blog/assets/images/digital-provenance/*",
"blog/assets/images/privacy-pass/*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Fria <fria@privacyguides.org>"
# Privacy Guides Paid Work - Kevin
[[annotations]]
path = [
"blog/assets/images/clearing-your-browsing-data/*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Kevin Pham <kevin@privacyguides.org>"
# Privacy Guides Paid Work - Jordan
[[annotations]]
path = [
"videos/posts/**"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = [
"Jordan Warne <jordan@privacyguides.org>",
"Jonah Aragon <jonah@privacyguides.org>"
]
# 2024 Jonah Aragon
[[annotations]]
path = [
"includes/strings.en.env"
]
precedence = "aggregate"
SPDX-FileCopyrightText = "2024 Jonah Aragon <jonah@privacyguides.org>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
# Fair Use / Copyrighted Logos
[[annotations]]
path = [
"theme/assets/img/**"
]
SPDX-FileCopyrightText = "NOASSERTION"
SPDX-License-Identifier = "LicenseRef-FairUse"
SPDX-LicenseComments = "This is a copyrighted and/or trademarked logo we are using under fair use. Your usage rights of this file outside Privacy Guides may vary."

View File

@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: MIT OR CC-BY-SA-4.0
authors:
aprilfools:
name: Anita Key
@@ -86,10 +90,6 @@ authors:
mastodon:
username: blacklight447
instance: mastodon.social
ptrmdn:
name: Peter Marsden
description: Guest Contributor
avatar: https://forum-cdn.privacyguides.net/user_avatar/discuss.privacyguides.net/ptrmdn/288/14291_2.png
sam-howell:
name: Sam Howell
description: Guest Contributor

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# 2019
!!! danger "Old Content"

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# 2020
!!! danger "Old Content"

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# 2021
!!! danger "Old Content"

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# 2022
!!! danger "Old Content"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,5 @@
SPDX-FileCopyrightText: Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-FairUse
SPDX-FileComment: This file contains the Mastodon logo, which is used under fair use.
SPDX-FileContributor: Mastodon gGmbH <https://joinmastodon.org/>

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -0,0 +1,7 @@
SPDX-FileCopyrightText: Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-FairUse
SPDX-FileComment: Mastodon mascot by @dopatwo@mastodon.social and Mastodon logo used with permission from Mastodon gGmbH. This site is not otherwise affiliated with Mastodon gGmbH.
SPDX-FileContributor: Em <em@privacyguides.org>
SPDX-FileContributor: dopatwo <https://mastodon.social/@dopatwo>
SPDX-FileContributor: Mastodon gGmbH <https://joinmastodon.org/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 891 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

View File

@@ -0,0 +1,10 @@
version = 1
# Privacy Guides Paid Work - Em
[[annotations]]
path = [
"*"
]
SPDX-FileCopyrightText = "Privacy Guides <https://magicgrants.org/funds/privacy_guides/>"
SPDX-License-Identifier = "CC-BY-SA-4.0"
SPDX-FileContributor = "Em <em@privacyguides.org>"

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2025 Freddy <freddy@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# Daniel Gray
![Profile picture](https://github.com/dngray.png){ align=right }

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: Em is a full-time journalist at Privacy Guides.
schema:
-

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2025 Freddy <freddy@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# Freddy
![Profile picture](https://github.com/freddy-m.png){ align=right }

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: Jonah Aragon is the Project Director and staff writer at Privacy Guides. His role includes researching and writing for this website, system administration, creating Privacy Guides Online Learning course content, reviewing the products recommended here, and most other day-to-day tasks.
schema:
-

View File

@@ -1,3 +1,9 @@
<!--
SPDX-FileCopyrightText: 2024 Niek de Wilde <niek@privacyguides.org>
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# Niek de Wilde
![Profile picture](https://github.com/blacklight447.png){ align=right }

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: The latest announcements and updates from the Privacy Guides team.
---

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: Privacy Guides News presents the latest tech news about the world's best (and occasionally worst) software, hardware, and services in the privacy world.
---

View File

@@ -1,7 +1,10 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: Read the latest privacy product reviews and stories from Privacy Guides contributing writers.
---
# Reviews
Looking for alternatives to privacy-invasive apps you use everyday? Do you just want to know all the details behind your favorite privacy tools? *Privacy Guides Reviews* is the place to find all that and more. This is your one stop to find the latest advice and recommendations on things we use every day directly from Privacy Guides contributors.
Looking for alternatives to privacy-invasive apps you use every day? Do you just want to know all the details behind your favorite privacy tools? *Privacy Guides Reviews* is the place to find all that and more. This is your one stop to find the latest advice and recommendations on things we use every day directly from Privacy Guides contributors.

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
title: Editorial Policy
---

View File

@@ -1,6 +1,9 @@
---
# SPDX-FileCopyrightText: 2024 Jonah Aragon <jonah@privacyguides.org>
# SPDX-FileCopyrightText: 2024 Daniel Gray <dngray@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
description: Privacy-related news stories, product reviews, opinion pieces, and other important articles from Privacy Guides contributors.
canonical_url: https://www.privacyguides.org/posts/tag/articles/
hide:
- footer
---

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Jonah Aragon <jonah@privacyguides.org>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-01-23T19:15:00Z
updated: 2025-01-27T20:00:00Z

View File

@@ -1,11 +1,14 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-05-06T21:45:00Z
categories:
- News
authors:
- em
description: Age verification laws forcing platforms to restrict access to content online have been multiplying in recent years. The problem is, implementing such measure necessarily requires identifying each user accessing this content, one way or another. This is bad news for your privacy.
description: Age verification laws and propositions forcing platforms to restrict content accessed by children and teens have been multiplying in recent years. The problem is, implementing such measure necessarily requires identifying each user accessing this content, one way or another. This is bad news for your privacy.
schema_type: AnalysisNewsArticle
preview:
cover: blog/assets/images/age-verification-wants-your-face/ageverification-cover.webp

View File

@@ -1,313 +0,0 @@
---
date:
created: 2025-09-08T18:00:00Z
updated: 2025-09-15T16:30:00Z
categories:
- News
authors:
- em
description:
Chat Control is back to undermine everyone's privacy. There's an important deadline on October 14th, 2025. We must act now to stop it!
schema_type: ReportageNewsArticle
preview:
cover: blog/assets/images/chat-control-must-be-stopped/chatcontrol-cover.webp
---
# Chat Control Must Be Stopped, Act Now!
![Filtered photo of a protest with a protestor holding a sign in first plan. The background is a red monochrome and the sign is in turquoise. The sign says "You won't make me live this 1984 sh*t".](../assets/images/chat-control-must-be-stopped/chatcontrol-cover.webp)
<small aria-hidden="true">Illustration: Em / Privacy Guides | Photo: Ramaz Bluashvili / Pexels</small>
If you've heard of [Chat Control](the-future-of-privacy.md) already, bad news: **it's back**. If you haven't, this is a pressing issue you should urgently learn more about if you value privacy, democracy, and human rights. This is happening **right now**, and **we must act to stop it right now**.<!-- more -->
Take a minute to visualize this: Every morning you wake up with a police officer entering your home to inspect it, and staying with you all day long.
The agent checks your bathroom, your medicine cabinet, your bedroom, your closets, your drawers, your fridge, and takes photos and notes to document everything. Then, this report is uploaded to the police's cloud. It's "[for a good cause](encryption-is-not-a-crime.md)" you know, it's to make sure you aren't hiding any child sexual abuse material under your bed.
Every morning. Even if you're naked in bed. Even while you're having a call with your doctor or your lover. Even when you're on a date. Even while you're working and discussing your client's confidential information with their attorney. This police officer is there, listening to you and reporting on everything you do.
This is the in-person equivalent of Chat Control, a piece of legislation that would mandate **all** services to scan **all** private digital communications of **everyone** residing in the European Union.
This is an Orwellian nightmare.
## Act now!
This is happening **right now**. European governments will be finalizing their positions on the regulation proposal on September 12th, and there will be a final vote on **October 14th, 2025**.
<div class="admonition warning" markdown>
<p class="admonition-title">Important: If you are reading this article after September 12th</p>
Regardless of the outcome on September 12th, the fight isn't over. The next deadline will be the **final vote on October 14th, 2025**.
If you've missed September 12th, make sure to contact your representatives **right now** to tell them to **oppose Chat Control** on October 14th.
</div>
- ==If you are not located in Europe==: Keep reading, this will affect you too.
- If you are still unconvinced: Keep reading, we discuss Chat Control in [more details](#why-is-this-bad) below.
- If you are located in Europe: You must **act now** to stop it.
<div class="admonition question" markdown>
<p class="admonition-title">How to stop this? Contact your MEPs today</p>
Use this [**website**](https://fightchatcontrol.eu/) to easily contact your government representatives, and tell them they should **oppose Chat Control**. Even if your country already opposes Chat Control, contact your representatives to tell them you are relieved they oppose, and support them in this decision to protect human rights. This will help reinforce their position.
But if your country *supports* Chat Control, or is *undecided*, **it is vital that you contact your representatives as soon as possible**. To support your point, you can share this article with them or one of the many great [resources](#resources-to-learn-more-and-fight-for-human-rights) listed at the end.
At the time of this writing, the list of countries to contact is:
| **Supporting (15)** | | **Undecided (6)** |
| ---------------------------------- | ----------------------------------- | -------------------- |
| :triangular_flag_on_post: Bulgaria | :triangular_flag_on_post: Latvia | :warning: Estonia |
| :triangular_flag_on_post: Croatia | :triangular_flag_on_post: Lithuania | :warning: Germany |
| :triangular_flag_on_post: Cyprus | :triangular_flag_on_post: Malta | :warning: Greece |
| :triangular_flag_on_post: Denmark | :triangular_flag_on_post: Portugal | :warning: Luxembourg |
| :triangular_flag_on_post: France | :triangular_flag_on_post: Slovakia | :warning: Romania |
| :triangular_flag_on_post: Hungary | :triangular_flag_on_post: Spain | :warning: Slovenia |
| :triangular_flag_on_post: Ireland | :triangular_flag_on_post: Sweden | |
| :triangular_flag_on_post: Italy | | |
</div>
![A map of countries part of the European Union. Countries opposing Chat Control are represented in green, countries undecided in blue, and countries in favor are in red. Below there is text saying "Act now! www.chatcontrol.eu".](../assets/images/chat-control-must-be-stopped/chatcontrol-map-chatcontroleu-20250903.webp)
<small aria-hidden="true">Image: Patrick Breyer / [chatcontrol.eu](https://www.chatcontrol.eu)</small>
## What is Chat Control?
"Chat Control" refers to a series of legislative proposals that would make it mandatory for *all* service providers (text messaging, email, social media, cloud storage, hosting services, etc.) to scan *all* communications and *all* files (including end-to-end encrypted ones), in order to supposedly detect whatever the government deems "abusive material."
The push for Chat Control started in 2021 with the approval of a [derogation](https://www.patrick-breyer.de/en/chatcontrol-european-parliament-approves-mass-surveillance-of-private-communications/) to the ePrivacy Directive by the European Parliament. This derogation escalated to a second proposal for *mandatory* scanning a year later, which was [rejected](https://fortune.com/europe/2023/10/26/eu-chat-control-csam-encryption-privacy-european-commission-parliament-johansson-breyer-zarzalejos-ernst/) in 2023. Nevertheless, lawmakers and lobbyists determined to undermine our safety and civil liberties are bringing it back again two years later, **literally trying to wear you down**.
We cannot let authoritarians wear us down until we lose all our privacy rights. Our privacy rights are fundamental to so many other human rights, to civil liberties, to public safety, and to functioning democracies.
Chat Control undermines all of this.
Cryptography professor and cybersecurity expert Matthew Green described the 2022 proposal document for Chat Control as "[**the most terrifying thing I've ever seen**](https://fortune.com/2022/05/12/europe-phone-surveillance-crackdown-child-sexual-abuse-material-sparks-outrage-among-cybersecurity-experts-privacy-activists/)".
And terrifying, it is.
The [most recent proposal for Chat Control](https://tuta.com/blog/chat-control-criticism) comes from the EU Council Danish presidency pushing for regulation misleadingly called the **Child Sexual Abuse Regulation** (CSAR). Despite its seemingly caring name, this regulation will **not** help fight child abuse, and will even likely worsen it, impacting negatively what is already being done to fight child abuse (more on this in the [next section](#would-this-protect-the-children)).
The CSAR proposal (which *is* the latest iteration of Chat Control) could be implemented as early as *next month*, if we do not stop it.
**The problem is this: Chat Control will not work, it is unreliable, it will escalate in scope, and it will endanger everyone (including the children).**
Even if you are not in Europe, know that Chat Control will affect everyone inside *and* outside of Europe one way or another. Regardless of where you are, you should be concerned and pay attention, and there are things you can do to fight back. This is important.
![Still image from a video showing an illustration of three cellphones being scanned by a red light, with lines leading to a law enforcement icon.](../assets/images/chat-control-must-be-stopped/chatcontrol-stopscanningme-video.webp)
<small aria-hidden="true">Still image from [video](https://stopscanningme.eu/video/csar-explainer.mp4): Stop Scanning Me / EDRi</small>
## Why is this bad?
The idea that it's possible to somehow [magically protect](encryption-is-not-a-crime.md/#magical-backdoor-only-for-the-good-guys-is-a-complete-fantasy) information properly while giving access to unquestionably well-intended law enforcement comes from either extreme naivety, lack of information, and plain dishonesty.
This proposal would effectively break any end-to-end encryption protections, and potentially expose all your files and communications to not only law enforcement, but eventually also to criminals of all sorts (with the data breaches, data leaks, and corruption that will inevitably follow).
Here's a summary of some dangers this regulation would create if approved:
- **Breaking end-to-end encryption**: Removing crucial protections for all sensitive files and communications of vulnerable populations, victims, whistleblowers, journalists, activists, and everyone else.
- **Mission creep**: Once this mass surveillance system is in place, authorities can decide to add more criteria such as searching all communications for references to drug use, protest attendances, political dissidence, or even [negative comments](https://www.lemonde.fr/en/international/article/2025/03/22/how-a-french-researcher-being-refused-entry-to-the-us-turned-into-a-diplomatic-mess_6739415_4.html) about a leader. Europol (the EU law enforcement agency) has already called for [expanding the program](https://www.youtube.com/watch?v=L933xDcSS3o&t=2016s).
![A cartoon illustration explaining that chat control is planning to monitor all chats, emails, and messenger conversations, and use artificial intelligence to automatically report flagged content to the police.](../assets/images/chat-control-must-be-stopped/chatcontrol-LornaSchutte-chatcontroleu-1.webp)
<small aria-hidden="true">Image: Lorna Schütte / [chatcontrol.eu](https://www.chatcontrol.eu)</small>
- **Criminal attacks**: Each time a backdoor exists, it doesn't take long for criminals to find access and steal our information. This could include criminals finding access to each service independently or to the entire database authorities would keep. A database that would be filled with material tagged as sexually explicit text or photos of children. This could even *create* new Child Sexual Abuse Material (CSAM) for criminals. For example, consenting teenagers innocently sexting together could have their photos collected in this database, after being wrongly flagged by the automated system. Then, criminals could steal their intimate photos from the governments.
- **False positives**: With a mass surveillance system this large, moreover a system with no transparency and little oversight, false positives are inevitable. Despite marketing promises from the [organizations lobbying government officials](https://www.patrick-breyer.de/en/chat-control-eu-ombudsman-criticises-revolving-door-between-europol-and-chat-control-tech-lobbyist-thorn/), we all know AI technologies regularly misfire and cannot be reliable for anything of such importance. Loving parents could get flagged as pedophiles just for innocently uploading a photo of their child in the bathtub on their *private* cloud. Teenagers exploring their sexuality consensually with each other could get tagged as sexual predators (a label that might stick on them decades later). The police could receive reports for breastfeeding mothers. The list is infinite.
![A cartoon illustration summarizing why chat control is dangerous.](../assets/images/chat-control-must-be-stopped/chatcontrol-LornaSchutte-chatcontroleu-3.webp)
<small aria-hidden="true">Image: Lorna Schütte / [chatcontrol.eu](https://www.chatcontrol.eu)</small>
- **Overwhelming resources**: The inevitable false positives will completely overwhelm the agencies responsible for investigating flagged material. This will cost them precious time they will not have to investigate *actual* abuse cases. Organizations fighting child sexual abuse are already overwhelmed and lack resources to prosecute real criminals.
- **Hurting victims**: Such system of mass surveillance could prevent victims of child sexual abuse (and other crimes) to reach out for help. Knowing that all their communications would be scanned, they would lose all confidentiality while reporting crimes. The evidences they share could even be tagged by Chat Control, as if they were the perpetrator rather than the victim. Sadly, many will likely decide it's safer not to report at all.
- **Self-censorship**: With Chat Control in place, not only victims might censor themselves and stop reaching out for help, but everyone else as well. When people know they are being observed, they feel less free to be themselves and to share openly. This is doubly true for anyone who is part of a marginalized group, such as [LGBTQ+ people](importance-of-privacy-for-the-queer-community.md), or anyone who is being victimized or at risk of victimization.
![A cartoon illustration explaining how chat control does not protect the victims and might silence them due to loss of confidentiality.](../assets/images/chat-control-must-be-stopped/chatcontrol-LornaSchutte-chatcontroleu-2.webp)
<small aria-hidden="true">Image: Lorna Schütte / [chatcontrol.eu](https://www.chatcontrol.eu)</small>
- **Undermining democracy**: This surveillance system would allow governments to spy on opposition. Chat logs from opposing candidates, activists, and journalists could all be accessed by authorities in order to silence opponents or blackmail candidates. Even if you trust your government to not do this now, this doesn't mean it could not be used in this way by the next government. We have all seen how fast the political landscape can change.
- **Violating the GDPR (and other laws)**: The General Data Protection Regulation (GDPR) offers wonderful protections to Europeans. Sadly, Chat Control would make a complete farce of it. The Right to Erasure (right to delete) could be reduced to ashes by Chat Control, including for any highly sensitive information wrongly caught in the CSAR net. Moreover, it would [violate Article 7 and Article 8](https://tuta.com/blog/chat-control-criticism) of the EU Charter of Fundamental Rights.
Protecting the children is only the excuse used in hope of convincing a misinformed public. **Chat Control is authoritarian mass surveillance.**
Authorities understand well how important protecting communication and information is. This is why they included an exemption to protect *their own* communications, but not yours.
## Would this protect the children?
No.
This cannot be stressed enough: **This regulation would not protect the children, it would *harm* the children**, and everyone else too, worldwide. Claiming otherwise is either naivety, or misinformation.
Last year, the civil and human rights association European Digital Rights (EDRi) put together a [joint statement from 48 organizations](https://edri.org/our-work/joint-statement-on-the-future-of-the-csa-regulation/) for children's protection, digital rights, and human rights, demanding that the European Parliament invest instead in proven strategies to fight child abuse. This appeal to reason does not seem to have been heard by most EU Member States.
There are many things we can do as a society to increase protections for children and fight abusers and criminals, but Chat Control is far from it all. Protection of the children is clearly only an excuse here, and a very misleading one.
![A popular No Yes meme, with the face replaced with the European Commission logo. In the No-part is: "Invest in: social workers, help for victims, support hotlines, prevention, education, targeted police work, IT-security", and in the Yes-part below is: "Buy Chat Control filter technology that doesn't solve the problem".](../assets/images/chat-control-must-be-stopped/chatcontrol-stopscanningme-meme-4.webp)
<small aria-hidden="true">[Image](https://stopscanningme.eu/en/organise-now.html): Stop Scanning Me / EDRi</small>
### Mislabelling children as criminals
First, this automated system is flawed in many ways, and the false-positive rate would likely be high. But let's imagine that, magically, the system could flag CSAM at an accuracy rate of 99%. This still means 1% of reports would be false. Expanded to the size of European Union's population of approximately 450 million people, exchanging likely billions of messages and files every day, this still means millions could be falsely tagged as sexual predators, with all the [consequences](https://www.republik.ch/2022/12/08/die-dunklen-schatten-der-chatkontrolle) this implies.
Worse, the Swiss federal police reported that currently about 80% of all automated reports received were [false-positives](https://www.patrick-breyer.de/en/posts/chat-control/#WhatYouCanDo). This means in reality, the error rate is likely far higher than 1%, and actually closer to an **80% error rate**. Of the approximate 20% of positive reports, in Germany, over 40% of investigations initiated [targeted children](https://www.polizei-beratung.de/aktuelles/detailansicht/straftat-verbreitung-kinderpornografie-pks-2022/) themselves.
Sometimes, flagged content is simply teenagers innocently sexting each other consensually. Not only would they be wrongly tagged as criminals under Chat Control, but they'd be triggering an investigation that would expose their intimate photos to some faceless officers or tech employees working on the system.
Even in a magical world where Chat Control AI is 99% accurate, it would still wrongly tag and **expose sensitive data from millions of children**. In reality, no AI system is even remotely close to this accuracy level, and proprietary algorithms are usually opaque black boxes impossible to audit transparently. The number of children Chat Control would harm, and likely traumatize for life, would be disastrous.
### Exposing children's sensitive and sexual information
Any content that could be deemed suspicious or explicit by the system, accurately or not, would be flagged and reported.
When this content is reported, it will likely be uploaded to a database for human review. This means that if a teenager was sending an intimate photo of themselves to another consenting teenager, they could be flagged as sharing CSAM, even if it's their own photo. Then, their photo would be sent to the police for review. Information that should very much have stayed protected and private between these two teenagers is now exposed to strangers. This is wrong, and dangerous.
Even innocuous communications such as daily conversations, teenagers chatting with each other, parents reporting information about their child to a [doctor](https://www.nytimes.com/2022/08/21/technology/google-surveillance-toddler-photo.html), and therapists talking with their patients, could all inadvertently expose children sensitive information. This is information that should have remained *private*, and would now be uploaded to a police database, likely [stored there forever](https://www.iccl.ie/news/an-garda-siochana-unlawfully-retains-files-on-innocent-people-who-it-has-already-cleared-of-producing-or-sharing-of-child-sex-abuse-material/) with few recourses to remove it.
The more we collect sensitive information about children (photos, faces, locations, identifications, medical information, private chats, experiences, etc.), the more we risk exposing children to harm. This includes systems used by authorities and governments. Even if everyone with legitimate access to this data is miraculously 100% exemplary and incorruptible citizens, the databases and scanning systems will still be vulnerable to attacks from criminals and hostile governments alike.
The only way to protect children's information properly is to **1) not collect it**, and **2) use end-to-end encryption to protect it** when we cannot avoid collecting it. Spying on everyone and every child is the opposite of that.
### Authorities' databases will be attacked
It's impossible to perfectly secure information online. There is a lot we can do to improve security (much more than is done now), but data breaches will happen.
If governments mandate a backdoor to have access to all our online communication and stored files, it's inevitable that at least some criminals will eventually get access to it as well. This is even truer if this system is closed-source, [privatized](https://fortune.com/europe/2023/09/26/thorn-ashton-kutcher-ylva-johansson-csam-csa-regulation-european-commission-encryption-privacy-surveillance/), and isn't subjected to frequent independent audits with strong accountability.
Once a vulnerability is found by criminals, they will have the same access as authorities have to our data. With Chat Control, this means pretty much all our data.
In addition, Chat Control could facilitate the proliferation of even more spyware and [stalkerware](https://stopstalkerware.org/) on the market, thriving on the vulnerabilities found in the powerful system. This would allow *anyone* to purchase access to spy on *anyone*, including databases of identified children. It could give a direct backdoor-access to pedophiles. How could *this* be helping to protect the children?
### The danger is inside
Even if the idea of online strangers accessing children's sensitive data is terrifying, the worse danger in often much closer.
Sadly, we already know that the [vast majority](https://content.c3p.ca/pdfs/C3P_SurvivorsSurveyFullReport2017.pdf) of child sexual abuse is perpetrated by adults close to the child, not strangers, and that two-thirds of CSAM images appear to have been [produced at home](https://theconversation.com/new-research-shows-parents-are-major-producers-of-child-sexual-abuse-material-153722). Chat Control would do nothing to fight this. In fact, it could facilitate it.
Child abuse is an incredibly important topic to discuss and to fight against as a society. Utilizing this issue as an excuse to pass a surveillance law that would endanger everyone, including the victims, is despicable.
When children are living with the abuser, the only escape is outside the home, and sometimes this means *online*. Abusers often use spying technologies to control and restrict access to help for their victims. If we make mass surveillance mandatory and normalized, this risks aggravating the stalkerware problem by obligating providers to implement backdoors in their systems. We would effectively be helping abusers at home to restrict access to help for their victims, including victims of CSAM. This is completely unacceptable.
### How to actually help the children
Despite the politicization of this issue to manipulate the public opinion in accepting mass surveillance, there are actually *proven* solutions to help to protect the children, online and offline.
First, governments should [listen](https://mogis.info/static/media/uploads/eu-libe-mogis-hahne-07032023_en.pdf) to [organizations already doing the work](https://edri.org/our-work/most-criticised-eu-law-of-all-time/). Most are understaffed and under-resourced to properly support the victims and prosecute the criminals. Thousands of more reports every day would not help them do any effective work. More capacity to conduct *targeted* investigation and arrest criminals, and more capacity to create safe spaces to support the victims and witnesses will help.
Privacy should be the default, for everyone.
If all our services were using end-to-end encryption when possible, and implemented proper security and privacy features and practices, this would effectively help to protect the children as well. Abusers and criminals are looking for leaked and stolen data all the time. When a cloud photo storage gets hacked, your photos are up for grabs online, including the photos of your children. When parents upload photos of their children and their address online, and this data gets exposed (leaked, breached, AI-scraped, etc.), this data then becomes accessible to criminals.
**Better privacy protections also means better protections for the children.**
Children themselves should receive better education on how their data is used online and how to protect it. Additionally, it is vital to provide better education on what behaviors aren't normal coming from an adult, and how to reach out for help when it happens. Children should have access to safe and confidential resources to report abuse, whether it's happening outside or inside their home.
Parents should be careful when sharing information about their children. And when they have to, they should benefit from complete confidentiality, knowing their communication is fully end-to-end encrypted and not shared with anyone else.
There is so much we can do to help to protect better the children online, surveillance is the opposite of it all.
## How would this affect me?
If this regulation is approved on **October 14th, 2025** (the date for the final vote), the consequences would be devastating for everyone, even outside the European Union.
We have seen how platforms implemented better privacy practices and features after the GDPR became effective in 2018, features that often benefited people worldwide. This could have the same effect in reverse.
Every platform potentially handling data of people located in the EU would be subjected to the law. Platforms would be obligated to scan all communications and all files of (at least) data subjects located in the EU, even data currently protected with end-to-end encryption. This would affect popular apps and services like Signal, Tuta, Proton, WhatsApp, Telegram, and much more.
### Outside of Europe
This would not only affect Europeans' data, but also the data of anyone outside communicating with someone located in the European Union. Because end-to-end encryption can only work if **both** ends are protected.
If Chat Control gets approved and applied, it will become very difficult to communicate with anyone located in the EU while keeping strong protections for your data. Many people might just accept the surveillance passively, and as a result lose their rights, their protections, and compromise their democratic processes. Overtime, this will likely lead to a slippery slope towards dystopian authoritarianism.
Outside of Europe, you could expect to see services removing some privacy-protective features, downgrading encryption, blocking European countries that are subjected to the law, or moving outside of Europe entirely. If localization-based scanning is too complicated to handle for an application, some companies might just decide it's simpler to scan communications for all users, worldwide.
Additionally, Five Eyes countries (Australia, Canada, New Zealand, the United Kingdom, and the United States) have already [expressed support](https://www.youtube.com/watch?v=L933xDcSS3o&t=2163s) for Chat Control, and might be keen to try the same at home, if this gets approved and tested in Europe first.
### Inside of Europe
Without using tools that would be now deemed illegal, you would lose any protections currently granted by end-to-end encryption. It would become impossible for you to send an email, a text message, or a photo without being observed by your government, and potentially also by criminals and foreign governments, following the inevitable data breaches.
You would have to constantly self-censor to avoid triggering the system and getting reported to the authorities. At first, you would probably just have to stop sending nudes, sexting, or sending photos of naked children in the bathtub or playing at the beach. Then, this would escalate to never mentioning drug or anything that could sound like drug, even as a joke. Later, you might have to stop texting about going to a protest, and stop organizing protests online. Further down the line, you might even have to self-censor to make sure you are not saying anything negative about a leader, or a [foreign politician](https://www.reuters.com/world/us/trump-administration-resuming-student-visa-appointments-state-dept-official-says-2025-06-18/) even. This isn't that hypothetical, this sort of [oppressive surveillance](https://www.hrw.org/news/2017/11/19/china-police-big-data-systems-violate-privacy-target-dissent) already exists in some countries.
Many services you currently rely on right now would simply shut down, or move away from Europe entirely. Businesses might also move outside of Europe if they worry about protecting their proprietary information. This could cause massive layoffs, while organizations move to jurisdictions where they are allowed to keep their data protected and unobserved.
Finally, even if this doesn't affect you personally, or you don't believe it will, [**this isn't just about you**](the-privacy-of-others.md).
The data of vulnerable people would be exposed and their safety put at risk. Victims might decide to stop reaching out for help or reporting crimes. Sources requiring anonymity might decide the risk isn't worth reporting valuable information to journalists. Opponents of governments in power could be silenced. Every democracy in the European Union would suffer greatly from it.
Chat Control is completely antithetical to the values the European Union has been presenting to the world in recent years.
![The popular Red Dress meme, with the offended woman overlaid with the words "Fundamental Rights", the whistling man the words "European Commission", and woman wearing the red dress the words "Scanning private messages and controlling how citizens use the internet".](../assets/images/chat-control-must-be-stopped/chatcontrol-stopscanningme-meme-2.webp)
<small aria-hidden="true">[Image](https://stopscanningme.eu/en/organise-now.html): Stop Scanning Me / EDRi</small>
## What can I do about it?
Even if the landscape seems dismal, **the battle isn't over**. There are many things you can do, right now, to fight against this authoritarian dystopia.
### For Europeans, specifically
- Contact your country representatives **TODAY**. The group Fight Chat Control has put together an [**easy tool**](https://fightchatcontrol.eu/#contact-tool) making this quick with only a few clicks.
- After September 12th, the battle isn't over. Although governments will finalize their positions on that day, the final vote happens on **October 14th, 2025**. If you missed the September 12th deadline, keep contacting your representatives anyway.
- Tell your family and friends to contact their representatives as well, talk about it, make noise.
### For Everyone, including Europeans
- Talk about Chat Control on social media often, especially this month. Make noise online. Use the hashtags #ChatControl and #StopScanningMe to help others learn more about the opposition movement.
- Share informative [videos and memes](#resources-to-learn-more-and-fight-for-human-rights) about Chat Control. Spread the word in various forms.
- Contact your European friends in impacted countries and tell them to contact their representatives NOW.
- Even outside the EU, you can contact your own representatives as well, to let them know regulations like Chat Control are horrible for human rights, and you hope your country will never fall for such repressive laws. Tell your political representatives that privacy rights are important to you. **Your voice matters.**
We need your help to fight this. For democracy, for privacy, and for all other human rights, we cannot afford to lose this battle.
![Screenshot of the Fight Chat Control website in a browser.](../assets/images/chat-control-must-be-stopped/chatcontrol-fightchatcontrol-website.webp)
<small aria-hidden="true">Screenshot: [fightchatcontrol.eu](https://fightchatcontrol.eu/)</small>
## Resources to learn more, and fight for human rights
### Videos about Chat Control
- [**Stop Scanning Me**: Short video that summarizes perfectly the issues with Chat Control](https://stopscanningme.eu/video/csar-explainer.mp4)
- [**Stop Scanning Me**: German-language version of the same short video](https://www.patrick-breyer.de/posts/chat-control/)
- [**Louis Rossmann**: Video discussing why privacy matters, and the impact of Chat Control from a perspective outside of Europe](https://www.youtube.com/watch?v=3NyUgv6dpJc)
- [**Shaping Opinion**: Excellent interview with Chat Control expert Patrick Breyer (recommended)](https://www.youtube.com/watch?v=L933xDcSS3o)
- [**Patrick Breyer**: PeerTube channel with numerous videos related to Chat Control (German & English)](https://peertube.european-pirates.eu/c/patrick_breyer_mep_channel)
### Memes about Chat Control
- [**Stop Scanning Me**: Memes, banners, and other graphics](https://stopscanningme.eu/en/organise-now.html)
- [**Patrick Breyer**: Memes, explainers, maps, and other graphics](https://www.patrick-breyer.de/posts/chat-control/#WhatYouCanDo)
### Websites with more information
- [**Fight Chat Control** (Contact your representatives here **TODAY**!)](https://fightchatcontrol.eu/)
- [**Stop Scanning Me** (from EDRi)](https://stopscanningme.eu)
- [**Patrick Breyer** (expert and former Member of the European Parliament)](https://www.patrick-breyer.de/posts/chat-control/)
- [**European Crypto Initiative**](https://eu.ci/eu-chat-control-regulation/)
- [Follow **Fight Chat Control** on Mastodon for updates](https://mastodon.social/@chatcontrol)
---
**Update (9/15):** Added modifications related to the second important deadline for action, on October 14th.
**Update (9/8):** Added clarification about what Chat Control is for readers unfamiliar with it.

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-02-13T21:00:00Z
categories:

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
title: "CryptPad Review: Replacing Google Docs"
template: review-article.html
schema_type: ReviewNewsArticle
@@ -9,7 +12,7 @@ categories:
- Reviews
authors:
- em
description: If you've been looking for a privacy-respectful replacement to Google Docs, now is the time to switch to the end-to-end encrypted office suite CryptPad.
description: "If you have been looking for a privacy-respectful replacement to Google Docs, now is the time to switch to the end-to-end encrypted office suite CryptPad."
preview:
logo: theme/assets/img/document-collaboration/cryptpad.svg
review:

View File

@@ -1,250 +0,0 @@
---
date:
created: 2025-09-30T16:30:00Z
categories:
- Explainers
authors:
- fria
tags:
- Privacy Enhancing Technologies
schema_type: BackgroundNewsArticle
description: Differential privacy is a mathematically rigorous framework for adding a controlled amount of noise to a dataset so that no individual can be reidentified. Learn how this technology is being implemented to protect you.
preview:
cover: blog/assets/images/differential-privacy/cover.webp
---
# What is Differential Privacy?
!["Differential Privacy" text with a series of ones and zeros being obscured with a blur filter](../assets/images/differential-privacy/cover.webp)
<small aria-hidden="true">Image: Privacy Guides / Jordan Warne</small>
Is it possible to collect data from a large group of people but protect each individual's privacy? In this entry of my series on [privacy-enhancing technologies](../tags.md/#tag:privacy-enhancing-technologies), we'll discuss differential privacy and how it can do just that.<!-- more -->
## Problem
It's useful to collect data from a large group of people. You can see trends in a population. But it requires a lot of individual people to give up personally identifiable information. Even things that seem innocuous like your gender can help identify you.
Latanya Sweeney in a [paper](https://dataprivacylab.org/projects/identifiability/paper1.pdf) from 2000 used U.S. Census data to try and re-identify people solely based on the metrics available to her. She found that 87% of Americans could be identified based on only 3 metrics: ZIP code, date of birth, and sex.
Obviously, being able to identify individuals based on publicly available data is a huge privacy issue.
## History
### Before Differential Privacy
Being able to collect aggregate data is essential for research. It's what the U.S. Census does every 10 years.
Usually we're more interested in the data as a whole and not data of individual people as it can show trends and overall patterns in groups of people. However, in order to get that data we must collect it from individuals.
It was thought at first that simply [removing names and other obviously identifying details](https://simons.berkeley.edu/news/differential-privacy-issues-policymakers#:~:text=Prior%20to%20the%20line%20of%20research%20that%20led%20to%20differential%20privacy%2C%20it%20was%20widely%20believed%20that%20anonymizing%20data%20was%20a%20relatively%20straightforward%20and%20sufficient%20solution%20to%20the%20privacy%20challenge.%20Statistical%20aggregates%20could%20be%20released%2C%20many%20people%20thought%2C%20without%20revealing%20underlying%20personally%20identifiable%20data.%20Data%20sets%20could%20be%20released%20to%20researchers%20scrubbed%20of%20names%2C%20but%20otherwise%20with%20rich%20individual%20information%2C%20and%20were%20thought%20to%20have%20been%20anonymized.) from the data was enough to prevent re-identification, but [Latanya Sweeney](https://latanyasweeney.org/JLME.pdf) (a name that will pop up a few more times) proved in 1997 that even without names, a significant portion of individuals can be re-identified from a dataset by cross-referencing external data.
Previous attempts at anonymizing data have relied on been highly vulnerable to re-identification attacks.
#### AOL Search Log Release
A famous example is the AOL search log release. AOL had been logging its users searches for research purposes. When they released the data, they only replaced the users' real names with an identifier. Researchers were able to identify [user 4417749](https://archive.nytimes.com/www.nytimes.com/learning/teachers/featured_articles/20060810thursday.html) as Thelma Arnold based on the identifying details of her searches.
#### Strava Heatmap Incident
In 2018, the fitness app Strava announced a major update to its heatmap, showing the the workout patterns of users of fitness trackers like Fitbit.
Analyst [Nathan Ruser](https://x.com/Nrg8000/status/957318498102865920) indicated that these patterns can reveal military bases and troop movement patterns. This is obviously a huge op-sec problem and can endanger the lives of troops.
It was also possible to [deanonymize](https://steveloughran.blogspot.com/2018/01/advanced-denanonymization-through-strava.html) individual users in some circumstances.
#### Randomized Response
One of the earliest ideas for anonymizing data was [randomized response](https://uvammm.github.io/docs/randomizedresponse.pdf), first introduced all the way back in 1965 in a paper by Stanley L. Warner. The idea behind it is quite clever.
For certain questions like "have you committed tax fraud?" respondents will likely be hesitant to answer truthfully. The solution? Have the respondent flip a coin. If the coin is tails, answer yes. If the coin lands on heads, answer truthfully.
| Respondent | Answer | Coin Flip (not included in the actual dataset just here for illustration) |
| --- | --- | --- |
| 1 | Yes | Tails (Answer Yes) |
| 2 | No | Heads (Answer Truthfully) |
| 3 | Yes | Tails (Answer Yes) |
| 4 | Yes | Tails (Answer Yes) |
| 5| No | Heads (Answer Truthfully) |
Because we know the exact probability that a "Yes" answer is fake, 50%, we can remove it and give a rough estimate of how many respondents answered "Yes" truthfully.
Randomized Response would lay the groundwork for differential privacy, but it wouldn't truly be realized for many decades.
#### Unrelated Question Randomized Response
A variation used later in a [paper](https://www.jstor.org/stable/2283636) by Greenberg et al. called **unrelated question randomized response** would present each respondent with either a sensitive question or a banal question like "is your birthday in January?" to increase the likelihood of people answering honestly, since the researcher doesn't know which question was asked.
| Respondent | Question (not visible to researcher) | Answer |
| --- | --- | --- |
| 1 | Have you ever committed tax evasion? | No |
| 2 | Is your birthday in January? | Yes |
| 3 | Is your birthday in January? | No |
| 4 | Have you ever committed tax evasion? | Yes |
| 5 | Have you ever committed tax evasion? | No |
#### k-Anonymity
Latanya Sweeney and Pierangela Samarati introduced [k-anonymity](https://dataprivacylab.org/dataprivacy/projects/kanonymity/paper3.pdf) to the world back in 1998.
It's interesting that even all the way back in 1998 concerns constant data collection were already relevant.
> Most actions in daily life are recorded on some computer somewhere. That information in turn is often shared, exchanged, and sold. Many people may not care that the local grocer keeps track of which items they purchase, but shared information can be quite sensitive or damaging to individuals and organizations. Improper disclosure of medical information, financial information or matters of national security can have alarming ramifications, and many abuses have been cited.
In a dataset, you might have removed names and other obviously identifying information, but there might be other data such as birthday, ZIP code, etc., that might be unique to one person in the dataset. If someone were to cross-reference this data with outside data, it could be possible to deanonymize individuals.
k-anonymity means that for each row, at least k-1 other rows are identical. So for a k of 2, at least one other row is identical to each row.
##### Generalization
This is achieved through a few techniques, one of which is generalization. Generalization is reducing the precision of data so that it's not as unique.
For example, instead of recording an exact age, you might give a range like 20-30. You've probably noticed this on surveys you've taken before. Data like this that's not directly identifiable but could be used to re-identify someone is referred to as *quasi-identifiers*.
##### Suppression
Sometimes even with generalization, you might have outliers that don't satisfy the k-anonymity requirements.
In these cases, you can simply remove the row entirely.
##### Attacks on k-Anonymity
k-anonymity has been [demonstrated](https://www.usenix.org/system/files/sec22-cohen.pdf) to not prevent re-identification of individuals despite the data in a dataset being properly k-anonymized by "statistical experts".
Researchers were able to deanonymize 3 students from a k-anonymized dataset from Harvard and MIT's EdX platform by cross-referencing data from LinkedIn, putting potentially thousands of students at risk of re-identification.
### Dawn of Differential Privacy
Most of the concepts I write about seem to come from the 70s and 80s, but differential privacy is a relatively new concept. It was first introduced in a paper from 2006 called [*Calibrating Noise to Sensitivity in Private Data Analysis*](https://desfontain.es/PDFs/PhD/CalibratingNoiseToSensitivityInPrivateDataAnalysis.pdf).
The paper introduces the idea of adding noise to data to achieve privacy, similar to randomized response. However, differential privacy is much more mathematically rigorous and provable.
Of course, adding noise to the dataset reduces its accuracy. Ɛ defines the amount of noise added to the dataset, with a small Ɛ meaning more privacy but less accurate data and vice versa. It's also referred to as the "privacy loss parameter" or "privacy budget".
#### Central Differential Privacy
This early form of differential privacy relied on adding noise to the data *after* it was already collected, meaning you still have to trust a central authority with the raw data.
## Google RAPPOR
In 2014, Google introduced [Randomized Aggregatable Privacy-Preserving Ordinal Response](https://arxiv.org/pdf/1407.6981) (RAPPOR), their [open source](https://github.com/google/rappor) implementation of differential privacy.
Google RAPPOR implements and builds on previous techniques such as randomized response and adds significant improvements on top.
### Local Differential Privacy
In Google's implementation, noise is added to data on-device before it's sent off to any server. This removes the need to trust the central authority to handle your raw data, an important step in achieving truly anonymous data collection.
### Bloom Filters
Google RAPPOR makes use of a clever technique called bloom filters that saves space and improves privacy.
Bloom filters work by starting out with an array of all 0's
`[0, 0, 0, 0, 0, 0, 0, 0, 0]`
Then, you run data such as the word "apple" through a hashing algorithm, which will give 1's in specific positions, say position 1, 3, and 5.
`[0, 1, 0, 1, 0, 1, 0, 0, 0]`
When you want to check if data is present, you run the data through the hashing algorithm and check if the corresponding positions are 1's. If they are, the data *might* be present (other data might have flipped those same bits at some point). If any of the 1's are 0's, then you know for sure that the data is not in the set.
### Permanent Randomized Response
A randomization step is performed flipping some of the bits randomly. This response is then "memoized" so that the same random values are used for future reporting. This protects against an "averaging" attack where an attacker sees multiple responses from the same user and can eventually recover the real value by averaging them out over time.
### Instantaneous Randomized Response
On top of the permanent randomized data, another randomization step is performed. This time, different randomness is added on top of the permanent randomness so that every response sent is unique. This prevents an attacker from determining a user from seeing the same randomized pattern over and over again.
Both the permanent and instantaneous randomized response steps can be fine-tuned to for the desired privacy.
### Chrome
Google first used differential privacy in their Chrome browser for detection of [malware](https://blog.chromium.org/2014/10/learning-statistics-with-privacy-aided.html).
Differential privacy is also used in Google's [Privacy Sandbox](https://privacysandbox.google.com/private-advertising/aggregation-service/privacy-protection-report-strategy).
### Maps
Google Maps uses DP for its [place busyness](https://safety.google/privacy/data/#:~:text=To%20offer%20features%20like%20place%20busyness%20in%20Maps%2C%20we%20apply%20an%20advanced%20anonymization%20technology%20called%20differential%20privacy%20that%20adds%20noise%20to%20your%20information%20so%20it%20can%E2%80%99t%20be%20used%20to%20personally%20identify%20you.) feature, allowing Maps to show you how busy an area is without revealing the movements of individual people.
### Google Fi
[Google Fi](https://opensource.googleblog.com/2019/09/enabling-developers-and-organizations.html) uses differential privacy as well to improve the service.
## OpenDP
[OpenDP](https://opendp.org) is a community effort to build open source and trustworthy tools for differential privacy. Their members consist of academics from prestigious universities like Harvard and employees at companies like Microsoft.
There's been an effort from everyone to make differential privacy implementations open source, which is a breath of fresh air from companies that typically stick to closed source for their products.
## Apple
[Apple](https://www.apple.com/privacy/docs/Differential_Privacy_Overview.pdf) uses local differential privacy for much of its services, similar to what Google does. They add noise before sending any data off device, enabling them to collect aggregate data without harming the privacy of any individual user.
They limit the number of contributions any one user can make via a *privacy budget* (this is the same as Ɛ) so you won't have to worry about your own contributions being averaged out over time and revealing your own trends.
This allows them to find new words that people use that aren't included by default in the dictionary, or find which emojis are the most popular.
Some of the things they use differential privacy for include
- QuickType suggestions
- Emoji suggestions
- Lookup Hints
- Safari Energy Draining Domains
- Safari Autoplay Intent Detection
- Safari Crashing Domains
- Health Type Usage
That's just based on their initial white paper, they've likely increased their use of DP since then.
### Sketch Matrix
Apple uses a similar method to Google, with a matrix initialized with all zeros. The input for the matrix is encoded with the SHA-256 hashing algorithm, and then bits are flipped randomly at a probability dependent on the epsilon value.
Apple only sends a random row from this matrix instead of the entire thing in order to stay within their privacy budget.
### See What's Sent
You can see data sent with differential privacy in iOS under Settings > Privacy > Analytics > Analytics Data, it will begin with `DifferentialPrivacy`. On macOS, you can see these logs in the Console.
## U.S. Census
Differential privacy isn't just used by big corporations, in 2020 famously the U.S. Census used DP to protect the data of U.S. citizens for the first time.
As a massive collection of data from numerous U.S. citizens, it's important for the census bureau to protect the privacy of census participants while still preserving the overall aggregate data.
### Impetus
Since the 90s, the U.S. Census used a less formal injection of statistical noise into their data, which they did all the way through 2010.
After the 2010 census, the bureau tried to [re-identify individuals](https://www2.census.gov/library/publications/decennial/2020/census-briefs/c2020br-03.pdf) in the census data.
>The experiment resulted in reconstruction of a dataset of more than 300 million individuals. The Census Bureau then used that dataset to match the reconstructed records to four commercially available data sources, to attempt to identify the age, sex, race, and Hispanic origin of people in more than six million blocks in the 2010 Census.
Considering 309 million people lived in the U.S. in 2010, that's a devastating breach of personal privacy. Clearly more formal frameworks for protecting the privacy of individuals were needed.
>Nationwide, roughly 150 million individuals—almost one-half of the population, have a unique combination of sex and single year of age at the block level.
They could keep adding noise until these attacks are impossible, but that would make the data nigh unusable. Instead, differential privacy offers a mathematically rigorous method to protect the data from future re-identification attacks without ruining the data by adding too much noise. They can be sure thanks to the mathematical guarantees of DP.
## DPrio
Mozilla has been constantly working to make their telemetry more private over the years. Firefox uses [Prio](https://blog.mozilla.org/security/2019/06/06/next-steps-in-privacy-preserving-telemetry-with-prio/), a [Distributed Aggregation Protocol](https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap)-based telemetry system. It uses Multi-Party Computation to split the processing of user data between multiple parties.
To accomplish this, [Mozilla](https://blog.mozilla.org/en/firefox/partnership-ohttp-prio/) partnered with [Divvi Up](https://divviup.org/blog/divvi-up-in-firefox/) as their DAP provider, and [Fastly](https://www.fastly.com/blog/firefox-fastly-take-another-step-toward-security-upgrade) as their OHTTP provider. OHTTP acts as a multi-hop proxy to separate traffic between two parties when making a connection: neither Mozilla nor Fastly will know both who you are and what you're connecting to.
In 2023 researchers from Mozilla also conducted research into making Prio differentially private. The so-named "[DPrio](https://petsymposium.org/popets/2023/popets-2023-0086.pdf)" would combine multi-party computation, OHTTP, and differential privacy in a very impressive display of privacy protection. Unfortunately I couldn't find any evidence to suggest that DPrio has been implemented, but something to keep a lookout for in the future.
## Future of Differential Privacy
Differential privacy unlocks the potential for data collection with minimal risk of data exposure for any individual. Already, DP has allowed for software developers to improve their software, for new possibilities in research in the health sector and in government organizations.
Adoption of scientifically and mathematically rigorous methods of data collection allows for organizations to collect aggregate data will allow for increased public trust in organizations and subsequently greater potential for research that will result in improvements to our everyday lives.
I think for there to be more public trust there needs to be a bigger public outreach. That's my goal with this series, I'm hoping to at least increase awareness of some of the technology being deployed to protect your data, especially since so much of the news we hear is negative. Armed with the knowledge of what's available, we can also demand companies and organizations use these tools if they aren't already.
It's heartening to see the level of openness and collaboration in the research. You can see a clear improvement over time as each paper takes the previous research and builds on it. I wish we saw the same attitude with all software.
## Further Research
Any programmers interested in learning how to implement differential privacy can check out the book *[Programming Differential Privacy](https://programming-dp.com)* to see Python examples.

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-05-19T20:15:00Z
categories:
@@ -14,6 +17,7 @@ preview:
# The Power of Digital Provenance in the Age of AI
![Article cover showing a painterly background with cool colors and the Content Credentials logo](../assets/images/digital-provenance/cover.jpg)
<small aria-hidden="true">Photo: Kseniya Lapteva / Pexels | Logo: Content Credentials</small>
With the popularity of generative AI, it's becoming more and more difficult to [distinguish](https://uwaterloo.ca/news/media/can-you-tell-ai-generated-people-real-ones) reality from fiction. Can this problem be solved using cryptography? What are the privacy implications of the currently proposed systems?<!-- more -->

View File

@@ -1,285 +0,0 @@
---
title: "Email Security: Where We Are and What the Future Holds"
date:
created: 2025-11-15T22:45:00Z
categories:
- Explainers
authors:
- fria
tags:
- Email
license: BY-SA
schema_type: BackgroundNewsArticle
description: Email is ubiquitous. If you want to function in modern society, you pretty much have to have an email address. But is it really a good idea to still be relying on the same decades old techology? What can we do about replacing it?
preview:
cover: blog/assets/images/email-security/cover.png
---
![Email icon opening with an alert message inside](../assets/images/email-security/cover.png)
<small aria-hidden="true">Illustration: fria / Privacy Guides</small>
Email is ubiquitous. If you want to function in modern society, you pretty much have to have an email address. What was originally just a simple protocol to send messages between machines has morphed beyond what it was originally intended for into the *de facto* authentication, identity, and "secure" communication channel for almost all technology users today. It's been updated many times to fix security issues and there are more updates to come, but is it worth trying to fix a decades-old protocol, or should we scrap it all and start over?<!-- more -->
## Current State of Email Security
The [**Simple Mail Transport Protocol (SMTP)**](https://www.rfc-editor.org/rfc/rfc5321.html) is the standard used to send emails.
Over the years, multiple protocols have been introduced to fix security issues and improve the usability of email, resulting in a complex mess that we're still feeling the consequences of to this day.
### Encryption
By default, there's no encryption in SMTP. Not transport encryption or end-to-end encryption, it's just a plaintext protocol.
To remedy this, several solutions have been created.
#### STARTTLS
[STARTTLS](https://www.rfc-editor.org/rfc/rfc3207) is a command that allows email clients to negotiate TLS encryption. Importantly, the negotiation phase happens in plaintext which leaves it vulnerable to attackers.
STARTTLS allows a bit more flexibility at the cost of some security. Since you don't really know if the recipient's email client supports TLS or not, it allows you to continue with the SMTP session anyway if you want to.
Since it's just using TLS, STARTTLS can't provide E2EE, just transport encryption. The encryption looks something like:
Encrypted between your email client and your SMTP server → decrypted at your SMTP server → Encrypted between your SMTP server and recipient's SMTP server → decrypted at recipient's SMTP server → encrypted between their SMTP server and their POP3/IMAP server → decrypted at their POP3/IMAP server → encrypted between their POP3/IMAP server and their email client → decrypted by their email client.
``` mermaid
flowchart LR
A[Email Client] -->|Optional TLS Encryption| B(SMTP Server)
B --> |Optional TLS Encryption| C(Other SMTP Server)
C -->|Optional TLS Encryption| D[POP3 or IMAP Server]
D -->|Optional TLS Encryption| F[Other Party's Email Client]
```
At each point in the process TLS encryption is not guaranteed. Now consider that you can have multiple recipients with their own SMTP servers as well, and you start to see how flimsy this protection can be. And since the initial negotiation is in plaintext, an attacker can simply strip away the STARTTLS command, preventing a secure connection from being established.
Authentication is left to another protocol to solve, this just handles the transport encryption.
#### SMTPS
Also known as "Implicit TLS" (as opposed to the "Explicit TLS" of STARTTLS), SMTPS starts with an encrypted connection, similar to HTTPS, removing the potential for an adversary to downgrade the connection.
The [current](https://datatracker.ietf.org/doc/html/rfc8314) recommendations are to use port 465 for SMTPS and port 587 for STARTTLS. Unfortunately, these ports aren't standardized and thus there is disagreement and confusion about what port should be used for SMTPS.
In the past, ports 25, 465, 587, and 2525 have all been used for SMTP at various points. This lack of a standardized port means that you end up with services using different ports and being unable to establish a secure connection. Particularly, there is still confusion in some email providers whether to use port 465 or port 587 for SMTPS, although the current recommendation is port 465.
#### POP3S
[Post Office Protocol version 3](https://en.wikipedia.org/wiki/Post_Office_Protocol) or POP3 is a protocol for retrieving mail from a mail server. It's one of the ways your email client can show you your mail.
POP3 also supports implicit TLS over port 995, so it can be encrypted by default as well.
#### IMAPS
[Internet Message Access Protocol](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) or IMAP is another protocol for retrieving mail from a mail server.
Like SMTPS and POP3s, IMAP supports implicit TLS. The implicit TLS port is 993.
#### OpenPGP
The above features only protect the email in transit and don't protect against the email providers involved, which is a massive security issue if you don't trust your email provider. On top of that, you as a user have no control over which parts of the chain are encrypted. If you want to be sure that no party in between you and your recipient can read or alter your emails, you need to use end-to-end encryption. Unfortunately, by default, email doesn't support end-to-end encryption.
[Pretty Good Privacy (PGP)](https://www.openpgp.org/about/) was originally created in 1997 by [Phil Zimmerman](https://www.privacyguides.org/videos/2025/05/08/when-code-became-a-weapon/). While originally proprietary software, an open source version of PGP called OpenPGP has been standardized by the [IETF](https://www.rfc-editor.org/rfc/rfc9580.html). As you can imagine from software originally conceived in the 90s, the user experience isn't the smoothest.
Unlike modern messengers like [Signal](https://signal.org), OpenPGP requires you to [manually manage your keys](https://dev.to/adityabhuyan/how-to-generate-your-own-public-and-secret-keys-for-pgp-encryption-1joh). This is a problem not only because it's cumbersome, but the security of E2EE rests on protecting the private key. If the private key is compromised, your messages are compromised.
PGP also lacks [forward secrecy](https://en.wikipedia.org/wiki/Forward_secrecy), meaning that if your private key is ever exposed, all previous messages you've ever sent using that key are also exposed. All it takes is a slight user error for a catastrophic compromise.
PGP encryption also usually doesn't encrypt important metadata like `To`, `From`, `Cc`, `Date`, and `Subject`, stored in the [email header](https://en.wikipedia.org/wiki/Email#Message_header); usually, only the body of the email is encrypted, which can be a major privacy issue. What the email is about, who you are, and who you're messaging can all be revealed even with E2EE. Some email clients use their hidden headers that can reveal more data about you.
#### S/MIME
Another common option for email encryption is [S/MIME](https://www.digicert.com/faq/email-trust/what-is-smime-or-encrypted-email), or Secure/Multipurpose Internet Mail Extensions. S/MIME works a bit like HTTPS, using [X.509 digital certificates](https://www.ssl.com/faqs/what-is-an-x-509-certificate/) and [certificate authorities](https://www.digicert.com/blog/what-is-a-certificate-authority) to encrypt and verify the authenticity of emails.
While a step up from the manual keys of PGP, S/MIME is still a pain to use, particularly because it usually requires purchasing and managing a certificate from a CA, which can be expensive and annoying. S/MIME also lacks forward secrecy just like PGP, so if there's ever a compromise of your private key, all previously sent messages are also compromised.
These issues make S/MIME nonviable for most people outside business settings.
#### Web Key Directory
A problem with PGP is getting your public key out to people without manually exchanging keys. This problem can be solved with Web Key Directory (WKD), which allows you to upload your public PGP key to a server and clients that want to send E2EE emails to you can ask that server to send you their public key.
You can read more on our [email security](https://www.privacyguides.org/en/basics/email-security/?h=email#what-is-the-web-key-directory-standard) page.
### Authentication
SMTP by default essentially has no authentication and allows spoofing the `MAIL FROM` header. Your email client will just blindly accept whoever the sender says they are without any authentication. Luckily, there are several solutions for this.
There are multiple methods that email providers can implement to verify the authenticity of an email sender.
#### SPF
The first solution implemented was [Sender Policy Framework (SPF)](https://datatracker.ietf.org/doc/html/rfc7208). SPF uses [DNS TXT records](https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/).
Just like the name sounds, a DNS TXT record allows you to store text in a [DNS record](https://www.cloudflare.com/learning/dns/dns-records/). Here's an example of what a DNS TXT record might look like:
| example.com | record type | value | TTL |
|-------------|--------------|--------|-----|
| @ | TXT | "color=blue" |99999|
SPF lists all the servers that are authorized to send from a specific domain. When an email is received, it checks the sending server against the list of authorized servers for that domain. An SPF record might look like this:
| example.com | record type | value | TTL |
|-------------|--------------|--------|-----|
| @ | TXT | "v=spf1 ip4:200.56.78.99 ip4:156.67.109.43 include:_spf.google.com -all" |99999|
The IP addresses are the ones that are authorized to send email from this domain. The `include:` tag denotes what third-party domains are allowed to send email on behalf of `example.com`. The third-party SPF record will be checked and included in the allowed IP addresses.
While a good start, SPF still has several glaring weaknesses. Since it relies on DNS, an attack on the DNS infrastructure could cause spoofed DNS data to be accepted.
Since SPF doesn't authenticate individual users, it's still possible for a sender to impersonate another user. SPF does not authenticate the `MAIL FROM` header. If you try to send an email from a gmail.com domain, but the server doesn't match gmail.com, it will fail.
SPF has a few different modes, allowing for a hard fail, soft fail, or completely ignoring it. `-all` means an email that fails will be rejected, `~all` will mark emails that fail as insecure or spam but still send them, and `+all` will specify that any server is allowed to send emails on behalf of your domain.
This flexibility, while convenient, allows for the security benefits of SPF to be completely undermined.
#### DKIM
[DomainKeys Identified Mail (DKIM)](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/) relies on public key cryptography to verify the domain of an email.
Example of a DKIM DNS TXT record:
| name | record type | value | TTL |
|-------------|--------------|--------|-----|
| test-email._domainkey.example.com | TXT | "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtY+7sGVwvyS8w+3HgJk7EviazH+C4L8gV4gOJzAq9oKJjZ5En7LDEw3FqAh8C0M59c9sBQcC+Kj8VxMBY9y+E0Pm1fPK9V7sI3Gm7yE7Y9yU4uVZr8R3N+5z+qZ+7V76RU4oZ0mtSvw8m3pX1hZyHd7NZfXaFfKfgd18W5T7YQIDAQAB" | 9999 |
DKIM records are stored under a specific name following the format
`[selector]_domainkey.[domain]`
The public and private keys are generated by the email provider, such as gmail.com. The public key is stored in a publicly available DNS TXT record like the one seen above and is used by the receiver to verify messages. The private key is kept secret by the email provider.
Emails sent from the email provider contain a DKIM header with a signature generated from the private key and the content of the message. If the email message is altered or signed with the wrong key, when the receiver verifies the signature using the public key it will be obvious it was altered.
An example of a DKIM header:
`v=1; a=rsa-sha256; d=example.com; s=test-email; h=from:to:subject bh=uMixy0BsCqhbru4fqPZQdeZY5Pq865sNAnOAxNgUS0s=;b=LiIvJeRyqMo0gngiCygwpiKphJjYezb5kXBKCNj8DqRVcCk7obK6OUg4o+EufEbBtRYQfQhgIkx5m70IqA6dP+DBZUcsJyS9C+vm2xRK7qyHi2hUFpYS5pkeiNVoQk/Wk4wZG4tu/g+OA49mS7VX+64FXr79MPwOMRRmJ3lNwJU=`
`v=` shows the version of DKIM, currently version one is the latest (we'll come back to that later). `a=` shows the algorithm used. `d=` shows the domain of the sender. `s=` denotes the selector that is used in the TXT record. `h=` shows the headers that were used to create the signature. `bh=` shows a hash of the body of the email. `b=` is the signature computed from the listed headers and the hash of the body listed in `bh`.
In this way, not only does DKIM provide assurance that the email was sent from the correct domain, it also protects the integrity of the message. However, since the keys are controlled by your email provider, it can't stop your email provider from tampering with your messages.
Note also that this has nothing to do with encryption of the message, only verifying the authenticity and sender. The message is still sent in plaintext unless another component encrypts it.
#### DMARC
[Domain-based Message Authentication Reporting and Conformance (DMARC)](https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/) is an authentication method that builds on SPF and DKIM. DMARC tells a receiving email server what to do after checking the SPF and DKIM. If the email fails, the DMARC policy tells the receiver whether to mark it as spam, block it, or allow it through.
DMARC also uses TXT records. An example DMARC policy might look like
`v=DMARC1; p=quarantine; adkim=s; aspf=s;`
The `v=` shows the version of DMARC to use. The `p=` shows what should be done with emails if they fail, in this case `quarantine` means the receiver should put the email in the user's spam folder. `reject` can be specified as well to show that emails that fail should be outright blocked. `adkim=` tells how DKIM should be enforced, with `s` meaning "strict"; for relaxed, `r` is listed instead. Ditto for `aspf=`.
#### DNSSEC
You may have noticed that all of these authentication methods rely on DNS. Unfortunately, DNS wasn't designed to be secure when it was invented in the 1980s. Ironically, there's no authentication built into DNS by default, so by attacking DNS, a malicious actor can [poison](https://www.cloudflare.com/learning/dns/dns-cache-poisoning/) your DNS cache with false information.
[Researchers at CMU in 2014](https://www.sei.cmu.edu/blog/probable-cache-poisoning-of-mail-handling-domains/) found that emails that were supposedly to be sent by Gmail, Yahoo!, and Outlook.com were actually being sent by a rogue email server. This is disastrous for security and breaks the entire email authentication system. There are many such cases of attacks on DNS infrastructure and many more [possible attacks](https://www.akamai.com/glossary/what-are-dns-attack-vectors) on DNS.
The solution? [DNSSEC](https://www.cloudflare.com/learning/dns/dnssec/how-dnssec-works/). DNSSEC uses digital signatures to verify the authenticity of the DNS response. Unfortunately, DNSSEC isn't as widely used as it could be so DNS attacks are still a real threat.
DNSSEC forms a [chain of trust](https://en.wikipedia.org/wiki/Chain_of_trust), with each zone forming a parent/child relationship all the way up to the [root zone](https://www.cloudflare.com/learning/dns/glossary/dns-root-server/).
The public key infrastructure (PKI) that we rely on for things like HTTPS in browsers similarly relies on a chain of trust, but web PKI relies on many trusted entities whereas DNSSEC effectively reduces it to one: the IANA which signs the root zone key in a [root signing ceremony](https://www.cloudflare.com/learning/dns/dnssec/root-signing-ceremony/).
Effectively, DNSSEC is designed so that you can be sure the results of a DNS query are accurate.
#### DANE
DNS-Based Authentication of Named Entities or DANE applies the security of DNSSEC to email. It forces TLS to be used and binds the TLS certificate to DNS names directly using TLSA, thus allowing email providers to bypass the certificate authority system relied on by HTTPS.
#### MTA-STS
[MTA-STS](https://www.mailhardener.com/kb/mta-sts) or Mail Transfer Agent Strict Transport Security is a way to force TLS connections for email and validate that the DNS is correct. Instead of DNSSEC, MTA-STS relies on HTTPS and the web PKI to validate DNS. It's not stored as a DNS record but instead an HTTPS server that serves the file.
You can think of MTA-STS like HSTS, HTML Strict Transport Security, which forces the use of TLS for websites. It's the same principal, just applied to email.
The extra reliance on web PKI introduces more trust than with DNSSEC, but it's easier to implement and relies on the already-established infrastructure of the internet.
Both DANE and MTA-STS can be used together for a multilayered approach to email security.
### General Security
#### Email as a Backdoor into Your Accounts
Something seldom discussed is the fact that email is the default 2FA method for most accounts and also can be used to bypass your password through the password reset function on the login screen of most services. This essentially means the security of all of your accounts rests on the security of your email, which can be very shaky and lacks E2EE usually. It's most comparable to SMS 2FA which is also used a lot of the time as a method for getting into accounts when you forgot your password.
I touched on this a bit in my [passkey article](toward-a-passwordless-future.md), but we need to stop relying on email for security critical applications and start using proper recovery methods like recovery codes. Email should be used for what it's intended for: sending messages and updates to people, announcements, etc.
#### Third-Party Clients
Many email providers such as Gmail provide their own clients for you to view your inbox, send messages, etc. But many people choose to use third-party clients for their email needs.
While it's great that email can support that, it does mean you need to trust another party with your sensitive email and essentially the security of all of your accounts. Not to mention that email clients can have [vulnerabilities](https://www.mozilla.org/en-US/security/known-vulnerabilities/thunderbird/), so you need to be very careful about which one you trust.
#### Email Attack Surface
A big part of the reason email clients can be so vulnerable to exploits is the vast attack surface afforded by things like JavaScript support in emails. This puts email clients dangerously close to the same territory as browsers in terms of attack surface but without the same level of scrutiny or hardening effort that goes into browsers.
Since almost anyone can email you at any time, you have to trust that your email client vendor is able to protect you against [vulnerabilities](https://www.csoonline.com/article/1308164/microsoft-outlook-flaw-opens-door-to-1-click-remote-code-execution-attacks.html) and also has timely patches when they're found.
Luckily, lots of email clients let you disable JavaScript and HTML if you want, but not all do, and email clients can have lots of other vulnerabilities as well not related to JavaScript.
## Future of Email Security
It's been a multi-decade cross-industry effort to bring email up to snuff as a modern communication system, and we still have a long way to go. There's still efforts to improve the state of email security, so look out for these in the future.
### Improvements to OpenPGP
The IETF has a [working group](https://datatracker.ietf.org/wg/openpgp/about/) for OpenPGP that wants to add many improvements to OpenPGP, including post-quantum encryption, forward secrecy, and usability improvements.
Key transparency is also a planned feature, similar to what apps like [WhatsApp](https://scontent.xx.fbcdn.net/v/t39.8562-6/379264560_846690136905658_6336040801441930900_n.pdf?_nc_cat=108&ccb=1-7&_nc_sid=e280be&_nc_ohc=gNmDlLkE0DMQ7kNvwEyKONi&_nc_oc=AdmucQjSjoTw2nXUszYeZNStyUHGqvM2pj3oRVV7qI4xmLEJMmY2pUV29WcOnKC1KpA&_nc_zt=14&_nc_ht=scontent.xx&_nc_gid=5lSqV7L5iCqeiMSQDCwN0w&oh=00_AfXoxrF8ukQtSVZM_BCBDbveIDviQPfn0kDEV8pSbxX1SQ&oe=68AB9400) have implemented. Key transparency systems use an append-only, auditable and tamper-evident log of keys that allows you to automatically verify the authenticity of whoever you're messaging with.
There's even a plan to add the ability to verify keys manually using QR codes, similar to how some messengers let you manually verify keys.
### Improvements to S/MIME
The [LAMPS](https://datatracker.ietf.org/wg/lamps/about/) working group is looking at adding post-quantum encryption to S/MIME to protect against future quantum computer threats. This would include "dual-signature" schemes combining traditional encryption with PG encryption, similar to how some messengers handle it.
### DKIM2
[DKIM2](https://www.ietf.org/archive/id/draft-gondwana-dkim2-motivation-00.html) is the planned next version of DKIM.
An issue with the current version of DKIM is a malicious actor taking emails signed with DKIM from a different domain and replaying them, spamming them out to thousands of people and eroding trust in the original domain. The new DKIM2 specification would force each hop the email takes along its path to sign it, so any issues will be the fault of the previous hop.
DKIM2 aims to simplify the protocol and make it more standardized. For example, in practice, the vast majority of DKIM is singed using relaxed methods, so DKIM2 will only support relaxed.
The fact that DKIM relies on an explicit list of headers as part of the signature, there is inconsistent signing of headers and some security-critical headers might not be signed. In order to prevent attackers from adding headers that weren't originally part of the email, providers would sign headers with no information in them. DKIM2 would specify a fixed set of headers in alignment with best practices, so there won't be a need to specify headers.
### DMARCbis
[DMARCbis](https://datatracker.ietf.org/doc/draft-ietf-dmarc-dmarcbis/) is a proposed updated version of DMARC.
The `pct` tag is going away, which was a tag that would only allow a specified percentage of emails, say 50%, to be sent if they failed. Apparently, this wasn't implemented properly so now it's being replaced with the `t` mode that is a binary pass or fail.
The new `np` tag adds the ability to define what to do with a non-existent subdomain of a real domain. This will prevent cybercriminals from subverting DMARC by using a fake subdomain.
They are also adding [requirements](https://datatracker.ietf.org/doc/html/draft-ietf-dmarc-dmarcbis-41#name-conformance-requirements-fo) that mail providers must meet to fully conform to the specification, which should eliminate questions about best practices and how DMARC should be implemented.
### Deprecation of Cleartext Email
Since there are now protocols in place to at least allow for transport encryption at every stage of the email process, providers should work on [removing support](https://datatracker.ietf.org/doc/html/rfc8314#section-4.1) for unencrypted email entirely.
Transport encryption between servers now should be the minimum expected for email services going into the future.
### Passkeys
The adoption of [passkeys](https://fidoalliance.org/passkeys/) will eliminate the need for email as a recovery method, since users won't have to remember passwords. Email can be used for what it was originally intended for: a method of communication and sending updates and announcements, nothing more. This will take a concerted effort from service providers though, and it seems for now most services that support passkeys still require and email for some reason. Here's hoping this changes in the future.
The adoption of passkeys will also make email services themselves more secure, since at the moment they act as a sort of de facto recovery method for all of our accounts. They should focus on deprecating passwords for improved security.
### Wider Adoption of DNSSEC
DNSSEC should be universally adopted to prevent DNS poisoning attacks. This would drastically improve the security of email.
### Guidance for E2EE
The usability of E2EE in email is significantly lacking compared to other methods of communication, especially modern messengers like Signal that make the E2EE very seamless and simple. The handling of E2EE by email clients can also vary a lot and leave email users [vulnerable to bypasses](https://efail.de) for the E2EE.
An [RFC](https://www.ietf.org/archive/id/draft-ietf-lamps-e2e-mail-guidance-17.html) to address usability issues and best practices for email clients exists, hopefully it can lead to a future of improved user experience and security in email.
### SMTP End-to-End Encryption
The biggest obstacle in the way of email privacy is it's not E2EE by default like most modern messengers we use daily. Some providers like Proton Mail will automatically encrypt emails between [Proton Mail](https://proton.me/support/manage-encryption#:~:text=Proton%20Mail%20encrypts%20all%20emails%20sent%20between%20Proton%20accounts%20with%20end%2Dto%2Dend%20encryption%20(E2EE)) users. The obvious next step is to build E2EE into SMTP itself.
An [RFC proposal](https://dcrubro.com/files/smtp-ee2esign-latest.txt) exists for just such an idea. I'm hopeful something like this can be standardized and widely adopted, and finally bring email into the 21st century.

View File

@@ -1,11 +1,14 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-04-11T16:00:00Z
categories:
- Opinion
authors:
- em
description: Encryption is not a crime, encryption protects us all. Encryption, and especially end-to-end encryption, is an essential tool to protect everyone online. Attempts to undermine encryption are an attack to our fundamental right to privacy and an attack to our inherent right to security and safety.
description: Encryption is not a crime, encryption protects all of us. Encryption, and especially end-to-end encryption, is an essential tool to protect everyone online. Attempts to undermine encryption are an attack to our fundamental right to privacy and an attack to our inherent right to security and safety.
schema_type: OpinionNewsArticle
preview:
cover: blog/assets/images/encryption-is-not-a-crime/encryption-is-not-a-crime-cover.webp

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-06-03T17:00:00Z
categories:
@@ -7,7 +10,7 @@ tags:
- Pride Month
authors:
- em
description: Data privacy is important for everyone. But for some marginalized populations, data privacy is indispensable for social connection, access to information, and physical safety. For Pride month, we discuss topics at the intersection of data privacy and experiences specific to the LGBTQ+ community.
description: Data privacy is important for everyone. But for some marginalized populations, data privacy is indispensable for social connection, access to information, and physical safety. For Pride month this year, we will discuss topics at the intersection of data privacy and experiences specific to the LGBTQ+ community.
schema_type: AnalysisNewsArticle
preview:
cover: blog/assets/images/importance-of-privacy-for-the-queer-community/pride-cover.webp

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-04-30T20:30:00Z
updated: 2025-05-06T18:00:00Z
@@ -8,7 +11,7 @@ tags:
- Tor
authors:
- em
description: You might have heard of Tor already, yet never dared to try it yourself. Despite being around for decades, too few people know about Tor. It isn't only a tool for journalists and activists, but for anyone seeking greater privacy online. What is Tor exactly? And how can Tor help you?
description: You might have heard of Tor in the news a few times, yet never dared to try it yourself. Despite being around for decades, Tor is still a tool too few people know about. Today, Tor is easy to use for anyone. It not only helps journalists and activists, but anybody who seeks greater privacy online or access to information regardless of location. But what is Tor exactly? How can Tor help you? And why is it such an important tool?
schema_type: OpinionNewsArticle
preview:
cover: blog/assets/images/in-praise-of-tor/tor-cover.webp

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-01-29T22:00:00Z
categories:

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-03-18T17:00:00Z
categories:

View File

@@ -1,4 +1,7 @@
---
# SPDX-FileCopyrightText: 2025 Privacy Guides <https://magicgrants.org/funds/privacy_guides/>
#
# SPDX-License-Identifier: CC-BY-SA-4.0
date:
created: 2025-03-28T17:00:00Z
categories:

Some files were not shown because too many files have changed in this diff Show More