chore: harden audit checks and issue taxonomy
Some checks failed
Dependency Audit / dependency-audit (push) Has been cancelled
Security Audit / security-audit (push) Has been cancelled

This commit is contained in:
2026-07-29 14:16:27 +02:00
parent 11d45bce25
commit a3beca6fc5
6 changed files with 107 additions and 20 deletions

View File

@@ -2,17 +2,24 @@
# Copy to a deployment-local .env or secret store. Do not commit populated secrets.
APP_ENV=production
# Live graph changes are useful in development. Production should apply saved
# module state through a coordinated restart of all API and worker processes.
GOVOPLAN_MODULE_LIVE_APPLY_ENABLED=
GOVOPLAN_INSTALL_PROFILE=self-hosted
MASTER_KEY_B64=<generate-with-govoplan-config-env-template-generate-secrets>
DATABASE_URL=postgresql+psycopg://govoplan:change-me@127.0.0.1:5432/govoplan
GOVOPLAN_DATABASE_URL_PGTOOLS=postgresql://govoplan:change-me@127.0.0.1:5432/govoplan
GOVOPLAN_DB_POOL_SIZE=5
GOVOPLAN_DB_MAX_OVERFLOW=10
GOVOPLAN_DB_POOL_TIMEOUT_SECONDS=30
GOVOPLAN_DB_POOL_RECYCLE_SECONDS=1800
ENABLED_MODULES=tenancy,organizations,identity,access,admin,dashboard,policy,audit,files,mail,campaigns,calendar,poll,scheduling,connectors,datasources,dataflow,workflow,views,notifications,docs,ops
ENABLED_MODULES=tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,files,mail,campaigns,calendar,poll,scheduling,connectors,datasources,dataflow,workflow,views,postbox,notifications,docs,ops
CELERY_ENABLED=true
REDIS_URL=redis://127.0.0.1:6379/0
CELERY_QUEUES=send_email,append_sent,notifications,calendar,default
CELERY_QUEUES=send_email,append_sent,notifications,calendar,dataflow,events,default
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90
GOVOPLAN_CONNECTOR_ALLOW_PRIVATE_NETWORKS=false
@@ -24,10 +31,14 @@ GOVOPLAN_HTTP_MAX_REQUEST_BODY_BYTES=536870912
GOVOPLAN_HTTP_HSTS_SECONDS=31536000
AUTH_LOGIN_THROTTLE_ENABLED=true
AUTH_ACTIVITY_TOUCH_INTERVAL_SECONDS=300
AUTH_LOGIN_THROTTLE_IDENTITY_LIMIT=10
AUTH_LOGIN_THROTTLE_CLIENT_LIMIT=100
AUTH_LOGIN_THROTTLE_WINDOW_SECONDS=900
AUTH_LOGIN_THROTTLE_REDIS_RETRY_SECONDS=30
# Production startup fails without Redis unless this explicit single-process
# risk acknowledgement is enabled.
GOVOPLAN_ALLOW_PROCESS_LOCAL_LOGIN_THROTTLE=false
CORS_ORIGINS=https://govoplan.example.org
GOVOPLAN_TRUSTED_HOSTS=govoplan.example.org

View File

