Compare commits
22
Commits
v0.3.17
...
a0c0ee26ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0c0ee26ca | ||
|
|
3e637a8429 | ||
|
|
2d1964106b | ||
|
|
7c4652ac49 | ||
|
|
c855253072 | ||
|
|
f20b7de053 | ||
|
|
afa7474094 | ||
|
|
256cb98695 | ||
|
|
1cd6fc11a4 | ||
|
|
9643916f16 | ||
|
|
f52a4ef3cf | ||
|
|
ebdf3f4f91 | ||
|
|
ed8f59439d | ||
|
|
5c287f2459 | ||
|
|
fdb71081e0 | ||
|
|
751bf8be16 | ||
|
|
e738cba3a3 | ||
|
|
4c00ccaa39 | ||
|
|
36f41ba43a | ||
|
|
61502548d4 | ||
|
|
7b6f6d43fc | ||
|
|
4822ee6880 |
+2
-2
@@ -16,8 +16,8 @@ DJANGO_SECRET_KEY=CHANGE_ME_generate_at_least_50_random_characters
|
|||||||
DJANGO_DEBUG=0
|
DJANGO_DEBUG=0
|
||||||
# Leeg laten tot er een publieke HTTPS-URL is.
|
# Leeg laten tot er een publieke HTTPS-URL is.
|
||||||
PUBLIC_BASE_URL=
|
PUBLIC_BASE_URL=
|
||||||
DJANGO_ALLOWED_HOSTS=192.168.10.150,127.0.0.1,localhost
|
DJANGO_ALLOWED_HOSTS=vacatureradar.local,127.0.0.1,localhost
|
||||||
DJANGO_CSRF_TRUSTED_ORIGINS=http://192.168.10.150:1226,http://127.0.0.1:1226
|
DJANGO_CSRF_TRUSTED_ORIGINS=http://vacatureradar.local:1226,http://127.0.0.1:1226
|
||||||
DJANGO_TIME_ZONE=Europe/Brussels
|
DJANGO_TIME_ZONE=Europe/Brussels
|
||||||
VACATURERADAR_OWNER_NAME=Jens
|
VACATURERADAR_OWNER_NAME=Jens
|
||||||
VACATURERADAR_VERSION=0.3.12
|
VACATURERADAR_VERSION=0.3.12
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
name: deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: deploy-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: self-hosted
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Push-to-deploy op server
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [ -z "${DEPLOY_COMPOSE_FILE:-}" ]; then
|
|
||||||
DEPLOY_COMPOSE_FILE="docker-compose.yml"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${APP_HOST:-}" ]; then
|
|
||||||
APP_HOST="$(hostname -f 2>/dev/null || hostname)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${APP_SCHEME:-}" ]; then
|
|
||||||
APP_SCHEME="http"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "${DJANGO_DEBUG:-}" ]; then
|
|
||||||
if [ "${APP_SCHEME}" = "https" ]; then
|
|
||||||
DJANGO_DEBUG="0"
|
|
||||||
else
|
|
||||||
DJANGO_DEBUG="1"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
export APP_HOST
|
|
||||||
export APP_SCHEME
|
|
||||||
export DJANGO_DEBUG
|
|
||||||
|
|
||||||
export DEPLOY_COMPOSE_FILE
|
|
||||||
if [ -n "${APP_ORIGINS:-}" ]; then
|
|
||||||
export APP_ORIGINS
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${APP_HOSTS:-}" ]; then
|
|
||||||
export APP_HOSTS
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${APP_PORT:-}" ]; then
|
|
||||||
export APP_PORT
|
|
||||||
fi
|
|
||||||
|
|
||||||
bash scripts/deploy_docker.sh "${DEPLOY_COMPOSE_FILE}" .env
|
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
name: Managed validation
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
profile:
|
||||||
|
description: Allowlisted validation profile
|
||||||
|
required: true
|
||||||
|
default: full
|
||||||
|
type: choice
|
||||||
|
options: [test, lint, typecheck, build, security, full]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: managed-validation-${{ gitea.repository }}-${{ gitea.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
full:
|
||||||
|
name: full
|
||||||
|
# Public fork code must never execute automatically on the private runner.
|
||||||
|
if: ${{ gitea.event_name != 'pull_request' || gitea.event.pull_request.head.repo.full_name == gitea.repository }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
container:
|
||||||
|
# Gitea's JavaScript actions execute inside the job container, so use
|
||||||
|
# the version-matched Playwright image that includes Node as well as the
|
||||||
|
# pinned Chromium browser and native runtime libraries.
|
||||||
|
image: mcr.microsoft.com/playwright:v1.54.0-noble
|
||||||
|
options: --ipc=host
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
- name: Provision the supported Python runtime
|
||||||
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
|
||||||
|
with:
|
||||||
|
python-version: '3.13.2'
|
||||||
|
- name: Validate repository with a bounded profile
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
REQUESTED_PROFILE: ${{ inputs.profile }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
profile="${REQUESTED_PROFILE:-full}"
|
||||||
|
case "${profile}" in
|
||||||
|
test|lint|typecheck|build|security|full) ;;
|
||||||
|
*) echo "Profile is not allowlisted" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
git diff --check
|
||||||
|
if git grep -nE '^(<<<<<<< |=======$|>>>>>>> )' -- . ':!*.lock' ':!*.patch'; then
|
||||||
|
echo "Unresolved merge markers detected" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f pyproject.toml || -f requirements.txt ]]; then
|
||||||
|
# Compile only tracked Python sources. Running compileall after a
|
||||||
|
# Node install would otherwise traverse node_modules and turn a
|
||||||
|
# lightweight baseline into a large runner workload.
|
||||||
|
git ls-files -z '*.py' | xargs -0 -r python -m py_compile
|
||||||
|
if [[ -f uv.lock ]]; then
|
||||||
|
python -m venv "${RUNNER_TEMP}/managed-uv"
|
||||||
|
uv_python="${RUNNER_TEMP}/managed-uv/bin/python"
|
||||||
|
"${uv_python}" -m pip install --disable-pip-version-check uv==0.10.0
|
||||||
|
managed_uv="${RUNNER_TEMP}/managed-uv/bin/uv"
|
||||||
|
export UV_PROJECT_ENVIRONMENT="${RUNNER_TEMP}/managed-project-venv"
|
||||||
|
"${managed_uv}" sync --locked --extra browser
|
||||||
|
export PATH="${UV_PROJECT_ENVIRONMENT}/bin:${PATH}"
|
||||||
|
if [[ "${profile}" == test || "${profile}" == full ]]; then
|
||||||
|
if "${managed_uv}" run python -c 'import pytest' 2>/dev/null; then
|
||||||
|
# The image supplies the native browser libraries. Install
|
||||||
|
# only the lockfile-matched browser payload into an explicit
|
||||||
|
# job-local path; never invoke Playwright's apt workflow.
|
||||||
|
export PLAYWRIGHT_BROWSERS_PATH="${RUNNER_TEMP}/managed-playwright"
|
||||||
|
timeout --foreground 5m "${managed_uv}" run playwright install chromium
|
||||||
|
timeout --foreground 20m "${managed_uv}" run python -m pytest
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ "${profile}" == lint || "${profile}" == full ]]; then
|
||||||
|
if "${managed_uv}" run python -c 'import ruff' 2>/dev/null; then
|
||||||
|
"${managed_uv}" run python -m ruff check .
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif [[ -f requirements.txt ]]; then
|
||||||
|
python -m venv "${RUNNER_TEMP}/managed-python"
|
||||||
|
managed_python="${RUNNER_TEMP}/managed-python/bin/python"
|
||||||
|
"${managed_python}" -m pip install --disable-pip-version-check -r requirements.txt
|
||||||
|
export PATH="${RUNNER_TEMP}/managed-python/bin:${PATH}"
|
||||||
|
if [[ "${profile}" == test || "${profile}" == full ]]; then
|
||||||
|
if "${managed_python}" -c 'import pytest' 2>/dev/null; then
|
||||||
|
"${managed_python}" -m pytest
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prepare Python before invoking Node scripts. Polyglot repositories
|
||||||
|
# commonly delegate their test script to Python and need the managed
|
||||||
|
# virtual environment to be active first.
|
||||||
|
if [[ -f package.json ]]; then
|
||||||
|
corepack enable
|
||||||
|
if [[ -f pnpm-lock.yaml ]]; then
|
||||||
|
pnpm install --frozen-lockfile
|
||||||
|
[[ "${profile}" == test || "${profile}" == full ]] && pnpm --if-present test
|
||||||
|
[[ "${profile}" == lint || "${profile}" == full ]] && pnpm --if-present lint
|
||||||
|
[[ "${profile}" == typecheck || "${profile}" == full ]] && pnpm --if-present typecheck
|
||||||
|
[[ "${profile}" == build || "${profile}" == full ]] && pnpm --if-present build
|
||||||
|
elif [[ -f package-lock.json ]]; then
|
||||||
|
npm ci
|
||||||
|
[[ "${profile}" == test || "${profile}" == full ]] && npm run --if-present test
|
||||||
|
[[ "${profile}" == lint || "${profile}" == full ]] && npm run --if-present lint
|
||||||
|
if [[ "${profile}" == typecheck || "${profile}" == full ]]; then
|
||||||
|
npm run --if-present typecheck
|
||||||
|
fi
|
||||||
|
[[ "${profile}" == build || "${profile}" == full ]] && npm run --if-present build
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f go.mod ]]; then
|
||||||
|
if [[ "${profile}" == test || "${profile}" == build || "${profile}" == full ]]; then
|
||||||
|
go test ./...
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -f Cargo.toml ]]; then
|
||||||
|
if [[ "${profile}" == test || "${profile}" == build || "${profile}" == full ]]; then
|
||||||
|
cargo test --locked
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if compgen -G '*.sln' >/dev/null; then
|
||||||
|
if [[ "${profile}" == test || "${profile}" == build || "${profile}" == full ]]; then
|
||||||
|
dotnet test --configuration Release
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
name: Unraid autoredeploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
|
- ".gitea/**"
|
||||||
|
- "docs/**"
|
||||||
|
- "**/*.md"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: unraid-production-vacatureradar
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: Deploy vacatureradar
|
||||||
|
runs-on: unraid-deploy
|
||||||
|
timeout-minutes: 180
|
||||||
|
steps:
|
||||||
|
- name: Deploy exact Gitea revision
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
docker exec gitea-deploy-control \
|
||||||
|
/opt/gitea-deploy/deploy.py deploy \
|
||||||
|
"$GITHUB_REPOSITORY" "$GITHUB_SHA"
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
path: ./
|
path: ./
|
||||||
extra_args: --only-verified
|
extra_args: --only-verified
|
||||||
- name: Scan project dependencies and lockfiles (high/critical)
|
- name: Scan project dependencies and lockfiles (high/critical)
|
||||||
uses: aquasecurity/trivy-action@0.30.0
|
uses: aquasecurity/trivy-action@v0.30.0
|
||||||
with:
|
with:
|
||||||
scan-type: fs
|
scan-type: fs
|
||||||
scan-ref: .
|
scan-ref: .
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
- name: Build production image
|
- name: Build production image
|
||||||
run: docker build --pull --tag vacatureradar:ci .
|
run: docker build --pull --tag vacatureradar:ci .
|
||||||
- name: Scan container image for high/critical vulnerabilities
|
- name: Scan container image for high/critical vulnerabilities
|
||||||
uses: aquasecurity/trivy-action@0.30.0
|
uses: aquasecurity/trivy-action@v0.30.0
|
||||||
with:
|
with:
|
||||||
image-ref: vacatureradar:ci
|
image-ref: vacatureradar:ci
|
||||||
format: table
|
format: table
|
||||||
@@ -74,7 +74,7 @@ jobs:
|
|||||||
exit-code: "1"
|
exit-code: "1"
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
- name: Generate CycloneDX software bill of materials
|
- name: Generate CycloneDX software bill of materials
|
||||||
uses: aquasecurity/trivy-action@0.30.0
|
uses: aquasecurity/trivy-action@v0.30.0
|
||||||
with:
|
with:
|
||||||
image-ref: vacatureradar:ci
|
image-ref: vacatureradar:ci
|
||||||
format: cyclonedx
|
format: cyclonedx
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ Alle betekenisvolle wijzigingen worden hier bijgehouden. Het project volgt voorl
|
|||||||
- De Gitea-releasebootstrap gebruikt een immutable `setup-uv`-commit en een exacte
|
- De Gitea-releasebootstrap gebruikt een immutable `setup-uv`-commit en een exacte
|
||||||
uv-versie; downloads lopen via de Astral-mirror en zijn niet langer afhankelijk
|
uv-versie; downloads lopen via de Astral-mirror en zijn niet langer afhankelijk
|
||||||
van de gelimiteerde GitHub Releases-API op het gedeelde runner-IP.
|
van de gelimiteerde GitHub Releases-API op het gedeelde runner-IP.
|
||||||
|
- De achterhaalde `main`-push-to-deployworkflow is verwijderd; alleen een
|
||||||
|
semantische tag kan nog een immutable releaseimage publiceren.
|
||||||
|
- De Unraid Docker-host gebruikt een conflictvrije `/24`-address pool met ruimte
|
||||||
|
voor 256 tijdelijke en toekomstige netwerken.
|
||||||
|
|
||||||
## 0.3.16 - 2026-08-12
|
## 0.3.16 - 2026-08-12
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
VacatureRadar is een persoonlijke vacature-assistent voor België. De applicatie volgt toegestane werkgeversbronnen, ATS-pagina’s, feeds en vacaturemails, verwijdert dubbels en irrelevante resultaten en rangschikt de overblijvende kansen tegen jouw zoekprofiel. Jij behoudt altijd de controle: VacatureRadar helpt zoeken en opvolgen, maar solliciteert nooit automatisch.
|
VacatureRadar is een persoonlijke vacature-assistent voor België. De applicatie volgt toegestane werkgeversbronnen, ATS-pagina’s, feeds en vacaturemails, verwijdert dubbels en irrelevante resultaten en rangschikt de overblijvende kansen tegen jouw zoekprofiel. Jij behoudt altijd de controle: VacatureRadar helpt zoeken en opvolgen, maar solliciteert nooit automatisch.
|
||||||
|
|
||||||
**Actuele release: 0.3.17.** De volledige P0/P1-releasebasis en de publieke
|
**Actuele release: 0.3.17.** De volledige P0/P1-releasebasis en de publieke
|
||||||
demo-hardening zijn afgerond: 327 tests zijn groen, Microsoft 365 verwerkt platformmails via
|
demo-hardening zijn afgerond: 328 tests zijn groen, Microsoft 365 verwerkt platformmails via
|
||||||
app-only OAuth/XOAUTH2. Release 0.3.17 herstelt bovendien de reproduceerbare
|
app-only OAuth/XOAUTH2. Release 0.3.17 herstelt bovendien de reproduceerbare
|
||||||
private-registrypublicatie zonder afhankelijkheid van de GitHub Releases-API.
|
private-registrypublicatie zonder afhankelijkheid van de GitHub Releases-API.
|
||||||
Het controleerbare acceptatiebewijs staat in
|
Het controleerbare acceptatiebewijs staat in
|
||||||
|
|||||||
+2
-1
@@ -38,7 +38,8 @@ Deze data mag nooit shell-, netwerk-, e-mail-, bestandssysteem- of sollicitatiea
|
|||||||
|
|
||||||
## Kwetsbaarheid melden
|
## Kwetsbaarheid melden
|
||||||
|
|
||||||
Maak geen publieke issue met secrets of persoonlijke vacaturegegevens. Documenteer intern:
|
Maak geen publieke issue met secrets of persoonlijke vacaturegegevens. Meld een
|
||||||
|
kwetsbaarheid privé via `security@itworx.tech` en vermeld:
|
||||||
|
|
||||||
1. component en versie/commit;
|
1. component en versie/commit;
|
||||||
2. reproduceerbare stappen met synthetische data;
|
2. reproduceerbare stappen met synthetische data;
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ def seed_demo_environment(user) -> None:
|
|||||||
profile.save(update_fields=["is_active"])
|
profile.save(update_fields=["is_active"])
|
||||||
|
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
|
today = timezone.localdate(now)
|
||||||
workplace_map = {
|
workplace_map = {
|
||||||
"hybrid": JobPosting.Workplace.HYBRID,
|
"hybrid": JobPosting.Workplace.HYBRID,
|
||||||
"remote": JobPosting.Workplace.REMOTE,
|
"remote": JobPosting.Workplace.REMOTE,
|
||||||
@@ -254,7 +255,7 @@ def seed_demo_environment(user) -> None:
|
|||||||
defaults={
|
defaults={
|
||||||
"status": Application.Status.INTERVIEW,
|
"status": Application.Status.INTERVIEW,
|
||||||
"applied_at": now - timedelta(days=6),
|
"applied_at": now - timedelta(days=6),
|
||||||
"follow_up_date": (now + timedelta(days=2)).date(),
|
"follow_up_date": today + timedelta(days=2),
|
||||||
"contact_name": "Sofie Vandael",
|
"contact_name": "Sofie Vandael",
|
||||||
"contact_email": "sofie.vandael@cloudnexus.example",
|
"contact_email": "sofie.vandael@cloudnexus.example",
|
||||||
"notes": "Eerste gesprek gepland. Demo-data.",
|
"notes": "Eerste gesprek gepland. Demo-data.",
|
||||||
@@ -267,7 +268,7 @@ def seed_demo_environment(user) -> None:
|
|||||||
defaults={
|
defaults={
|
||||||
"status": Application.Status.APPLIED,
|
"status": Application.Status.APPLIED,
|
||||||
"applied_at": now - timedelta(days=2),
|
"applied_at": now - timedelta(days=2),
|
||||||
"follow_up_date": (now + timedelta(days=5)).date(),
|
"follow_up_date": today + timedelta(days=5),
|
||||||
"notes": "Sollicitatie verstuurd. Demo-data.",
|
"notes": "Sollicitatie verstuurd. Demo-data.",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,34 @@
|
|||||||
|
# Append after docker-compose.unraid.yml. Operator-only migration prerequisite;
|
||||||
|
# every path must be a verified cold clone, never the original live data.
|
||||||
|
# Also pass MIGRATION_ENV_FILE as Compose --env-file for interpolation parity.
|
||||||
|
name: vacatureradar-managed
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
labels:
|
||||||
|
io.itworx.migration-attempt: ${MIGRATION_ATTEMPT:?journaled migration attempt required}
|
||||||
|
image: ${MIGRATION_IMAGE:?set an attempt-specific candidate image}
|
||||||
|
env_file:
|
||||||
|
- ${VACATURERADAR_ENV_FILE:?set the protected external runtime env file}
|
||||||
|
build:
|
||||||
|
labels:
|
||||||
|
org.opencontainers.image.source: jens/vacatureradar
|
||||||
|
org.opencontainers.image.revision: ${MIGRATION_SOURCE_REVISION:?full verified Git commit required}
|
||||||
|
org.opencontainers.image.source-tree: ${MIGRATION_SOURCE_TREE:?verified Git tree required}
|
||||||
|
org.opencontainers.image.version: ${MIGRATION_BUILD_ID:?broker build ID required}
|
||||||
|
org.opencontainers.image.created: ${MIGRATION_BUILD_DATE:?broker UTC build date required}
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: ${MIGRATION_LOCAL_ROOT:?verified cold clone of the complete local tree required}/media
|
||||||
|
target: /app/media
|
||||||
|
bind:
|
||||||
|
create_host_path: false
|
||||||
|
- type: bind
|
||||||
|
source: ${MIGRATION_LOCAL_ROOT:?verified cold clone of the complete local tree required}/logs
|
||||||
|
target: /app/logs
|
||||||
|
bind:
|
||||||
|
create_host_path: false
|
||||||
|
- type: bind
|
||||||
|
source: ${MIGRATION_LOCAL_ROOT:?verified cold clone of the complete local tree required}
|
||||||
|
target: /app/local
|
||||||
|
bind:
|
||||||
|
create_host_path: false
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Gecontroleerde migratie van legacy deployments
|
||||||
|
|
||||||
|
`docker-compose.migration.yml` is een optionele operatoroverride, geen wijziging
|
||||||
|
aan de standaarddeployment. Gebruik deze alleen na de expliciete migratieprocedure
|
||||||
|
in ProjectBrain `scripts/legacy-deployment-migration/`.
|
||||||
|
|
||||||
|
De operator valideert de exacte Git-revisie en imageprovenance, stopt de oude
|
||||||
|
container en maakt een gecontroleerde koude kopie van de volledige `local`-map.
|
||||||
|
`MIGRATION_LOCAL_ROOT` verwijst uitsluitend naar die kopie. Media, logs en de
|
||||||
|
PostgreSQL-data houden hun geneste mountrelatie. De originele data, image en
|
||||||
|
container blijven bewaard voor rollback; startupmigraties mogen ze niet wijzigen.
|
||||||
|
|
||||||
|
Alle migratievariabelen zijn verplicht, paden worden niet automatisch aangemaakt,
|
||||||
|
en een attemptlabel bindt de nieuwe container aan precies één hersteltransactie.
|
||||||
|
De operator controleert gemergde Compose-mounts, gezondheid, HTTP en de echte
|
||||||
|
brokerreceipt voordat de configuratie definitief wordt overgezet.
|
||||||
|
|
||||||
|
De override is offline getest met echte Compose-rendering en ontbrekende
|
||||||
|
invoervariabelen. Toevoeging van dit bestand bewijst geen uitgevoerde productiemigratie.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Repository sanitation status
|
||||||
|
|
||||||
|
The accidental deployment log containing live root-SSH/container output was removed from the current tree. Active Unraid examples now use a neutral local hostname and generic appdata/backup paths rather than the operator's private host and storage layout.
|
||||||
|
|
||||||
|
## HISTORY_REWRITE_REQUIRED
|
||||||
|
|
||||||
|
Earlier commits contain the removed `deploy-log.txt` object, including private deployment commands, host information and runtime/database output. Earlier `.env.unraid.example`, `BACKUP_RESTORE.md` and `DEPLOYMENT.md` revisions also contain the original private host and appdata/backup paths.
|
||||||
|
|
||||||
|
Before public review, scan all refs for credentials, SSH targets, personal applicant/job data, production databases, media, backups, logs, archives and large objects. Review fixtures and screenshots for names, contact details, application history and other personal data. No history was rewritten during this campaign.
|
||||||
+37
-1
@@ -2419,7 +2419,7 @@ tasks:
|
|||||||
gate met 327 tests groen, 84,04% dekking.
|
gate met 327 tests groen, 84,04% dekking.
|
||||||
- id: VR-230
|
- id: VR-230
|
||||||
title: Herstel de immutable Gitea-releasepublicatie
|
title: Herstel de immutable Gitea-releasepublicatie
|
||||||
status: ready
|
status: done
|
||||||
priority: P0
|
priority: P0
|
||||||
requirement_ids:
|
requirement_ids:
|
||||||
- NFR-009
|
- NFR-009
|
||||||
@@ -2440,3 +2440,39 @@ tasks:
|
|||||||
- .gitea/workflows/release.yml
|
- .gitea/workflows/release.yml
|
||||||
- tests/unit/test_deployment_configuration.py
|
- tests/unit/test_deployment_configuration.py
|
||||||
- docs/audit/FINAL_ACCEPTANCE.md
|
- docs/audit/FINAL_ACCEPTANCE.md
|
||||||
|
result:
|
||||||
|
completed_at: '2026-08-12'
|
||||||
|
note: Releasebootstrap gepind op immutable setup-uv v8.1.0-commit en uv 0.11.12 via Astral-mirror; Gitea Actions-run
|
||||||
|
3062 publiceerde digest sha256:98f4b33d met checksum-geldige SBOM/release-evidence; Unraid gepind op volledige
|
||||||
|
digest en live health/readiness groen.
|
||||||
|
- id: VR-231
|
||||||
|
title: Sluit de operationele 0.3.17-restpunten
|
||||||
|
status: done
|
||||||
|
priority: P0
|
||||||
|
requirement_ids:
|
||||||
|
- NFR-009
|
||||||
|
depends_on:
|
||||||
|
- VR-230
|
||||||
|
summary: Verwijder de achterhaalde push-to-deployroute, herstel voldoende Docker-netwerkcapaciteit, valideer de
|
||||||
|
resterende mailboxfout en maak actuele versus historische deploymentstatus ondubbelzinnig.
|
||||||
|
acceptance_criteria:
|
||||||
|
- Main-pushes maken geen onbeperkt wachtende deployruns meer; alleen de immutable tagrelease bouwt en publiceert.
|
||||||
|
- Unraid heeft een persistente, conflictvrije default address pool met minstens 256 kleine bridge-netwerken.
|
||||||
|
- De Jobat-productiemailbox slaagt opnieuw via de bestaande OAuth/IMAP-taak of levert een exact extern restpunt.
|
||||||
|
- Projectstatus en deploymentdocumentatie beschrijven alleen het actuele releasepad als operationele waarheid.
|
||||||
|
verification:
|
||||||
|
- uv run pytest tests/unit/test_deployment_configuration.py
|
||||||
|
- ./scripts/codex_verify.sh
|
||||||
|
- Live Docker-netwerk-, mailbox-, container- en readinesssmokes
|
||||||
|
primary_paths:
|
||||||
|
- .gitea/workflows/release.yml
|
||||||
|
- docs/operations/GITEA_DEPLOYMENT.md
|
||||||
|
- docs/operations/UNRAID_DEPLOYMENT.md
|
||||||
|
- docs/ai/PROJECT_STATE.md
|
||||||
|
- tests/unit/test_deployment_configuration.py
|
||||||
|
result:
|
||||||
|
completed_at: '2026-08-12'
|
||||||
|
note: Oude main-pushdeploy verwijderd en run 3065 begrensd geannuleerd; Jobat OAuth/IMAP-herpoll groen met 61
|
||||||
|
duplicates en 0 fouten; Unraid persistent op conflictvrije 10.200.0.0/16→/24-pool gezet en live proefnetwerk
|
||||||
|
bewezen; na Docker-herstart alle vooraf actieve containers hersteld en geen unhealthy containers, VacatureRadar
|
||||||
|
publiek/intern healthy.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Projectstatus
|
# Projectstatus
|
||||||
|
|
||||||
- Laatst bijgewerkt: 2026-08-12
|
- Laatst bijgewerkt: 2026-08-12
|
||||||
- Repositoryversie: 0.3.16 publieke demo-hardening
|
- Repositoryversie: 0.3.17 immutable releaseherstel
|
||||||
- Uitvoeringsmodus: autonome backlog
|
- Uitvoeringsmodus: autonome backlog
|
||||||
- Eerste uitvoerbare taak: controleer met `python scripts/backlog.py next`
|
- Eerste uitvoerbare taak: controleer met `python scripts/backlog.py next`
|
||||||
|
|
||||||
@@ -44,10 +44,31 @@ Visuele demo-hardening `VR-229` op 2026-08-12:
|
|||||||
een live sessiesmoke bevestigde dashboard 200, zes demomatches, negen
|
een live sessiesmoke bevestigde dashboard 200, zes demomatches, negen
|
||||||
platformmailboxen, actieve ingress, nul oude policyfouten en geen
|
platformmailboxen, actieve ingress, nul oude policyfouten en geen
|
||||||
wachtwoord-maskplaceholder;
|
wachtwoord-maskplaceholder;
|
||||||
- de Gitea-releaseworkflow faalde tweemaal in stap `astral-sh/setup-uv@v6` en
|
- `VR-230` herstelde de Gitea-releaseworkflow door `setup-uv` op immutable commit
|
||||||
publiceerde daarom nog geen 0.3.16-registrymanifest. De bewezen immutable
|
`0880764` en uv op 0.11.12 te pinnen; de Astral-mirror verwijdert de eerdere
|
||||||
registryrelease blijft 0.3.15; runnerdiagnose en herpublicatie vereisen opnieuw
|
GitHub Releases-API-rate-limit;
|
||||||
bereikbare Unraid-beheertoegang. Volgende uitvoerbare backlogtaak: geen.
|
- vier lege, verweesde Docker-netwerken zijn gecontroleerd verwijderd nadat de
|
||||||
|
runner geen subnet meer kon reserveren; actieve productie- en compose-netwerken
|
||||||
|
bleven onaangeroerd;
|
||||||
|
- Gitea Actions-run 3062 publiceerde 0.3.17 met digest
|
||||||
|
`sha256:98f4b33db353c192967013818f7c82c4f171921f3d300645908d52680fde209f`
|
||||||
|
en artifact `release-evidence-v0.3.17` met SPDX-SBOM, checksums en release notes;
|
||||||
|
- een dedicated `read:package`-token geeft Unraid alleen pulltoegang. De
|
||||||
|
pre-deployback-up staat onder
|
||||||
|
`/mnt/user/appdata/VacatureRadar/local/backups/release-0.3.17-20260812T114510Z`;
|
||||||
|
- Unraid is live op de immutable digest gepind: container healthy, nul restarts,
|
||||||
|
interne liveness/readiness groen, publieke readiness 200 en runtimeversie 0.3.17.
|
||||||
|
- `VR-231` verwijderde de oude `main`-push-to-deployworkflow en annuleerde de
|
||||||
|
laatste onbeperkt wachtende run 3065; alleen semantische tags publiceren nog;
|
||||||
|
- Jobat is via de bestaande OAuth/IMAP-taak geforceerd herhaald: 61 duplicaten
|
||||||
|
correct herkend, nul fouten en de foutstatus volledig gewist;
|
||||||
|
- Unraid gebruikt persistent `10.200.0.0/16,size=24`; een live proefnetwerk kreeg
|
||||||
|
`10.200.1.0/24` en werd daarna verwijderd. Na de gecontroleerde Docker-herstart
|
||||||
|
zijn alle 127 vooraf actieve containers hersteld; VacatureRadar, Grimmory en
|
||||||
|
MeTube zijn healthy en er zijn geen unhealthy of herstartende containers;
|
||||||
|
- serverback-ups bewaren de eerdere `docker.cfg`, de running-containersnapshot,
|
||||||
|
de Grimmory-template en de Gitea-database vóór de begrensde runannulering.
|
||||||
|
Volgende uitvoerbare backlogtaak: geen.
|
||||||
|
|
||||||
README-update op 2026-07-30:
|
README-update op 2026-07-30:
|
||||||
|
|
||||||
@@ -440,10 +461,13 @@ VR-208-herverificatie op 2026-07-22:
|
|||||||
## Deploymentstatus
|
## Deploymentstatus
|
||||||
|
|
||||||
- `main` is via de bestaande Gitea-SSH-sleutel naar `NuklearRabbit/VacatureRadar` gepusht.
|
- `main` is via de bestaande Gitea-SSH-sleutel naar `NuklearRabbit/VacatureRadar` gepusht.
|
||||||
- De applicatie draait op de Unraid-server via `http://192.168.10.150:1226/` als één Dockerman-container; Supervisor bewaakt intern PostgreSQL 17, Redis, web, worker en scheduler.
|
- De applicatie draait op de Unraid-server via de geconfigureerde private host en poort `1226` als één Dockerman-container; Supervisor bewaakt intern PostgreSQL 17, Redis, web, worker en scheduler.
|
||||||
- De Dockerman-tegel gebruikt de lokale VacatureRadar-favicon en opent rechtstreeks de WebUI op poort 1226.
|
- De Dockerman-tegel gebruikt de lokale VacatureRadar-favicon en opent rechtstreeks de WebUI op poort 1226.
|
||||||
- De server-side `.env` heeft rechten `0600`; gegenereerde secrets zijn niet naar Git of logs gekopieerd.
|
- De server-side `.env` heeft rechten `0600`; gegenereerde secrets zijn niet naar Git of logs gekopieerd.
|
||||||
- De self-hosted Gitea Actions-runner is niet actief. Deze sessie gebruikte daarom een directe, commitgebonden SSH-deploy; push-to-deploy vereist nog runnerherstel/registratie.
|
- Historisch bewijs (2026-07-22, inmiddels vervangen): de self-hosted runner was
|
||||||
|
toen niet actief en die sessie gebruikte een directe SSH-deploy. Sinds 0.3.17
|
||||||
|
is uitsluitend de taggestuurde immutable registryrelease operationeel; een
|
||||||
|
gewone push naar `main` deployt bewust niet.
|
||||||
- Deze historische LAN-beperking is op 2026-07-29 opgeheven: het publieke domein, reverse proxy/TLS, `DJANGO_DEBUG=0` en secure cookies zijn live gevalideerd.
|
- Deze historische LAN-beperking is op 2026-07-29 opgeheven: het publieke domein, reverse proxy/TLS, `DJANGO_DEBUG=0` en secure cookies zijn live gevalideerd.
|
||||||
|
|
||||||
## Laatste uitgevoerde backlogtaak
|
## Laatste uitgevoerde backlogtaak
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Finale acceptance 0.3.15
|
# Finale acceptance 0.3.17
|
||||||
|
|
||||||
Status: productie geaccepteerd op 2026-07-30.
|
Status: productie geaccepteerd op 2026-08-12.
|
||||||
|
|
||||||
## Bewijs
|
## Bewijs
|
||||||
|
|
||||||
@@ -22,6 +22,17 @@ Status: productie geaccepteerd op 2026-07-30.
|
|||||||
Het artifact bevat een geverifieerde SPDX-SBOM, checksums en release notes.
|
Het artifact bevat een geverifieerde SPDX-SBOM, checksums en release notes.
|
||||||
- Unraid is op die digest gepind; pull, health/readiness, rollback naar `0.3.14`
|
- Unraid is op die digest gepind; pull, health/readiness, rollback naar `0.3.14`
|
||||||
en herstel naar `0.3.15` zijn live geslaagd.
|
en herstel naar `0.3.15` zijn live geslaagd.
|
||||||
|
- Gitea Actions-run 3062 publiceerde `v0.3.17` nadat de releasebootstrap op een
|
||||||
|
immutable `setup-uv`-commit en uv 0.11.12 werd gepind. De uv-download gebruikt
|
||||||
|
de Astral-mirror en vereist geen GitHub Releases-API.
|
||||||
|
- Het checksum-geldige artifact `release-evidence-v0.3.17` bevat image-digest,
|
||||||
|
SPDX-SBOM, checksums en release notes. De gepubliceerde digest is
|
||||||
|
`sha256:98f4b33db353c192967013818f7c82c4f171921f3d300645908d52680fde209f`.
|
||||||
|
- De checksum-geldige pre-deployback-up staat onder
|
||||||
|
`local/backups/release-0.3.17-20260812T114510Z`. Unraid gebruikt een beperkt
|
||||||
|
`read:package`-token en is op de volledige registrydigest gepind.
|
||||||
|
- De 0.3.17-container is healthy met nul restarts; interne liveness en readiness,
|
||||||
|
database, cache en publieke readiness zijn groen en de runtime meldt 0.3.17.
|
||||||
|
|
||||||
## Uitkomst
|
## Uitkomst
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +1,39 @@
|
|||||||
# Gitea push-to-deploy (self-hosted, geen handmatige variabelenvulling)
|
# Gitea immutable releasepad
|
||||||
|
|
||||||
Push naar `main` of `master` triggert automatisch:
|
Een push naar `main` publiceert geen productiecode. Alleen een expliciete semantische
|
||||||
|
tag `v*.*.*` start `.gitea/workflows/release.yml`. De runner:
|
||||||
|
|
||||||
- checkout op de server runner
|
1. verifieert de volledige repository;
|
||||||
- `bash scripts/deploy_docker.sh`
|
2. bouwt de Unraid-image met commit- en versielabels;
|
||||||
- deploy met `docker compose up -d --build`
|
3. publiceert die image naar de private Gitea-containerregistry;
|
||||||
|
4. genereert een SPDX-SBOM, digestbestand, checksums en release notes.
|
||||||
|
|
||||||
Deze workflow gebruikt defaults en hoeft niet te wachten op repo-secrets voor host/ssh/credentials.
|
Productie wordt daarna expliciet op de volledige `versie@sha256:digest` gepind.
|
||||||
|
Hierdoor kan een gewone documentatie- of codepush nooit ongemerkt productie
|
||||||
|
overschrijven en bestaat geen parallel mutable push-to-deploypad meer.
|
||||||
|
|
||||||
## Vereiste eenmalige setup op de server
|
## Vereiste runnerconfiguratie
|
||||||
|
|
||||||
1. Start en registreer een self-hosted Gitea-runner voor deze repo.
|
- De Gitea-runner accepteert label `ubuntu-latest` en kan jobcontainers starten.
|
||||||
2. Zorg dat die runner Docker/Compose kan draaien in de projectmap waar de runner draait.
|
- `REGISTRY_USER` en `REGISTRY_TOKEN` zijn repositorysecrets met uitsluitend de
|
||||||
3. Laat éénmaal dit script draaien op de server:
|
noodzakelijke package-schrijfrechten.
|
||||||
|
- Unraid gebruikt een afzonderlijk `read:package`-token om gepubliceerde images te
|
||||||
|
pullen; dat token staat alleen in de root-Dockerconfig op de server.
|
||||||
|
- De runnerhost heeft voldoende vrije Docker-address-pools voor tijdelijke
|
||||||
|
jobnetwerken; volg daarvoor de netwerksectie in
|
||||||
|
[Unraid-deployment](UNRAID_DEPLOYMENT.md#docker-netwerkcapaciteit).
|
||||||
|
|
||||||
```bash
|
## Publiceren en uitrollen
|
||||||
bash scripts/deploy_docker.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Daarna is het gedrag volledig push-only:
|
1. Maak en verifieer een database- en configuratieback-up.
|
||||||
|
2. Push de geverifieerde releasecommit naar `main`.
|
||||||
|
3. Maak en push de semantische tag.
|
||||||
|
4. Wacht tot de Gitea-releasejob groen is en verifieer de artifactchecksums.
|
||||||
|
5. Pull op Unraid de gepubliceerde volledige digest.
|
||||||
|
6. Zet `VACATURERADAR_IMAGE` op `versie@sha256:digest` en herstart Compose met
|
||||||
|
`--no-build --force-recreate`.
|
||||||
|
7. Controleer intern en publiek `/health/live/` en `/health/ready/`, runtimeversie,
|
||||||
|
containerhealth en restartteller.
|
||||||
|
|
||||||
- `git push` naar `main` of `master` → automatische deploy
|
PostgreSQL, Redis en Ollama blijven niet publiek bereikbaar. Bewaar de vorige
|
||||||
|
digest totdat minstens één volledige schedulercyclus groen is.
|
||||||
## Defaults
|
|
||||||
|
|
||||||
- `APP_HOST`: hostname van de server (fallback: `hostname`)
|
|
||||||
- `APP_SCHEME`: `http`
|
|
||||||
- `DJANGO_DEBUG`: afgeleid uit `APP_SCHEME`
|
|
||||||
- `0` als `APP_SCHEME=https`
|
|
||||||
- `1` als `APP_SCHEME=http`
|
|
||||||
- `DEPLOY_COMPOSE_FILE`: `docker-compose.yml`
|
|
||||||
- `APP_ORIGINS`, `APP_HOSTS`, `APP_PORT`: optioneel en veilig overnemen als op runner gezet
|
|
||||||
|
|
||||||
## Endpoint na deploy
|
|
||||||
|
|
||||||
- `http://<runner-host>:1226/health/ready/`
|
|
||||||
- `http://<runner-host>:1226/health/live/`
|
|
||||||
|
|
||||||
Voor productie: zet later op de runner de gewenste runtime-omgeving (bijv. reverse proxy + TLS) en herstart push.
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ Gebruik vanaf een beheerwerkstation altijd een benoemde SSH-hostalias met een af
|
|||||||
|
|
||||||
```sshconfig
|
```sshconfig
|
||||||
Host unraid-itworx
|
Host unraid-itworx
|
||||||
HostName 192.168.10.150
|
HostName server.example.test
|
||||||
Port 22
|
Port 22
|
||||||
User root
|
User root
|
||||||
IdentityFile ~/.ssh/itworx_unraid_deploy
|
IdentityFile ~/.ssh/itworx_unraid_deploy
|
||||||
@@ -168,6 +168,23 @@ Herstart web, worker en scheduler. Open daarna **Bronnen → Platformmailboxen**
|
|||||||
|
|
||||||
Voor een immutable registryrelease zet je `VACATURERADAR_IMAGE=gitea.itworx.tech/jens/vacatureradar:<versie>@sha256:<digest>` en start je met `docker compose -f docker-compose.unraid.yml up -d --no-build`.
|
Voor een immutable registryrelease zet je `VACATURERADAR_IMAGE=gitea.itworx.tech/jens/vacatureradar:<versie>@sha256:<digest>` en start je met `docker compose -f docker-compose.unraid.yml up -d --no-build`.
|
||||||
|
|
||||||
|
## Docker-netwerkcapaciteit
|
||||||
|
|
||||||
|
Deze Unraid-host draait veel geïsoleerde Compose-netwerken. De ingebouwde
|
||||||
|
Dockerpools delen grote `/16`- en `/20`-netwerken uit en kunnen daardoor opraken
|
||||||
|
terwijl er nog ruim voldoende private adresruimte bestaat. De live host gebruikt
|
||||||
|
daarom persistent in `/boot/config/docker.cfg`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
DOCKER_OPTS="--default-address-pool base=10.200.0.0/16,size=24"
|
||||||
|
```
|
||||||
|
|
||||||
|
Dat levert 256 nieuwe `/24`-netwerken en overlapt niet met LAN `192.168.10.0/24`,
|
||||||
|
WireGuard `10.253.0.0/16` of bestaande Docker-netwerken. De instelling geldt
|
||||||
|
alleen voor nieuw aangemaakte netwerken; bestaande subnets veranderen niet.
|
||||||
|
Maak vóór wijziging een kopie van `docker.cfg`, herstart Docker éénmaal en bewijs
|
||||||
|
de pool met een tijdelijk netwerk dat na inspectie meteen wordt verwijderd.
|
||||||
|
|
||||||
Voor sleutelrotatie zet je `nieuwe-sleutel,oude-sleutel` in `MAILBOX_CREDENTIAL_KEYS`, herstart je de processen en draai je:
|
Voor sleutelrotatie zet je `nieuwe-sleutel,oude-sleutel` in `MAILBOX_CREDENTIAL_KEYS`, herstart je de processen en draai je:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ Django/Celery
|
|||||||
| T-19 | Automatisch solliciteren/massamail | reputatie/privacy/juridisch risico | geen submitendpoint/task, expliciete ADR en non-goal | codezoekreview, AC-043 |
|
| T-19 | Automatisch solliciteren/massamail | reputatie/privacy/juridisch risico | geen submitendpoint/task, expliciete ADR en non-goal | codezoekreview, AC-043 |
|
||||||
| T-20 | Kwaadaardig bestand in sollicitatiedossier | host/browsercompromis | uploads nog niet actief; vóór implementatie allowlist, sniffing, size limit, niet-uitvoerbare opslag vereist | `VR-113`, nieuwe threat review |
|
| T-20 | Kwaadaardig bestand in sollicitatiedossier | host/browsercompromis | uploads nog niet actief; vóór implementatie allowlist, sniffing, size limit, niet-uitvoerbare opslag vereist | `VR-113`, nieuwe threat review |
|
||||||
| T-21 | Back-up bevat secrets/PII | langdurig datalek | encryptie, gescheiden opslag, korte retentie, herstelprocedure | runbook en hersteltest |
|
| T-21 | Back-up bevat secrets/PII | langdurig datalek | encryptie, gescheiden opslag, korte retentie, herstelprocedure | runbook en hersteltest |
|
||||||
| T-22 | Supply-chainpackage/image | code execution | exacte versies/lockfile, beperkte dependencies, pinned baseimages/digests en scans gepland | CI, `VR-115` |
|
| T-22 | Supply-chainpackage/image | code execution | exacte versies/lockfile, beperkte dependencies, pinned baseimages/digests, taggestuurde immutable release als enig productiepad, gescheiden package read/write-tokens en SBOM/checksums | CI, `VR-115`, `VR-230`, `VR-231` |
|
||||||
| T-23 | Onbevoegde admin op thuisnetwerk | volledige datatoegang | uniek wachtwoord, TLS/VPN, geen defaultcredentials, sessiebeveiliging | Unraidchecklist |
|
| T-23 | Onbevoegde admin op thuisnetwerk | volledige datatoegang | uniek wachtwoord, TLS/VPN, geen defaultcredentials, sessiebeveiliging | Unraidchecklist |
|
||||||
| T-24 | Source terms wijzigen | ongewenste voortgezette crawling | reviewdatum, source health en policy expiry gepland | `VR-102`, `VR-112` |
|
| T-24 | Source terms wijzigen | ongewenste voortgezette crawling | reviewdatum, source health en policy expiry gepland | `VR-102`, `VR-112` |
|
||||||
| T-31 | Sollicitatiedossier-export bevat niet-gewenste payload | data-lek of onbedoeld dossieroverdragen | export bevat alleen het gekozen dossier, ZIP-inhoud is beperkt tot snapshot/tijdlijn/print-HTML, bestandsnaam is geslugified zonder padseparators | `tests/integration/test_applications.py` |
|
| T-31 | Sollicitatiedossier-export bevat niet-gewenste payload | data-lek of onbedoeld dossieroverdragen | export bevat alleen het gekozen dossier, ZIP-inhoud is beperkt tot snapshot/tijdlijn/print-HTML, bestandsnaam is geslugified zonder padseparators | `tests/integration/test_applications.py` |
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
|
|||||||
| NFR-006 | I | offline pytest + coveragegate, inclusief platformbewuste productieconfiguratietests | VR-114 e2e; `tests/unit/test_public_configuration.py`; VR-225/226 |
|
| NFR-006 | I | offline pytest + coveragegate, inclusief platformbewuste productieconfiguratietests | VR-114 e2e; `tests/unit/test_public_configuration.py`; VR-225/226 |
|
||||||
| NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 |
|
| NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 |
|
||||||
| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie, zelfstandig VacatureRadar-productmerk, lokale ITWorx-ontwikkelaarscredit, toegankelijke interactieve radarillustratie en actuele user-first productdocumentatie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `tests/integration/test_views.py`, `artifacts/visual-validation/`, negen beelden in `docs/screenshots/readme/`, VR-209–224/226 |
|
| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie, zelfstandig VacatureRadar-productmerk, lokale ITWorx-ontwikkelaarscredit, toegankelijke interactieve radarillustratie en actuele user-first productdocumentatie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `tests/integration/test_views.py`, `artifacts/visual-validation/`, negen beelden in `docs/screenshots/readme/`, VR-209–224/226 |
|
||||||
| NFR-009 | I | lokale SQLite, configureerbare eigenaarbranding, Docker/Unraidconfig, publieke URL-helper, Nginx Proxy Manager-runbook, gevalideerde SSH-deployalias, release-smoke en restore | `tests/unit/test_deployment_configuration.py`, `tests/unit/test_public_configuration.py`, VR-117, VR-217/218/225 afgerond |
|
| NFR-009 | I | lokale SQLite, configureerbare eigenaarbranding, Docker/Unraidconfig, publieke URL-helper, Nginx Proxy Manager-runbook, gevalideerde SSH-deployalias, API-onafhankelijke immutable releasebootstrap zonder parallel push-to-deploypad, begrensde Docker-address pool, release-smoke en restore | `tests/unit/test_deployment_configuration.py`, `tests/unit/test_public_configuration.py`, VR-117, VR-217/218/225/230/231 afgerond |
|
||||||
| NFR-010 | I | `apps/sources/services/health.py`, `apps/sources/tasks.py`, `apps/core/views.py`, `config/settings.py` | `tests/integration/test_source_health.py` | VR-112 observability |
|
| NFR-010 | I | `apps/sources/services/health.py`, `apps/sources/tasks.py`, `apps/core/views.py`, `config/settings.py` | `tests/integration/test_source_health.py` | VR-112 observability |
|
||||||
|
|
||||||
## Systeemacceptatie
|
## Systeemacceptatie
|
||||||
@@ -86,6 +86,8 @@ Iedere backlogtaak die een requirement wijzigt, werkt in dezelfde commit deze ma
|
|||||||
## Aanvullende traceability-opmerking
|
## Aanvullende traceability-opmerking
|
||||||
- VR-228 levert release 0.3.14 met een fail-closed disposable PostgreSQL-benchmark, run-lokale importcaches, gebundelde veldprovenance en ongewijzigde score-snapshotcopy. De officiële drie iteraties bewijzen 3.264 queries per 250 items, parser 12/12, dedupeprecision/recall 1,0 en nul rankingchurn; bewijs staat in `docs/audit/IMPORT_PERFORMANCE_*.md` en het machineleesbare artifact.
|
- VR-228 levert release 0.3.14 met een fail-closed disposable PostgreSQL-benchmark, run-lokale importcaches, gebundelde veldprovenance en ongewijzigde score-snapshotcopy. De officiële drie iteraties bewijzen 3.264 queries per 250 items, parser 12/12, dedupeprecision/recall 1,0 en nul rankingchurn; bewijs staat in `docs/audit/IMPORT_PERFORMANCE_*.md` en het machineleesbare artifact.
|
||||||
- VR-229 houdt de publieke demo representatief door fictieve vacatures, scores, mailboxkoppelingen en opvolgdatums bij iedere demosessie idempotent te herstellen. Mailboxingress is uitgesloten van URL-fetchplanning en operationele UI-copy onderscheidt een actief profiel van bron- en systeemgezondheid.
|
- VR-229 houdt de publieke demo representatief door fictieve vacatures, scores, mailboxkoppelingen en opvolgdatums bij iedere demosessie idempotent te herstellen. Mailboxingress is uitgesloten van URL-fetchplanning en operationele UI-copy onderscheidt een actief profiel van bron- en systeemgezondheid.
|
||||||
|
- VR-230 pint `setup-uv` en uv exact, vermijdt de gelimiteerde GitHub Releases-API via de Astral-mirror en bewijst publicatie plus live pinning van de immutable 0.3.17-registrydigest.
|
||||||
|
- VR-231 verwijdert de hangende mutable deployroute, vergroot de Unraid-netwerkcapaciteit conflictvrij naar 256 `/24`-netwerken en bewijst na een volledige Docker-herstart dat alle vooraf actieve containers en VacatureRadar gezond zijn; de resterende Jobat-poll is opnieuw foutvrij geslaagd.
|
||||||
- VR-227 professionaliseert release 0.3.13 integraal: gecentreerd ultrawideframe, mobiele gastbanner en verticale pipeline, begrensde vacaturepaginering, verplichte zes-viewport-Playwrightgate zonder skips, echte runtimeheartbeat, volledige generieke parserbenchmark en SBOM-generatie. Bewijs staat in `docs/audit/`, de E2E-/auth-/runtime-/adaptertests en `USER_INPUT_REQUIRED.md`.
|
- VR-227 professionaliseert release 0.3.13 integraal: gecentreerd ultrawideframe, mobiele gastbanner en verticale pipeline, begrensde vacaturepaginering, verplichte zes-viewport-Playwrightgate zonder skips, echte runtimeheartbeat, volledige generieke parserbenchmark en SBOM-generatie. Bewijs staat in `docs/audit/`, de E2E-/auth-/runtime-/adaptertests en `USER_INPUT_REQUIRED.md`.
|
||||||
- VR-102 is gerealiseerd met auditbare policyreviews (`SourcePolicyReview`), robotscache met TTL/size/SSRF-controles en fail-closed policy-gating op verlopen of conflicterende reviews.
|
- VR-102 is gerealiseerd met auditbare policyreviews (`SourcePolicyReview`), robotscache met TTL/size/SSRF-controles en fail-closed policy-gating op verlopen of conflicterende reviews.
|
||||||
- VR-107 is gerealiseerd met `apps/sources/views.py`, `apps/sources/services/manual_import.py`, `templates/sources/list.html`, `static/js/manual_import.js` en bijhorende unit/integration-tests.
|
- VR-107 is gerealiseerd met `apps/sources/views.py`, `apps/sources/services/manual_import.py`, `templates/sources/list.html`, `static/js/manual_import.js` en bijhorende unit/integration-tests.
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ dependencies = [
|
|||||||
"defusedxml==0.7.1",
|
"defusedxml==0.7.1",
|
||||||
"gunicorn==26.0.0",
|
"gunicorn==26.0.0",
|
||||||
"whitenoise==6.11.0",
|
"whitenoise==6.11.0",
|
||||||
"cryptography==49.0.0",
|
"cryptography==50.0.0",
|
||||||
"msal==1.37.0",
|
"msal==1.37.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -145,15 +145,22 @@ def test_demo_login_logs_in_and_seeds_environment(client):
|
|||||||
assert "minstens één import actief" in sources.content.decode("utf-8")
|
assert "minstens één import actief" in sources.content.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def test_demo_login_is_idempotent(client):
|
def test_demo_login_is_idempotent(client, monkeypatch):
|
||||||
from datetime import timedelta
|
from datetime import UTC, datetime, timedelta
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from apps.jobs.models import Application, JobPosting
|
from apps.jobs.models import Application, JobPosting
|
||||||
|
from apps.jobs.services import demo_seed
|
||||||
from apps.profiles.models import SearchProfile
|
from apps.profiles.models import SearchProfile
|
||||||
from apps.sources.models import MailboxConnection, Source
|
from apps.sources.models import MailboxConnection, Source
|
||||||
|
|
||||||
|
# 22:30 UTC is already the following calendar day in Europe/Brussels.
|
||||||
|
# Freezing this boundary prevents UTC `.date()` calls from creeping back in.
|
||||||
|
near_local_midnight = datetime(2026, 9, 2, 22, 30, tzinfo=UTC)
|
||||||
|
monkeypatch.setattr(demo_seed.timezone, "now", lambda: near_local_midnight)
|
||||||
|
expected_local_day = timezone.localdate(near_local_midnight)
|
||||||
|
|
||||||
client.post(reverse("demo-login"))
|
client.post(reverse("demo-login"))
|
||||||
first = JobPosting.objects.count()
|
first = JobPosting.objects.count()
|
||||||
demo_user = get_user_model().objects.get(username=settings.DEMO_USERNAME)
|
demo_user = get_user_model().objects.get(username=settings.DEMO_USERNAME)
|
||||||
@@ -172,8 +179,8 @@ def test_demo_login_is_idempotent(client):
|
|||||||
job.refresh_from_db()
|
job.refresh_from_db()
|
||||||
application.refresh_from_db()
|
application.refresh_from_db()
|
||||||
assert job.status == JobPosting.Status.ACTIVE
|
assert job.status == JobPosting.Status.ACTIVE
|
||||||
assert job.last_seen.date() == timezone.localdate()
|
assert timezone.localdate(job.last_seen) == expected_local_day
|
||||||
assert application.follow_up_date > timezone.localdate()
|
assert application.follow_up_date > expected_local_day
|
||||||
assert profile.scores.count() == 6
|
assert profile.scores.count() == 6
|
||||||
assert MailboxConnection.objects.filter(user=demo_user, enabled=True).count() == 9
|
assert MailboxConnection.objects.filter(user=demo_user, enabled=True).count() == 9
|
||||||
assert Source.objects.filter(source_type=Source.Type.EMAIL, failure_count=0).count() >= 9
|
assert Source.objects.filter(source_type=Source.Type.EMAIL, failure_count=0).count() >= 9
|
||||||
|
|||||||
@@ -136,3 +136,11 @@ def test_release_uv_install_is_immutable_and_does_not_require_github_api() -> No
|
|||||||
assert "astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0" in workflow
|
assert "astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0" in workflow
|
||||||
assert 'version: "0.11.12"' in workflow
|
assert 'version: "0.11.12"' in workflow
|
||||||
assert "astral-sh/setup-uv@v6" not in workflow
|
assert "astral-sh/setup-uv@v6" not in workflow
|
||||||
|
|
||||||
|
|
||||||
|
def test_release_is_the_only_gitea_deployment_trigger() -> None:
|
||||||
|
workflows = ROOT / ".gitea" / "workflows"
|
||||||
|
|
||||||
|
assert not (workflows / "deploy.yml").exists()
|
||||||
|
release = yaml.safe_load((workflows / "release.yml").read_text(encoding="utf-8"))
|
||||||
|
assert release[True] == {"push": {"tags": ["v*.*.*"]}}
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ def test_configure_public_url_updates_only_public_security_settings(tmp_path: Pa
|
|||||||
env_file.write_text(
|
env_file.write_text(
|
||||||
"DJANGO_SECRET_KEY=keep-this-secret\n"
|
"DJANGO_SECRET_KEY=keep-this-secret\n"
|
||||||
"POSTGRES_PASSWORD=keep-this-password\n"
|
"POSTGRES_PASSWORD=keep-this-password\n"
|
||||||
"DJANGO_ALLOWED_HOSTS=192.168.10.150,localhost\n"
|
"DJANGO_ALLOWED_HOSTS=vacatureradar.local,localhost\n"
|
||||||
"DJANGO_CSRF_TRUSTED_ORIGINS=http://192.168.10.150:1226\n",
|
"DJANGO_CSRF_TRUSTED_ORIGINS=http://vacatureradar.local:1226\n",
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ def test_configure_public_url_updates_only_public_security_settings(tmp_path: Pa
|
|||||||
assert "DJANGO_DEBUG=0" in content
|
assert "DJANGO_DEBUG=0" in content
|
||||||
assert "vacatureradar.itworx.tech" in content
|
assert "vacatureradar.itworx.tech" in content
|
||||||
assert (
|
assert (
|
||||||
"DJANGO_CSRF_TRUSTED_ORIGINS=http://192.168.10.150:1226,https://vacatureradar.itworx.tech"
|
"DJANGO_CSRF_TRUSTED_ORIGINS=http://vacatureradar.local:1226,https://vacatureradar.itworx.tech"
|
||||||
) in content
|
) in content
|
||||||
assert "CACHE_URL=redis://127.0.0.1:6379/1" in content
|
assert "CACHE_URL=redis://127.0.0.1:6379/1" in content
|
||||||
assert "TRUSTED_PROXY_CIDRS=172.18.0.0/16" in content
|
assert "TRUSTED_PROXY_CIDRS=172.18.0.0/16" in content
|
||||||
|
|||||||
@@ -141,6 +141,68 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "charset-normalizer"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e5/3f/143b048436775b0f76ac3eec145c019e8173ccc2885c8f20319b996d5e83/charset_normalizer-3.5.1.tar.gz", hash = "sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3", size = 171764, upload-time = "2026-08-15T08:20:44.807Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/27/78873dc8b6a56357517b74b6bb9568b80450e7bb4f6ef7e3fa9d22aa0bd7/charset_normalizer-3.5.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f", size = 344456, upload-time = "2026-08-15T08:17:10.072Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/4c/be49ada26b1f0232d57aa89bbebf997a5cc2332a5616b6eca26ff680044d/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa", size = 238530, upload-time = "2026-08-15T08:17:11.563Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/84/6f1290fa07ae6978d3960caa3eb1b8019bf9284ab7c2297b00c099ef4250/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369", size = 230200, upload-time = "2026-08-15T08:17:12.919Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e7/a0/47b18adeed31c8f16ba9700f32c1b18594cfa09f47eb672a488c273c22bf/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893", size = 262222, upload-time = "2026-08-15T08:17:14.571Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/fe/341861ac118dae06f3ec0eb487488af52128f2ef2faf0b11003944d22259/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0", size = 258951, upload-time = "2026-08-15T08:17:16.158Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6f/89/bb5108dc6c3651dca963f2b0a3ba19bbcb370c94e1b6d3e0e844a58e6dca/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08", size = 248801, upload-time = "2026-08-15T08:17:17.683Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b1/ba/ef83ae3aca816393decfa3530976f38a79812d707b80b580ac33b83f9877/charset_normalizer-3.5.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada", size = 244070, upload-time = "2026-08-15T08:17:19.191Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f6/0b/c5292a2462d69b7378ea89793bbb5b2b6fcf6f7dd6d1667f9619094ad553/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9", size = 240110, upload-time = "2026-08-15T08:17:20.547Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/46/22/111e5be3b740d5c2a5bfcedb3d237b6591e5c2e82ae9d6ffcb121fe0909c/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e", size = 232836, upload-time = "2026-08-15T08:17:21.895Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/d2/d2aad6fe0dbb44b194bf3becb60f5a0ac48446ade999a47fe7bb41eb09a7/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6", size = 262712, upload-time = "2026-08-15T08:17:23.727Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/5a/337e4663a5eae6de99db940ee8066d4145caafb61327db62deda15313cce/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf", size = 242977, upload-time = "2026-08-15T08:17:25.157Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ca/85/f82f8a92e31c7519410e2e1afdc630f28ec47490ce2c09a11c1a43cbb459/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71", size = 260207, upload-time = "2026-08-15T08:17:26.602Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/52/643d11ffd60e9ac2fd1fb87e167a19285b9eefeff4a40e63c87cbfbeab36/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573", size = 250562, upload-time = "2026-08-15T08:17:27.971Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/16/46556278c2168d12df9da7fede5dc6fc70e60301b26a82bbeec238c9cfe3/charset_normalizer-3.5.1-cp312-cp312-win32.whl", hash = "sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2", size = 178507, upload-time = "2026-08-15T08:17:29.277Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9d/7a/4c6c298171e6b3e745633180ff59350fc0ca0db1ffd28df1e369e0579f71/charset_normalizer-3.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2", size = 200551, upload-time = "2026-08-15T08:17:30.668Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/d7/eb95a042f0dd22e304b0b6472b154f3546a1a039a9ee89ccb2a7f61591fc/charset_normalizer-3.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a", size = 180700, upload-time = "2026-08-15T08:17:32.028Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/61/2cb6ad133dbbb449fa2d37ccae973232f4827e799af258d15e589a3d1e9e/charset_normalizer-3.5.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9", size = 211584, upload-time = "2026-08-15T08:17:33.597Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/57/a305c968be1ca13f3dd1b32f445877e97addf55d80b65c7cb35fac82b777/charset_normalizer-3.5.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491", size = 223359, upload-time = "2026-08-15T08:17:35.022Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/0a/d3646670292ce8d8f8cc11ac067d44885e697a5591f57a9221128da5e7b3/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7", size = 194464, upload-time = "2026-08-15T08:17:36.452Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/de/93/d51ec556e01042fed6f993ea859311bc7917b466684182fbbceb6ca24762/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e", size = 197676, upload-time = "2026-08-15T08:17:37.819Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a4/a0/562247944386f7d4ef94467e84876600cc1e0f1b93239aaa9213d2bc3cbd/charset_normalizer-3.5.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d", size = 340473, upload-time = "2026-08-15T08:17:39.303Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/e7/1d994be1b93d41e9502b8b0460eaa88a1dd8df335df415db87d6c3e91ab2/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a", size = 240156, upload-time = "2026-08-15T08:17:40.66Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/53/27923ce5cc6cbccb832037b27dca98882d9c53e9b69e866bbbef4aae7fc8/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe", size = 228246, upload-time = "2026-08-15T08:17:42.003Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ce/48/5a97e84d63af1d55c07439cb80e56d99a8efb4295700eb4e18c0d1615d2c/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac", size = 263660, upload-time = "2026-08-15T08:17:43.627Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/c2/071575791dcc88316c0a9a65ce38897a82e4cfe4a325f0f7fe1b1ac47bcf/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e", size = 260354, upload-time = "2026-08-15T08:17:45.094Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fb/af/63240b0c0248c075c2535a1f1bd992821d8251b9f173abc13329661d09e4/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3", size = 250638, upload-time = "2026-08-15T08:17:46.496Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4d/66/70dfad64f15be09c15ccfee81330a7e515895dbe296dd23114e9a231268a/charset_normalizer-3.5.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876", size = 244583, upload-time = "2026-08-15T08:17:47.963Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c0/24/ef36367d38b9ddd4bccbf72888c342e8de1f5ae506fa0b2dcf970e2732a1/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6", size = 242038, upload-time = "2026-08-15T08:17:49.481Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/db/ab/55e683ba0fff2e43adafc10daa3001eac90fdaa419a97227d5a7067eedde/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2", size = 233677, upload-time = "2026-08-15T08:17:50.845Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bd/67/0f40eaf8d1b6e7cf15e82382a2965efaca787fc1c2794b7021d37aaf5036/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591", size = 264491, upload-time = "2026-08-15T08:17:52.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5c/64/12b4c2a11ee8df4fcc518c78b0d93e3a92bd3d5253d1617ce74ff0e8c7ef/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c", size = 245196, upload-time = "2026-08-15T08:17:54.023Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/2e/651d910af6d0fba325eee1cda37ec5443462ed25360e666c144166eb6091/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c", size = 261660, upload-time = "2026-08-15T08:17:55.491Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/90/c6/b09e05e6db7f64338e0dc067c79577b1138da86c1e38369096851d96be88/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f", size = 252618, upload-time = "2026-08-15T08:17:57.025Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/4e/362d4f9fdcdf5556fb2aa3ce7d4a58ebce03ed1ff03aa1d9aca8d02f13f3/charset_normalizer-3.5.1-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4", size = 140362, upload-time = "2026-08-15T08:17:58.425Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/d4/703be739b26acce318bd29eb3b25b7209e1b1f527f9eae3d1f1f01fdde2b/charset_normalizer-3.5.1-cp313-cp313-win32.whl", hash = "sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3", size = 177755, upload-time = "2026-08-15T08:18:00.037Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/33/56d97ade41c8db611e727168c52ae46c9224c362ec28d4b65d7e9869e8da/charset_normalizer-3.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6", size = 199295, upload-time = "2026-08-15T08:18:01.506Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/75/5b20dd1e6573a01a08158fe104104fa2c8abf941745596954185726cd46c/charset_normalizer-3.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0", size = 179856, upload-time = "2026-08-15T08:18:02.929Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/97/fb4e82231aba271ffd775a1b4993b0defc4e3059f286ae41d9433409fe85/charset_normalizer-3.5.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2", size = 331467, upload-time = "2026-08-15T08:19:50.959Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/2f/fe3f187327aac18e2d54e9d2b08e15d27bf9b642d9e51c219f130fc34d1a/charset_normalizer-3.5.1-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99", size = 253057, upload-time = "2026-08-15T08:19:52.654Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d7/c7/9e48cee5c161fe24da823b61bf381921d77cb994a0a4de148e95018c1984/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2", size = 240930, upload-time = "2026-08-15T08:19:54.163Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/e0/716601f3cc69be7b198951150c75ead1ece33c3c8036ff6ffa46029659a0/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235", size = 230822, upload-time = "2026-08-15T08:19:55.807Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d3/05/71bfc5caa0abcc45aea1f6a4d50ac68e59605ddc7666fe8494f4cd229665/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598", size = 260037, upload-time = "2026-08-15T08:19:57.312Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c3/92/de7e32ed05341e7a9c4c877c318418197b7f2d66a3b68d561bf2ac57ca3e/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96", size = 255097, upload-time = "2026-08-15T08:19:59.056Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f5/7b/ade0a122600319dfa0b1000ab0f9731c94a817904cf3c5de408c73a4ede7/charset_normalizer-3.5.1-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962", size = 250166, upload-time = "2026-08-15T08:20:00.612Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/75/9c/019fbb9f4834491a160951349b1a3714439376f66e5f7cf18b4f18f0c7aa/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3", size = 241821, upload-time = "2026-08-15T08:20:02.321Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/b8/11d4840bfc99330cc7fbcc2681ee5a044553a6e77655508d8f9b2bff7b34/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950", size = 232529, upload-time = "2026-08-15T08:20:04.008Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/96/2b3a21492d9f65171ac75d872f5018260013d00bfa0ff70ec9f179148cbd/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8", size = 260348, upload-time = "2026-08-15T08:20:05.877Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/aa/a69a2028e8bd052476c245460ab19d7de595de084dd968f2d75cd50c3e25/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031", size = 247234, upload-time = "2026-08-15T08:20:07.487Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/8a/3d130aeabcaf3d2466af76b7b141c08d9e89c9016ab4b7cdd0f7dc2d1c62/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072", size = 256917, upload-time = "2026-08-15T08:20:09.142Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/80/c2/a7379b840292d0c1ab9fbd17d1f3967aa81794dc95bc74be8999d7fedcf7/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d", size = 254846, upload-time = "2026-08-15T08:20:10.727Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/65/d43b714731bb2f40d4053dfa00ecfc1c5a301f8e3316c5db3a09af59fe94/charset_normalizer-3.5.1-cp37-abi3-win32.whl", hash = "sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc", size = 174216, upload-time = "2026-08-15T08:20:12.334Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/4f/b911ed898b26a09789eba9c9200c999aff6c61b4bafaf4838e56d1a1e1a3/charset_normalizer-3.5.1-cp37-abi3-win_amd64.whl", hash = "sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959", size = 199764, upload-time = "2026-08-15T08:20:13.908Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f0/a7/920baf467bfd9bf689f3b318340f37aee4572a71f162bd8db51da55ba4fa/charset_normalizer-3.5.1-cp37-abi3-win_arm64.whl", hash = "sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e", size = 287318, upload-time = "2026-08-15T08:20:15.551Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cc/61/d01fc49b8dea277640b55a9e15960dbca9fdc8c9fde18e572d39c59f4019/charset_normalizer-3.5.1-py3-none-any.whl", hash = "sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6", size = 68658, upload-time = "2026-08-15T08:20:43.306Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.4.2"
|
version = "8.4.2"
|
||||||
@@ -240,39 +302,39 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "49.0.0"
|
version = "50.0.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/de/41/6cbdcf9142d00fe82836fbb51e503e58088575cf7a0fe1dbff6695bf0840/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", size = 880201, upload-time = "2026-07-31T14:25:10.11Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" },
|
{ url = "https://files.pythonhosted.org/packages/c5/5c/59086b4aac5e879d38ddbcf74e4be7ade89cebc3eb199a55da998c3bb46a/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", size = 4001252, upload-time = "2026-07-31T14:23:33.331Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/ef/8f2df13c7216bcad3e1c74e07f6e193d93e998e114f524a53877c9af27ad/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645", size = 4719554, upload-time = "2026-07-31T14:23:35.611Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" },
|
{ url = "https://files.pythonhosted.org/packages/d9/41/029086c34d91052fc3b88bcc8056f709a7c915c7a23b235a54eb800b1c97/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", size = 4702130, upload-time = "2026-07-31T14:23:37.635Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" },
|
{ url = "https://files.pythonhosted.org/packages/7d/ff/b6ce0954962e7f7b969f850a883744197bb3910bdfd7b6da162eab7d9f68/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", size = 4725244, upload-time = "2026-07-31T14:23:39.471Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" },
|
{ url = "https://files.pythonhosted.org/packages/06/1e/63a1027cb7fec360a182208e1b7767d5aa1fe57be3d6aa856e69a321edc0/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", size = 5342265, upload-time = "2026-07-31T14:23:41.286Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" },
|
{ url = "https://files.pythonhosted.org/packages/6b/72/a1116d683a6d7ece94590013882515de087edf9ef0e6292aae615a44df73/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", size = 4734609, upload-time = "2026-07-31T14:23:43.139Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" },
|
{ url = "https://files.pythonhosted.org/packages/15/37/36a9c479bbe49acea2636c7fd3360d20f7b7e079c300352011c44850b181/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", size = 4356517, upload-time = "2026-07-31T14:23:44.939Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" },
|
{ url = "https://files.pythonhosted.org/packages/32/98/8a151d64367204cbc63ec65d37502f1d9c53cf4bfc6ec3c532614dbec60d/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", size = 4724529, upload-time = "2026-07-31T14:23:46.93Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" },
|
{ url = "https://files.pythonhosted.org/packages/22/f6/ec13b470172126464a86bf54d2294a46d29837fc51ba3e45d4047946fb5e/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", size = 5299852, upload-time = "2026-07-31T14:23:48.851Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" },
|
{ url = "https://files.pythonhosted.org/packages/da/3a/f05e32c99d440c9bb891ea0e36c9091891e36be5a9a87ab2ee6ea20729f6/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", size = 4734462, upload-time = "2026-07-31T14:23:50.861Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" },
|
{ url = "https://files.pythonhosted.org/packages/ca/dc/bd72b26be8953f80625f63151efd38eee71c76ca6cf591c08ff34615a79e/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", size = 4852708, upload-time = "2026-07-31T14:23:52.715Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" },
|
{ url = "https://files.pythonhosted.org/packages/27/20/c930314a2ab476d15dec966ec87e2e9637bb02b06106b12c0396c57bb603/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", size = 5004179, upload-time = "2026-07-31T14:23:54.887Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" },
|
{ url = "https://files.pythonhosted.org/packages/32/2e/c9db68a0c4bfa28e310707527c0ee3a2bd254104d2e02e68f368e197aa4c/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", size = 3840395, upload-time = "2026-07-31T14:23:56.677Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" },
|
{ url = "https://files.pythonhosted.org/packages/03/37/73d005be173aff344af30e9fd2a576575cb2391a7101d9cd3842e1fa8cce/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", size = 4036009, upload-time = "2026-07-31T14:24:24.122Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" },
|
{ url = "https://files.pythonhosted.org/packages/ff/c6/7a6202a534e32103a285b7834a120869557fe198d51d7cfe59754c8bda9c/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", size = 4745252, upload-time = "2026-07-31T14:24:26.118Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" },
|
{ url = "https://files.pythonhosted.org/packages/85/4f/0fa8c2f4428198f15d9ff8d63400e27afbf94ce833f6108da1eb3753f945/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", size = 4728939, upload-time = "2026-07-31T14:24:27.994Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/63/54dd723490ba2dc09b299682c10b38db38f159728bcaae8c591b8af2f22d/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", size = 4748483, upload-time = "2026-07-31T14:24:30.254Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" },
|
{ url = "https://files.pythonhosted.org/packages/1d/dd/7c77d26285cc7f6991efce64a0f5b4f9383bfa5dd8c5033003eaf7db4cdb/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", size = 5367599, upload-time = "2026-07-31T14:24:32.457Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" },
|
{ url = "https://files.pythonhosted.org/packages/46/c9/f60aed34c013f317f92817b6c171c2d22a78270fa41109bd4b08af26b194/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", size = 4762647, upload-time = "2026-07-31T14:24:34.599Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" },
|
{ url = "https://files.pythonhosted.org/packages/be/f3/f9a0173b139372c3a48ed98154b45cc6b9de17c789d5ab552e621c293609/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", size = 4385197, upload-time = "2026-07-31T14:24:36.647Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" },
|
{ url = "https://files.pythonhosted.org/packages/d8/36/83bb81f6e569bc38e1e4a7bc80f29b46bb9601920bc455fc8e888f5d5742/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", size = 4748095, upload-time = "2026-07-31T14:24:39.493Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" },
|
{ url = "https://files.pythonhosted.org/packages/6b/16/d3008eff98c764979865834c3d386d4fd041b5f52e7f34fc29ac1a5eb515/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", size = 5325948, upload-time = "2026-07-31T14:24:41.556Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" },
|
{ url = "https://files.pythonhosted.org/packages/9c/f8/d97f9603efda3888187bfdb893f26c41be4735c10631d05d284ee6b047c4/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", size = 4762400, upload-time = "2026-07-31T14:24:43.636Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" },
|
{ url = "https://files.pythonhosted.org/packages/64/a2/4615c8f7d81a00b1d6e6afe19f694e1543582349fb5f4076f6cb5dc36485/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", size = 4878208, upload-time = "2026-07-31T14:24:45.522Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" },
|
{ url = "https://files.pythonhosted.org/packages/d2/1a/efcfb02f91407149a0dacffffab791f7e19bf6385f63b3666dc8b5e5c9c8/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", size = 5037050, upload-time = "2026-07-31T14:24:47.697Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/30/4a22984d4f1bdfb8c054f07a92bc176b97a3134cc1d6c4b3bffb1f3688b4/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", size = 3874135, upload-time = "2026-07-31T14:24:50.085Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -469,6 +531,20 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/d1/53/70eb8c5c6037f27448f1e3c54ebede9545a801ae63f0a7254afca4fe8e45/lxml-6.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc", size = 3658490, upload-time = "2026-05-19T19:22:53.846Z" },
|
{ url = "https://files.pythonhosted.org/packages/d1/53/70eb8c5c6037f27448f1e3c54ebede9545a801ae63f0a7254afca4fe8e45/lxml-6.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc", size = 3658490, upload-time = "2026-05-19T19:22:53.846Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "msal"
|
||||||
|
version = "1.37.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
{ name = "pyjwt", extra = ["crypto"] },
|
||||||
|
{ name = "requests" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9a/99/d840198ecf6e8057bbc937f129ae940404485d736cda73253bbff9537f01/msal-1.37.0.tar.gz", hash = "sha256:1b1672a33ee467c1d70b341bb16cafd51bb3c817147a95b93263794b03971bec", size = 182444, upload-time = "2026-05-29T19:49:05.561Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/b0/d807279f4b55d16d1f120d5ac4344c6e39b56732e2a224d40bded7fd67ad/msal-1.37.0-py3-none-any.whl", hash = "sha256:dd17e95a7c71bce75e8108113438ba7c4a086b3bcad4f57a8c09b7af3d753c2d", size = 123725, upload-time = "2026-05-29T19:49:04.335Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "26.2"
|
version = "26.2"
|
||||||
@@ -595,6 +671,20 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyjwt"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
crypto = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "9.0.2"
|
version = "9.0.2"
|
||||||
@@ -686,6 +776,21 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" },
|
{ url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.34.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "certifi" },
|
||||||
|
{ name = "charset-normalizer" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.12.7"
|
version = "0.12.7"
|
||||||
@@ -774,6 +879,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/9e/a4/017a7a6cbe387d961a688ec31364ae60a5c4e22c96ae9921b79a947c855d/tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15", size = 18115, upload-time = "2026-06-29T08:03:38.666Z" },
|
{ url = "https://files.pythonhosted.org/packages/9e/a4/017a7a6cbe387d961a688ec31364ae60a5c4e22c96ae9921b79a947c855d/tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15", size = 18115, upload-time = "2026-06-29T08:03:38.666Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urllib3"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vacatureradar"
|
name = "vacatureradar"
|
||||||
version = "0.3.14"
|
version = "0.3.14"
|
||||||
@@ -790,6 +904,7 @@ dependencies = [
|
|||||||
{ name = "gunicorn" },
|
{ name = "gunicorn" },
|
||||||
{ name = "httpx" },
|
{ name = "httpx" },
|
||||||
{ name = "lxml" },
|
{ name = "lxml" },
|
||||||
|
{ name = "msal" },
|
||||||
{ name = "psycopg", extra = ["binary"] },
|
{ name = "psycopg", extra = ["binary"] },
|
||||||
{ name = "python-dateutil" },
|
{ name = "python-dateutil" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
@@ -821,13 +936,14 @@ requires-dist = [
|
|||||||
{ name = "bleach", specifier = "==6.4.0" },
|
{ name = "bleach", specifier = "==6.4.0" },
|
||||||
{ name = "celery", extras = ["redis"], specifier = "==5.6.3" },
|
{ name = "celery", extras = ["redis"], specifier = "==5.6.3" },
|
||||||
{ name = "certifi", specifier = "==2026.6.17" },
|
{ name = "certifi", specifier = "==2026.6.17" },
|
||||||
{ name = "cryptography", specifier = "==49.0.0" },
|
{ name = "cryptography", specifier = "==50.0.0" },
|
||||||
{ name = "defusedxml", specifier = "==0.7.1" },
|
{ name = "defusedxml", specifier = "==0.7.1" },
|
||||||
{ name = "django", specifier = "==5.2.16" },
|
{ name = "django", specifier = "==5.2.16" },
|
||||||
{ name = "feedparser", specifier = "==6.0.12" },
|
{ name = "feedparser", specifier = "==6.0.12" },
|
||||||
{ name = "gunicorn", specifier = "==26.0.0" },
|
{ name = "gunicorn", specifier = "==26.0.0" },
|
||||||
{ name = "httpx", specifier = "==0.28.1" },
|
{ name = "httpx", specifier = "==0.28.1" },
|
||||||
{ name = "lxml", specifier = "==6.1.1" },
|
{ name = "lxml", specifier = "==6.1.1" },
|
||||||
|
{ name = "msal", specifier = "==1.37.0" },
|
||||||
{ name = "playwright", marker = "extra == 'browser'", specifier = "==1.54.0" },
|
{ name = "playwright", marker = "extra == 'browser'", specifier = "==1.54.0" },
|
||||||
{ name = "psycopg", extras = ["binary"], specifier = "==3.3.4" },
|
{ name = "psycopg", extras = ["binary"], specifier = "==3.3.4" },
|
||||||
{ name = "pytest", marker = "extra == 'dev'", specifier = "==9.0.2" },
|
{ name = "pytest", marker = "extra == 'dev'", specifier = "==9.0.2" },
|
||||||
|
|||||||
Reference in New Issue
Block a user