@@ -149,6 +149,12 @@
"description": "GovOPlaN core runner, shared primitives, shell, or extension points.",
"exclusive": false
},
{
"name": "module/dashboard",
"color": "1d76db",
"description": "GovOPlaN Dashboard module behavior or integration.",
"exclusive": false
},
{
"name": "module/dataflow",
"color": "1d76db",
@@ -167,6 +173,12 @@
"description": "GovOPlaN Dms module behavior or integration.",
"exclusive": false
},
{
"name": "module/docs",
"color": "c5def5",
"description": "GovOPlaN Docs module behavior or integration.",
"exclusive": false
},
{
"name": "module/dist-lists",
"color": "0e8a16",

View File

@@ -24,6 +24,7 @@
-e ../govoplan-dataflow
-e ../govoplan-workflow
-e ../govoplan-views
-e ../govoplan-postbox
-e ../govoplan-poll
-e ../govoplan-scheduling
-e ../govoplan-notifications
@@ -37,6 +38,7 @@ idna>=3.15
jsonschema>=4,<5
pip>=26.1.2
pip-audit>=2.9,<3
pytest>=8,<9
pytest>=9.0.3,<10
pygments>=2.20,<3
python-multipart>=0.0.31
ruff>=0.14,<1

View File

@@ -1,4 +1,5 @@
# Test-harness dependencies used against immutable release source tags.
# Keep these separate from requirements-release.txt so they are not part of the
# deployable product dependency set.
pytest>=8,<9
pytest>=9.0.3,<10
pygments>=2.20,<3

View File

@@ -74,6 +74,8 @@ PY
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-dataflow/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-workflow/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-views/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-dashboard/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-postbox/tests
"$PYTHON" "$META_ROOT/tools/checks/check-datasource-composition.py"
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-mail/tests
"$PYTHON" -m unittest tests.test_api_smoke.ApiSmokeTests.test_mailbox_message_listing_reports_total_count
@@ -92,6 +94,12 @@ cd /mnt/DATA/git/govoplan-datasources/webui
cd /mnt/DATA/git/govoplan-workflow/webui
"$NPM" run typecheck
cd /mnt/DATA/git/govoplan-dashboard/webui
"$NPM" run test:dashboard-layout
cd /mnt/DATA/git/govoplan-postbox/webui
"$NPM" run test:ui-structure
cd /mnt/DATA/git/govoplan-mail/webui
"$NPM" run test:mail-ui

View File

@@ -496,7 +496,12 @@ run_bandit() {
fi
if [[ "${#PY_TEST_ROOTS[@]}" -gt 0 ]]; then
prepare_machine_report "$REPORTS_DIR/bandit-tests.json" || return 2
bandit -r "${PY_TEST_ROOTS[@]}" -f json -o "$REPORTS_DIR/bandit-tests.json"
# Tests intentionally use assertions and synthetic credentials. Keep the
# separate test scan useful by excluding only those test-specific signals.
bandit -r "${PY_TEST_ROOTS[@]}" \
--skip B101,B105,B106,B107 \
-f json \
-o "$REPORTS_DIR/bandit-tests.json"
local test_status=$?
[[ "$test_status" -le 1 ]] || status=2
fi
@@ -512,7 +517,11 @@ run_ruff_security() {
fi
if [[ "${#PY_TEST_ROOTS[@]}" -gt 0 ]]; then
prepare_machine_report "$REPORTS_DIR/ruff-security-tests.json" || return 2
ruff check --select S --output-format json "${PY_TEST_ROOTS[@]}" > "$REPORTS_DIR/ruff-security-tests.json"
ruff check \
--select S \
--ignore S101,S105,S106,S107 \
--output-format json \
"${PY_TEST_ROOTS[@]}" > "$REPORTS_DIR/ruff-security-tests.json"
local test_status=$?
[[ "$test_status" -le 1 ]] || status=2
fi
@@ -582,14 +591,32 @@ run_trivy() {
run_pip_audit_manifests() {
local status=0
for repo in "${REPOS[@]}"; do
[[ -f "$repo/requirements.txt" ]] || continue
local name
name="$(safe_name "$repo")"
prepare_machine_report "$REPORTS_DIR/pip-audit-$name.json" || return 2
# Requirements may contain project-relative entries such as `.[server]`.
# Resolve them from the owning repository instead of the meta-repository.
(cd "$repo" && pip-audit -r requirements.txt --progress-spinner off --format json --output "$REPORTS_DIR/pip-audit-$name.json")
accumulate_exit_status status "$?"
local repo_name
repo_name="$(safe_name "$repo")"
while IFS= read -r -d '' requirements_file; do
local manifest_name report_path
manifest_name="$(safe_name "$requirements_file")"
report_path="$REPORTS_DIR/pip-audit-$repo_name-$manifest_name.json"
prepare_machine_report "$report_path" || return 2
# Requirements may contain project-relative entries such as `.[server]`.
# Resolve them from the owning repository instead of the meta-repository.
(
cd "$repo" &&
pip-audit \
-r "$(basename "$requirements_file")" \
--progress-spinner off \
--format json \
--output "$report_path"
)
accumulate_exit_status status "$?"
done < <(
find "$repo" \
-maxdepth 1 \
-type f \
-name 'requirements*.txt' \
-print0 |
sort -z
)
done
return "$status"
}
@@ -597,12 +624,38 @@ run_pip_audit_manifests() {
run_npm_audit_manifests() {
local status=0
for repo in "${REPOS[@]}"; do
[[ -f "$repo/webui/package-lock.json" ]] || continue
local name
name="$(safe_name "$repo")"
prepare_machine_report "$REPORTS_DIR/npm-audit-$name.json" || return 2
(cd "$repo/webui" && npm audit --omit=dev --json > "$REPORTS_DIR/npm-audit-$name.json")
accumulate_exit_status status "$?"
local repo_name
repo_name="$(safe_name "$repo")"
while IFS= read -r -d '' lock_file; do
local lock_dir lock_name runtime_report all_report
lock_dir="$(dirname "$lock_file")"
lock_name="$(
printf '%s' "${lock_file#"$repo"/}" |
tr -c 'A-Za-z0-9_.-' '_'
)"
runtime_report="$REPORTS_DIR/npm-audit-runtime-$repo_name-$lock_name.json"
all_report="$REPORTS_DIR/npm-audit-all-$repo_name-$lock_name.json"
prepare_machine_report "$runtime_report" || return 2
(
cd "$lock_dir" &&
npm audit --omit=dev --json > "$runtime_report"
)
accumulate_exit_status status "$?"
prepare_machine_report "$all_report" || return 2
(
cd "$lock_dir" &&
npm audit --json > "$all_report"
)
accumulate_exit_status status "$?"
done < <(
find "$repo" \
-maxdepth 3 \
-type f \
-name package-lock.json \
-not -path '*/node_modules/*' \
-print0 |
sort -z
)
done
return "$status"
}