diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..1defedf
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,13 @@
+.git
+.github
+.mypy_cache
+.pytest_cache
+.ruff_cache
+.venv
+.workspace
+build
+dist
+docs
+tests
+**/__pycache__
+*.pyc
diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml
new file mode 100644
index 0000000..cc0c02c
--- /dev/null
+++ b/.github/actionlint.yaml
@@ -0,0 +1,3 @@
+self-hosted-runner:
+ labels:
+ - openrath-ga
diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index 5a8f154..9ceb51e 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -22,8 +22,8 @@ jobs:
name: Build Package
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: '3.12'
- run: uv build
diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml
index da47c98..1edeefe 100644
--- a/.github/workflows/ci-lint.yml
+++ b/.github/workflows/ci-lint.yml
@@ -30,8 +30,8 @@ jobs:
name: Ruff
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: '3.12'
- run: uv sync --dev --frozen
@@ -42,9 +42,9 @@ jobs:
name: MyPy
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: '3.12'
- - run: uv sync --dev --frozen
+ - run: uv sync --dev --extra postgres --extra redis --extra otel --frozen
- run: uv run mypy --no-incremental
diff --git a/.github/workflows/ci-live-provider.yml b/.github/workflows/ci-live-provider.yml
new file mode 100644
index 0000000..f8e9587
--- /dev/null
+++ b/.github/workflows/ci-live-provider.yml
@@ -0,0 +1,33 @@
+name: Test live provider release gate
+
+on:
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ live-provider:
+ name: pytest (live provider required)
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
+ with:
+ python-version: '3.12'
+ - name: Require approved provider credentials
+ env:
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ run: |
+ if [[ -z "${OPENAI_API_KEY}" && -z "${ANTHROPIC_API_KEY}" ]]; then
+ echo "An approved live provider credential is required." >&2
+ exit 1
+ fi
+ - name: Install live provider test dependencies
+ run: uv sync --dev --frozen
+ - name: Run live provider lifecycle tests
+ env:
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ run: uv run pytest -q -m live_llm
diff --git a/.github/workflows/ci-shellcheck.yml b/.github/workflows/ci-shellcheck.yml
index 155c69c..f2ac0d8 100644
--- a/.github/workflows/ci-shellcheck.yml
+++ b/.github/workflows/ci-shellcheck.yml
@@ -20,9 +20,9 @@ jobs:
name: ShellCheck
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Run ShellCheck
- uses: ludeeus/action-shellcheck@master
+ uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
with:
scandir: './scripts'
env:
diff --git a/.github/workflows/ci-test-fast.yml b/.github/workflows/ci-test-fast.yml
index e5000be..92ec698 100644
--- a/.github/workflows/ci-test-fast.yml
+++ b/.github/workflows/ci-test-fast.yml
@@ -38,8 +38,8 @@ jobs:
matrix:
python-version: ['3.10', '3.13']
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: ${{ matrix.python-version }}
- run: uv sync --dev --frozen
@@ -56,8 +56,8 @@ jobs:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: ${{ matrix.python-version }}
- run: uv sync --dev --frozen
diff --git a/.github/workflows/ci-test-opensandbox.yml b/.github/workflows/ci-test-opensandbox.yml
index 414c99a..76730a6 100644
--- a/.github/workflows/ci-test-opensandbox.yml
+++ b/.github/workflows/ci-test-opensandbox.yml
@@ -33,8 +33,8 @@ jobs:
name: pytest (opensandbox)
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: '3.12'
# setup-uv's post-job "Pruning cache" step has been hanging for
diff --git a/.github/workflows/ci-test-openviking.yml b/.github/workflows/ci-test-openviking.yml
index a26fd86..2f0b3fa 100644
--- a/.github/workflows/ci-test-openviking.yml
+++ b/.github/workflows/ci-test-openviking.yml
@@ -1,7 +1,13 @@
-name: Test OpenViking
+name: Test OpenViking contracts and live service
on:
workflow_dispatch:
+ inputs:
+ require_live:
+ description: Fail when live OpenViking credentials are unavailable
+ required: true
+ type: boolean
+ default: true
push:
branches: [main]
paths:
@@ -32,21 +38,18 @@ permissions:
jobs:
test-openviking:
- name: pytest (openviking)
+ name: pytest (openviking contracts)
runs-on: ubuntu-latest
- # OpenViking tests require a running server with reachable embedding +
- # VLM providers; allow failure in PRs until the CI environment is stable.
- continue-on-error: ${{ github.event_name == 'pull_request' }}
steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v5
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5
with:
python-version: '3.12'
# When repository secrets are absent we skip uv sync; without this
# the post-job cache prune fails because no cache dir was created.
prune-cache: false
- - name: Install dev dependencies
- run: uv sync --dev --frozen
+ - name: Install dev and OpenViking dependencies
+ run: uv sync --dev --extra openviking --frozen
- name: Check OpenViking credentials
id: creds
env:
@@ -60,9 +63,16 @@ jobs:
else
echo "available=false" >> "$GITHUB_OUTPUT"
fi
- - name: Install OpenViking SDK
- if: steps.creds.outputs.available == 'true'
- run: uv sync --dev --extra openviking --frozen
+ - name: Run OpenViking SDK and offline contracts
+ run: uv run pytest -q tests/memory/unit
+ - name: Require live credentials for release validation
+ if: >-
+ github.event_name == 'workflow_dispatch' &&
+ inputs.require_live &&
+ steps.creds.outputs.available != 'true'
+ run: |
+ echo "Live OpenViking credentials are required for release validation." >&2
+ exit 1
- name: Start OpenViking server
if: steps.creds.outputs.available == 'true'
env:
@@ -77,9 +87,11 @@ jobs:
echo "OPEN_VIKING_ROOT_API_KEY=${key}" >> "$GITHUB_ENV"
echo "OPEN_VIKING_URL=http://127.0.0.1:1933" >> "$GITHUB_ENV"
- name: Skip OpenViking (no repository secrets)
- if: steps.creds.outputs.available != 'true'
+ if: >-
+ steps.creds.outputs.available != 'true' &&
+ github.event_name != 'workflow_dispatch'
run: |
- echo "Skipping OpenViking integration tests."
+ echo "Only offline OpenViking contracts ran for this change."
echo "Configure repository secrets OPEN_VIKING_EMBEDDING_API_KEY + OPEN_VIKING_VLM_API_KEY,"
echo "or OPENAI_API_KEY, to run the live server job."
- name: Run OpenViking tests
diff --git a/.github/workflows/ci-v2-production.yml b/.github/workflows/ci-v2-production.yml
new file mode 100644
index 0000000..8c43e75
--- /dev/null
+++ b/.github/workflows/ci-v2-production.yml
@@ -0,0 +1,127 @@
+name: v2 production gates
+
+on:
+ pull_request:
+ push:
+ branches: [main]
+
+permissions:
+ contents: read
+
+jobs:
+ integration:
+ runs-on: ubuntu-latest
+ services:
+ postgres:
+ image: postgres:17-alpine@sha256:742f40ea20b9ff2ff31db5458d127452988a2164df9e17441e191f3b72252193
+ env:
+ POSTGRES_HOST_AUTH_METHOD: trust
+ ports:
+ - 55432:5432
+ options: >-
+ --health-cmd "pg_isready -U postgres"
+ --health-interval 5s
+ --health-timeout 3s
+ --health-retries 12
+ redis:
+ image: redis:8-alpine@sha256:8096655e437712b07503796fb64d81359256cfcff0ab29d95a7da72863786efb
+ ports:
+ - 56379:6379
+ env:
+ OPENRATH_TEST_POSTGRES_DSN: postgresql://postgres@127.0.0.1:55432/postgres
+ OPENRATH_TEST_REDIS_URL: redis://127.0.0.1:56379/0
+ OPENRATH_TEST_S3_ENDPOINT: http://127.0.0.1:59000
+ OPENRATH_TEST_S3_ACCESS_KEY: openrathtest
+ OPENRATH_TEST_S3_SECRET_KEY: openrath-test-secret
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ persist-credentials: false
+ - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
+ - name: Start S3-compatible object store
+ run: >-
+ docker run -d --name minio -p 59000:9000
+ -e MINIO_ROOT_USER=openrathtest
+ -e MINIO_ROOT_PASSWORD=openrath-test-secret
+ minio/minio:RELEASE.2025-09-07T16-13-09Z@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
+ server /data
+ - run: uv lock --check
+ - run: uv sync --frozen --extra postgres --extra server --extra s3 --extra redis --extra otel
+ - run: uv run ruff check src tests scripts examples
+ - run: uv run ruff format --check src tests example
+ - run: uv run mypy src/rath
+ - name: Audit exact production dependency set
+ run: |
+ uv export --frozen --no-dev --no-emit-project \
+ --extra server --extra postgres --extra s3 --extra redis --extra otel \
+ --output-file production-requirements.txt
+ uvx pip-audit --no-deps --disable-pip -r production-requirements.txt
+ - name: Audit every published extra and development group
+ run: |
+ uv export --frozen --all-extras --all-groups --no-emit-project \
+ --output-file all-requirements.txt
+ uvx pip-audit --no-deps --disable-pip -r all-requirements.txt
+ - run: uv run pytest -q -n auto -m "not live_llm and not opensandbox and not openviking"
+ - run: uv run python scripts/soak_v2.py --duration-seconds 10 --max-runs 500
+ - run: uv build
+ - name: Validate reference deployments
+ env:
+ POSTGRES_PASSWORD: review-only-password
+ OPENRATH_TOKEN: review-only-token
+ MINIO_ROOT_PASSWORD: review-only-minio-password
+ run: |
+ docker compose -f deploy/compose/compose.yaml config --quiet
+ docker run --rm \
+ -v "$PWD/deploy/kubernetes:/manifests:ro" \
+ ghcr.io/yannh/kubeconform:v0.7.0@sha256:85dbef6b4b312b99133decc9c6fc9495e9fc5f92293d4ff3b7e1b30f5611823c \
+ -strict -summary /manifests
+
+ container:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ persist-credentials: false
+ - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
+ - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
+ with:
+ context: .
+ file: docker/Dockerfile
+ push: false
+ load: true
+ tags: openrath:review
+ - name: Scan image, generate SBOM, and scan repository secrets
+ env:
+ TRIVY_IMAGE: aquasec/trivy@sha256:e2b22eac59c02003d8749f5b8d9bd073b62e30fefaef5b7c8371204e0a4b0c08 # v0.67.2
+ run: |
+ mkdir -p "$RUNNER_TEMP/trivy-cache"
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ "$TRIVY_IMAGE" image \
+ --severity CRITICAL,HIGH \
+ --exit-code 1 \
+ --ignore-unfixed \
+ openrath:review
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ -v "$PWD:/workspace" \
+ "$TRIVY_IMAGE" image \
+ --format cyclonedx \
+ --output /workspace/openrath-v2-sbom.cdx.json \
+ openrath:review
+ docker run --rm \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ -v "$PWD:/workspace:ro" \
+ "$TRIVY_IMAGE" fs \
+ --scanners secret \
+ --exit-code 1 \
+ --skip-dirs /workspace/.git \
+ --skip-dirs /workspace/.venv \
+ --skip-dirs /workspace/.mypy_cache \
+ --skip-dirs /workspace/.pytest_cache \
+ --skip-dirs /workspace/.ruff_cache \
+ --skip-dirs /workspace/build \
+ --skip-dirs /workspace/dist \
+ /workspace
diff --git a/.github/workflows/collect-v2-ga-evidence.yml b/.github/workflows/collect-v2-ga-evidence.yml
new file mode 100644
index 0000000..f1fc5e3
--- /dev/null
+++ b/.github/workflows/collect-v2-ga-evidence.yml
@@ -0,0 +1,95 @@
+name: Collect v2.0.0 Gate C evidence
+
+on:
+ workflow_dispatch:
+ inputs:
+ bundle_id:
+ description: Runner-local bundle directory name below the configured evidence root
+ required: true
+ type: string
+ confirmation:
+ description: Type "collect v2.0.0 gate c"
+ required: true
+ type: string
+
+concurrency:
+ group: collect-openrath-v2.0.0-${{ github.sha }}
+ cancel-in-progress: false
+
+permissions: {}
+
+jobs:
+ collect:
+ name: Validate and collect target evidence
+ runs-on: [self-hosted, linux, openrath-ga]
+ timeout-minutes: 15
+ environment:
+ name: ga-evidence
+ url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ permissions:
+ contents: read # Check out the exact candidate source for its verifier.
+ env:
+ BUNDLE_ID: ${{ inputs.bundle_id }}
+ EVIDENCE_ROOT: ${{ vars.OPENRATH_GA_EVIDENCE_ROOT }}
+ RELEASE_CONFIRMATION: ${{ inputs.confirmation }}
+ VERSION: 2.0.0
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ ref: ${{ github.sha }}
+ fetch-depth: 0
+ persist-credentials: false
+ - name: Validate candidate and protected target bundle
+ shell: bash
+ run: |
+ set -euo pipefail
+ test "$GITHUB_REF" = "refs/heads/main"
+ test "$RELEASE_CONFIRMATION" = "collect v2.0.0 gate c"
+ test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
+ git fetch origin main
+ test "$(git rev-parse origin/main)" = "$GITHUB_SHA"
+ project_version="$(python3 - <<'PY'
+ import re
+ from pathlib import Path
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ print(re.search(r'^version = "([^"]+)"$', text, re.MULTILINE).group(1))
+ PY
+ )"
+ test "$project_version" = "$VERSION"
+ [[ "$BUNDLE_ID" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ]]
+ test -n "$EVIDENCE_ROOT"
+ [[ "$EVIDENCE_ROOT" = /* ]]
+
+ root_real="$(realpath "$EVIDENCE_ROOT")"
+ source_real="$(realpath "$root_real/$BUNDLE_ID")"
+ case "$source_real" in
+ "$root_real"/*) ;;
+ *)
+ echo "Evidence bundle escapes the configured root." >&2
+ exit 1
+ ;;
+ esac
+ test -d "$source_real"
+ if find "$source_real" -type l -print -quit | grep -q .; then
+ echo "Evidence bundles must not contain symbolic links." >&2
+ exit 1
+ fi
+ bundle_kib="$(du -sk "$source_real" | awk '{print $1}')"
+ test "$bundle_kib" -le 2097152
+
+ destination="$RUNNER_TEMP/gates"
+ mkdir "$destination"
+ cp -a --no-preserve=ownership "$source_real/." "$destination/"
+ python3 scripts/release/verify_gate_bundle.py "$destination"
+ python3 scripts/release/verify_gate_reports.py \
+ "$destination" \
+ --source-commit "$GITHUB_SHA" \
+ --artifact-root "$destination"
+ - name: Upload immutable Gate C input
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: openrath-v2.0.0-ga-input
+ path: ${{ runner.temp }}/gates
+ retention-days: 90
+ if-no-files-found: error
+ compression-level: 6
diff --git a/.github/workflows/release-v2-ga-finalize.yml b/.github/workflows/release-v2-ga-finalize.yml
new file mode 100644
index 0000000..85cbc97
--- /dev/null
+++ b/.github/workflows/release-v2-ga-finalize.yml
@@ -0,0 +1,203 @@
+name: Finalize v2.0.0 GA
+
+on:
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: Existing annotated GA tag
+ required: true
+ type: string
+ preparation_run_id:
+ description: Successful Prepare v2.0.0 GA bundle run
+ required: true
+ type: string
+ confirmation:
+ description: Type "finalize v2.0.0" after the manual PyPI upload
+ required: true
+ type: string
+
+concurrency:
+ group: finalize-openrath-v2.0.0
+ cancel-in-progress: false
+
+permissions: {}
+
+jobs:
+ finalize-ga:
+ name: Verify PyPI and publish final GA surfaces
+ runs-on: ubuntu-latest
+ environment:
+ name: ga-release
+ url: https://github.com/${{ github.repository }}/releases/tag/v2.0.0
+ permissions:
+ actions: read # Read and download the protected preparation artifact.
+ attestations: read # Verify the source-SHA OCI image attestation.
+ contents: write # Create or verify the immutable GitHub Release.
+ packages: write # Promote the verified image digest to the 2.0.0 tag.
+ env:
+ IMAGE: ghcr.io/rath-team/openrath
+ PREPARATION_RUN_ID: ${{ inputs.preparation_run_id }}
+ RELEASE_TAG: ${{ inputs.tag }}
+ VERSION: 2.0.0
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ ref: ${{ env.RELEASE_TAG }}
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
+ with:
+ python-version: '3.12'
+ enable-cache: false
+ - name: Validate dispatch, tag, version, and main ancestry
+ env:
+ RELEASE_CONFIRMATION: ${{ inputs.confirmation }}
+ run: |
+ test "$GITHUB_REF" = "refs/heads/main"
+ test "$RELEASE_CONFIRMATION" = "finalize v2.0.0"
+ test "$RELEASE_TAG" = "v2.0.0"
+ test "$(git cat-file -t "$RELEASE_TAG")" = "tag"
+ test "$(git rev-parse "$RELEASE_TAG^{}")" = "$(git rev-parse HEAD)"
+ git fetch origin main
+ git merge-base --is-ancestor HEAD origin/main
+ project_version="$(python - <<'PY'
+ import re
+ from pathlib import Path
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ print(re.search(r'^version = "([^"]+)"$', text, re.MULTILINE).group(1))
+ PY
+ )"
+ test "$project_version" = "$VERSION"
+ test -f "release/notes/v${VERSION}.md"
+ ! grep -Eq 'TODO|HOLD|DRAFT' "release/notes/v${VERSION}.md"
+ test -z "$(git status --porcelain --untracked-files=no)"
+ echo "SOURCE_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
+ - name: Download and verify the protected candidate bundle
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ [[ "$PREPARATION_RUN_ID" =~ ^[1-9][0-9]*$ ]]
+ run_json="$(gh run view "$PREPARATION_RUN_ID" \
+ --repo "$GITHUB_REPOSITORY" \
+ --json headSha,conclusion,event,workflowName)"
+ test "$(jq -r .conclusion <<<"$run_json")" = "success"
+ test "$(jq -r .event <<<"$run_json")" = "workflow_dispatch"
+ test "$(jq -r .headSha <<<"$run_json")" = "$SOURCE_SHA"
+ test "$(jq -r .workflowName <<<"$run_json")" = \
+ "Prepare v2.0.0 GA bundle"
+ gh run download "$PREPARATION_RUN_ID" \
+ --repo "$GITHUB_REPOSITORY" \
+ --name openrath-2.0.0-ga-candidate \
+ --dir release-bundle
+ python scripts/release/verify_evidence.py \
+ release-bundle/release/evidence/"$VERSION"/manifest.json \
+ --artifact-root release-bundle
+ python scripts/release/verify_pypi_files.py \
+ --packages-dir release-bundle/dist \
+ --version "$VERSION" \
+ --require-complete \
+ --attempts 12 \
+ --delay-seconds 10
+ image_digest="$(jq -r '.artifacts.image.digest' \
+ release-bundle/release/evidence/"$VERSION"/manifest.json)"
+ [[ "$image_digest" =~ ^sha256:[0-9a-f]{64}$ ]]
+ echo "IMAGE_DIGEST=$image_digest" >> "$GITHUB_ENV"
+ - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
+ - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+ - name: Promote the attested candidate digest
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ candidate_digest="$(docker buildx imagetools inspect \
+ "$IMAGE:$SOURCE_SHA" |
+ sed -n 's/^Digest:[[:space:]]*//p' | head -1)"
+ test "$candidate_digest" = "$IMAGE_DIGEST"
+ gh attestation verify \
+ "oci://$IMAGE@$IMAGE_DIGEST" \
+ --repo "$GITHUB_REPOSITORY"
+
+ if docker buildx imagetools inspect "$IMAGE:$VERSION" \
+ >"$RUNNER_TEMP/existing-image.txt" 2>/dev/null; then
+ existing_digest="$(sed -n \
+ 's/^Digest:[[:space:]]*//p' \
+ "$RUNNER_TEMP/existing-image.txt" | head -1)"
+ test "$existing_digest" = "$IMAGE_DIGEST"
+ else
+ docker buildx imagetools create \
+ --prefer-index=false \
+ --tag "$IMAGE:$VERSION" \
+ "$IMAGE@$IMAGE_DIGEST"
+ fi
+
+ promoted_digest="$(docker buildx imagetools inspect \
+ "$IMAGE:$VERSION" |
+ sed -n 's/^Digest:[[:space:]]*//p' | head -1)"
+ test "$promoted_digest" = "$IMAGE_DIGEST"
+ - name: Create or verify the immutable GitHub Release
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ shopt -s nullglob
+ assets=(
+ release-bundle/dist/*
+ release-bundle/release/evidence/"$VERSION"/*.json
+ release-bundle/release/evidence/"$VERSION"/*.yaml
+ release-bundle/release/evidence/"$VERSION"/gates/*.json
+ )
+ test "${#assets[@]}" -gt 2
+ if gh release view "$RELEASE_TAG" \
+ --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
+ release_json="$(gh release view "$RELEASE_TAG" \
+ --repo "$GITHUB_REPOSITORY" \
+ --json isDraft,isPrerelease,tagName)"
+ test "$(jq -r .isDraft <<<"$release_json")" = "false"
+ test "$(jq -r .isPrerelease <<<"$release_json")" = "false"
+ test "$(jq -r .tagName <<<"$release_json")" = "$RELEASE_TAG"
+ mkdir "$RUNNER_TEMP/existing-release"
+ gh release download "$RELEASE_TAG" \
+ --repo "$GITHUB_REPOSITORY" \
+ --dir "$RUNNER_TEMP/existing-release"
+ python scripts/release/verify_release_assets.py \
+ "$RUNNER_TEMP/existing-release" \
+ "${assets[@]}"
+ else
+ gh release create "$RELEASE_TAG" \
+ "${assets[@]}" \
+ --repo "$GITHUB_REPOSITORY" \
+ --verify-tag \
+ --title "OpenRath $VERSION" \
+ --notes-file "release/notes/v${VERSION}.md"
+ fi
+ - name: Verify public GA artifacts
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ python scripts/release/verify_pypi_files.py \
+ --packages-dir release-bundle/dist \
+ --version "$VERSION" \
+ --require-complete
+ uv venv "$RUNNER_TEMP/verify"
+ uv pip install \
+ --python "$RUNNER_TEMP/verify/bin/python" \
+ --no-cache \
+ "openrath==$VERSION"
+ "$RUNNER_TEMP/verify/bin/python" -c \
+ "import importlib.metadata; assert importlib.metadata.version('openrath') == '$VERSION'"
+
+ docker logout ghcr.io
+ mkdir "$RUNNER_TEMP/docker-anonymous"
+ DOCKER_CONFIG="$RUNNER_TEMP/docker-anonymous" \
+ docker manifest inspect "$IMAGE@$IMAGE_DIGEST" >/dev/null
+ public_digest="$(DOCKER_CONFIG="$RUNNER_TEMP/docker-anonymous" \
+ docker buildx imagetools inspect "$IMAGE:$VERSION" |
+ sed -n 's/^Digest:[[:space:]]*//p' | head -1)"
+ test "$public_digest" = "$IMAGE_DIGEST"
+ gh attestation verify \
+ "oci://$IMAGE@$IMAGE_DIGEST" \
+ --repo "$GITHUB_REPOSITORY"
+ gh release view "$RELEASE_TAG" \
+ --repo "$GITHUB_REPOSITORY" >/dev/null
diff --git a/.github/workflows/release-v2-ga.yml b/.github/workflows/release-v2-ga.yml
new file mode 100644
index 0000000..3decda9
--- /dev/null
+++ b/.github/workflows/release-v2-ga.yml
@@ -0,0 +1,257 @@
+name: Prepare v2.0.0 GA bundle
+
+on:
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: Existing annotated GA tag
+ required: true
+ type: string
+ evidence_run_id:
+ description: Successful run containing openrath-v2.0.0-ga-input
+ required: true
+ type: string
+ confirmation:
+ description: Type "prepare v2.0.0" to authorize this run
+ required: true
+ type: string
+
+concurrency:
+ group: prepare-openrath-v2.0.0
+ cancel-in-progress: false
+
+permissions: {}
+
+jobs:
+ prepare-ga:
+ name: Verify evidence and prepare immutable artifacts
+ runs-on: ubuntu-latest
+ environment:
+ name: ga-release
+ url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ permissions:
+ actions: read # Read the Gate C result and download its evidence artifact.
+ attestations: write # Sign the immutable source-SHA OCI image.
+ contents: read
+ id-token: write # Request GitHub's OIDC identity for keyless attestation.
+ packages: write # Push only the source-SHA image candidate to GHCR.
+ env:
+ RELEASE_TAG: ${{ inputs.tag }}
+ EVIDENCE_RUN_ID: ${{ inputs.evidence_run_id }}
+ IMAGE: ghcr.io/rath-team/openrath
+ TRIVY_IMAGE: aquasec/trivy@sha256:e2b22eac59c02003d8749f5b8d9bd073b62e30fefaef5b7c8371204e0a4b0c08
+ VERSION: 2.0.0
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ ref: ${{ env.RELEASE_TAG }}
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
+ with:
+ python-version: '3.12'
+ enable-cache: false
+ - name: Validate dispatch, tag, version, and main ancestry
+ env:
+ RELEASE_CONFIRMATION: ${{ inputs.confirmation }}
+ run: |
+ test "$GITHUB_REF" = "refs/heads/main"
+ test "$RELEASE_CONFIRMATION" = "prepare v2.0.0"
+ test "$RELEASE_TAG" = "v2.0.0"
+ test "$(git cat-file -t "$RELEASE_TAG")" = "tag"
+ test "$(git rev-parse "$RELEASE_TAG^{}")" = "$(git rev-parse HEAD)"
+ git fetch origin main
+ git merge-base --is-ancestor HEAD origin/main
+ project_version="$(python - <<'PY'
+ import re
+ from pathlib import Path
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ print(re.search(r'^version = "([^"]+)"$', text, re.MULTILINE).group(1))
+ PY
+ )"
+ test "$project_version" = "$VERSION"
+ test -f "release/notes/v${VERSION}.md"
+ ! grep -Eq 'TODO|HOLD|DRAFT' "release/notes/v${VERSION}.md"
+ test -z "$(git status --porcelain --untracked-files=no)"
+ echo "SOURCE_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
+ - name: Download and verify same-SHA Gate C evidence
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ [[ "$EVIDENCE_RUN_ID" =~ ^[1-9][0-9]*$ ]]
+ run_json="$(gh api \
+ "repos/$GITHUB_REPOSITORY/actions/runs/$EVIDENCE_RUN_ID")"
+ test "$(jq -r .conclusion <<<"$run_json")" = "success"
+ test "$(jq -r .event <<<"$run_json")" = "workflow_dispatch"
+ test "$(jq -r .head_branch <<<"$run_json")" = "main"
+ test "$(jq -r .head_sha <<<"$run_json")" = "$SOURCE_SHA"
+ test "$(jq -r .name <<<"$run_json")" = \
+ "Collect v2.0.0 Gate C evidence"
+ test "$(jq -r .path <<<"$run_json")" = \
+ ".github/workflows/collect-v2-ga-evidence.yml"
+ gate_dir="release/evidence/$VERSION/gates"
+ mkdir -p "$gate_dir"
+ gh run download "$EVIDENCE_RUN_ID" \
+ --repo "$GITHUB_REPOSITORY" \
+ --name openrath-v2.0.0-ga-input \
+ --dir "$gate_dir"
+ uv run python scripts/release/verify_gate_reports.py \
+ "$gate_dir" \
+ --source-commit "$SOURCE_SHA" \
+ --artifact-root "$gate_dir"
+ - name: Record protected-environment approval
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ review_history="$RUNNER_TEMP/environment-approvals.json"
+ gh api \
+ "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/approvals" \
+ > "$review_history"
+ uv run python scripts/release/create_ga_approval.py \
+ --version "$VERSION" \
+ --source-commit "$SOURCE_SHA" \
+ --requested-by "$GITHUB_ACTOR" \
+ --repository "$GITHUB_REPOSITORY" \
+ --workflow-run-id "$GITHUB_RUN_ID" \
+ --review-history "$review_history" \
+ --output release/evidence/"$VERSION"/ga-approval.json
+ - name: Verify source and package gates
+ run: |
+ uv lock --check
+ uv sync --frozen --all-extras --all-groups
+ uv run ruff format --check src tests example
+ uv run ruff check src tests scripts examples
+ uv run mypy --no-incremental src/rath
+ uv run pytest -q -n auto \
+ -m "not live_llm and not opensandbox and not openviking"
+ uv run python scripts/export_openapi_v2.py \
+ --output "$RUNNER_TEMP/openapi-v2.json"
+ diff -u deploy/docs/openapi-v2.json "$RUNNER_TEMP/openapi-v2.json"
+ uv build
+ uvx twine check dist/*
+ - name: Audit exact dependency sets
+ run: |
+ uv export --frozen --no-dev --no-emit-project \
+ --extra server --extra postgres --extra s3 --extra redis --extra otel \
+ --output-file production-requirements.txt
+ uvx pip-audit --no-deps --disable-pip \
+ --format json \
+ --output release/evidence/"$VERSION"/dependency-audit-production.json \
+ -r production-requirements.txt
+ uv export --frozen --all-extras --all-groups --no-emit-project \
+ --output-file all-requirements.txt
+ uvx pip-audit --no-deps --disable-pip \
+ --format json \
+ --output release/evidence/"$VERSION"/dependency-audit-all.json \
+ -r all-requirements.txt
+ - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
+ - name: Build the final image once
+ uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
+ with:
+ context: .
+ file: docker/Dockerfile
+ load: true
+ push: false
+ tags: ${{ env.IMAGE }}:${{ env.SOURCE_SHA }}
+ build-args: |
+ OPENRATH_VERSION=${{ env.VERSION }}
+ OPENRATH_REVISION=${{ env.SOURCE_SHA }}
+ - name: Scan the final image and source
+ run: |
+ evidence_dir="release/evidence/$VERSION"
+ mkdir -p "$RUNNER_TEMP/trivy-cache"
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ -v "$PWD:/workspace" \
+ "$TRIVY_IMAGE" image \
+ --severity CRITICAL,HIGH \
+ --exit-code 1 \
+ --ignore-unfixed \
+ --format json \
+ --output "/workspace/$evidence_dir/image-scan.json" \
+ "$IMAGE:$SOURCE_SHA"
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ -v "$PWD:/workspace" \
+ "$TRIVY_IMAGE" image \
+ --format cyclonedx \
+ --output "/workspace/$evidence_dir/sbom.cdx.json" \
+ "$IMAGE:$SOURCE_SHA"
+ docker run --rm \
+ -v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
+ -v "$PWD:/workspace:ro" \
+ -v "$PWD/$evidence_dir:/evidence" \
+ "$TRIVY_IMAGE" fs \
+ --scanners secret \
+ --exit-code 1 \
+ --format json \
+ --output /evidence/secret-scan.json \
+ --skip-dirs /workspace/.git \
+ --skip-dirs /workspace/.venv \
+ --skip-dirs /workspace/.mypy_cache \
+ --skip-dirs /workspace/.pytest_cache \
+ --skip-dirs /workspace/.ruff_cache \
+ --skip-dirs /workspace/build \
+ --skip-dirs /workspace/dist \
+ /workspace
+ - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ github.token }}
+ - name: Push the immutable candidate image
+ id: push_image
+ run: |
+ push_output="$(docker push "$IMAGE:$SOURCE_SHA")"
+ printf '%s\n' "$push_output"
+ digest="$(sed -n \
+ 's/^.*digest: \(sha256:[0-9a-f]\{64\}\).*$/\1/p' \
+ <<<"$push_output" | tail -1)"
+ [[ "$digest" =~ ^sha256:[0-9a-f]{64}$ ]]
+ echo "digest=$digest" >> "$GITHUB_OUTPUT"
+ - name: Build and verify final SHA-bound evidence
+ env:
+ IMAGE_DIGEST: ${{ steps.push_image.outputs.digest }}
+ run: |
+ evidence_dir="release/evidence/$VERSION"
+ sed "s#${IMAGE}:${VERSION}#${IMAGE}@${IMAGE_DIGEST}#g" \
+ deploy/kubernetes/openrath.yaml \
+ > "$evidence_dir/openrath-kubernetes.yaml"
+ uv run python scripts/release/build_evidence.py \
+ --stage ga \
+ --tag "$RELEASE_TAG" \
+ --approval "$evidence_dir/ga-approval.json" \
+ --image-ref "$IMAGE" \
+ --image-digest "$IMAGE_DIGEST" \
+ --output "$evidence_dir/manifest.json" \
+ --artifact sbom="$evidence_dir/sbom.cdx.json" \
+ --artifact image_scan="$evidence_dir/image-scan.json" \
+ --artifact secret_scan="$evidence_dir/secret-scan.json" \
+ --artifact dependency_audit_production="$evidence_dir/dependency-audit-production.json" \
+ --artifact dependency_audit_all="$evidence_dir/dependency-audit-all.json" \
+ --artifact kubernetes="$evidence_dir/openrath-kubernetes.yaml" \
+ --artifact tests="$evidence_dir/gates/tests.json" \
+ --artifact live_adapters="$evidence_dir/gates/live-adapters.json" \
+ --artifact performance="$evidence_dir/gates/performance.json" \
+ --artifact soak="$evidence_dir/gates/soak.json" \
+ --artifact drills="$evidence_dir/gates/drills.json" \
+ --artifact compatibility="$evidence_dir/gates/compatibility.json"
+ uv run python scripts/release/verify_evidence.py \
+ "$evidence_dir/manifest.json"
+ - name: Attest the final OCI digest
+ uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
+ with:
+ subject-name: ${{ env.IMAGE }}
+ subject-digest: ${{ steps.push_image.outputs.digest }}
+ push-to-registry: true
+ - name: Upload the final release bundle
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: openrath-2.0.0-ga-candidate
+ retention-days: 90
+ if-no-files-found: error
+ path: |
+ dist/*
+ release/evidence/2.0.0/*
diff --git a/.github/workflows/release-v2-rc.yml b/.github/workflows/release-v2-rc.yml
new file mode 100644
index 0000000..c3509e7
--- /dev/null
+++ b/.github/workflows/release-v2-rc.yml
@@ -0,0 +1,191 @@
+name: Publish v2 release candidate
+
+on:
+ push:
+ tags:
+ - 'v2.0.0rc*'
+ workflow_dispatch:
+ inputs:
+ tag:
+ description: Existing v2.0.0rcN tag to publish
+ required: true
+ type: string
+
+permissions:
+ contents: write
+ packages: write
+ id-token: write
+ attestations: write
+
+jobs:
+ publish-rc:
+ name: Build, attest, and publish RC
+ runs-on: ubuntu-latest
+ environment: rc-release
+ env:
+ RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
+ IMAGE: ghcr.io/rath-team/openrath
+ TRIVY_IMAGE: aquasec/trivy@sha256:e2b22eac59c02003d8749f5b8d9bd073b62e30fefaef5b7c8371204e0a4b0c08
+ steps:
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
+ with:
+ ref: ${{ env.RELEASE_TAG }}
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
+ with:
+ python-version: '3.12'
+ enable-cache: false
+ - name: Validate tag and project version
+ run: |
+ version="${RELEASE_TAG#v}"
+ project_version="$(python - <<'PY'
+ import re
+ from pathlib import Path
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ print(re.search(r'^version = "([^"]+)"$', text, re.MULTILINE).group(1))
+ PY
+ )"
+ test "$version" = "$project_version"
+ test -f "release/notes/v${version}.md"
+ echo "VERSION=$version" >> "$GITHUB_ENV"
+ echo "SOURCE_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
+ - name: Verify source and package gates
+ run: |
+ uv lock --check
+ uv sync --frozen --all-extras --all-groups
+ uv run ruff format --check src tests example
+ uv run ruff check src tests scripts examples
+ uv run mypy --no-incremental src/rath
+ uv run pytest -q -n auto -m "not live_llm and not opensandbox and not openviking"
+ uv run python scripts/export_openapi_v2.py --output "$RUNNER_TEMP/openapi-v2.json"
+ diff -u deploy/docs/openapi-v2.json "$RUNNER_TEMP/openapi-v2.json"
+ uv build
+ uvx twine check dist/*
+ - name: Audit exact production dependencies
+ run: |
+ uv export --frozen --no-dev --no-emit-project \
+ --extra server --extra postgres --extra s3 --extra redis --extra otel \
+ --output-file production-requirements.txt
+ uvx pip-audit --no-deps --disable-pip \
+ --format json --output dependency-audit-production.json \
+ -r production-requirements.txt
+ uv export --frozen --all-extras --all-groups --no-emit-project \
+ --output-file all-requirements.txt
+ uvx pip-audit --no-deps --disable-pip \
+ --format json --output dependency-audit-all.json \
+ -r all-requirements.txt
+ - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
+ - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Build and push immutable RC image
+ id: image
+ uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
+ with:
+ context: .
+ file: docker/Dockerfile
+ push: true
+ tags: |
+ ${{ env.IMAGE }}:${{ env.VERSION }}
+ ${{ env.IMAGE }}:${{ env.SOURCE_SHA }}
+ build-args: |
+ OPENRATH_VERSION=${{ env.VERSION }}
+ OPENRATH_REVISION=${{ env.SOURCE_SHA }}
+ - name: Pull, scan, and describe published image
+ env:
+ IMAGE_DIGEST: ${{ steps.image.outputs.digest }}
+ run: |
+ mkdir -p release/evidence/"$VERSION"
+ docker pull "$IMAGE@$IMAGE_DIGEST"
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$PWD:/workspace" \
+ "$TRIVY_IMAGE" image \
+ --severity CRITICAL,HIGH \
+ --exit-code 1 \
+ --ignore-unfixed \
+ --format json \
+ --output /workspace/release/evidence/"$VERSION"/image-scan.json \
+ "$IMAGE@$IMAGE_DIGEST"
+ docker run --rm \
+ -v /var/run/docker.sock:/var/run/docker.sock \
+ -v "$PWD:/workspace" \
+ "$TRIVY_IMAGE" image \
+ --format cyclonedx \
+ --output /workspace/release/evidence/"$VERSION"/sbom.cdx.json \
+ "$IMAGE@$IMAGE_DIGEST"
+ docker run --rm \
+ -v "$PWD:/workspace:ro" \
+ -v "$PWD/release/evidence/$VERSION:/evidence" \
+ "$TRIVY_IMAGE" fs \
+ --scanners secret \
+ --exit-code 1 \
+ --format json \
+ --output /evidence/secret-scan.json \
+ --skip-dirs /workspace/.git \
+ --skip-dirs /workspace/.venv \
+ --skip-dirs /workspace/.mypy_cache \
+ --skip-dirs /workspace/.pytest_cache \
+ --skip-dirs /workspace/.ruff_cache \
+ --skip-dirs /workspace/build \
+ --skip-dirs /workspace/dist \
+ /workspace
+ cp dependency-audit-production.json release/evidence/"$VERSION"/
+ cp dependency-audit-all.json release/evidence/"$VERSION"/
+ sed "s#${IMAGE}:${VERSION}#${IMAGE}@${IMAGE_DIGEST}#g" \
+ deploy/kubernetes/openrath.yaml \
+ > release/evidence/"$VERSION"/openrath-kubernetes.yaml
+ - name: Build and verify SHA-bound evidence
+ env:
+ IMAGE_DIGEST: ${{ steps.image.outputs.digest }}
+ run: |
+ uv run python scripts/release/build_evidence.py \
+ --tag "$RELEASE_TAG" \
+ --image-ref "$IMAGE" \
+ --image-digest "$IMAGE_DIGEST" \
+ --output release/evidence/"$VERSION"/manifest.json \
+ --artifact sbom=release/evidence/"$VERSION"/sbom.cdx.json \
+ --artifact image_scan=release/evidence/"$VERSION"/image-scan.json \
+ --artifact secret_scan=release/evidence/"$VERSION"/secret-scan.json \
+ --artifact dependency_audit_production=release/evidence/"$VERSION"/dependency-audit-production.json \
+ --artifact dependency_audit_all=release/evidence/"$VERSION"/dependency-audit-all.json \
+ --artifact kubernetes=release/evidence/"$VERSION"/openrath-kubernetes.yaml
+ uv run python scripts/release/verify_evidence.py \
+ release/evidence/"$VERSION"/manifest.json
+ - name: Attest published image
+ uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
+ with:
+ subject-name: ${{ env.IMAGE }}
+ subject-digest: ${{ steps.image.outputs.digest }}
+ push-to-registry: true
+ - name: Upload release evidence
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: openrath-${{ env.VERSION }}-release
+ retention-days: 90
+ if-no-files-found: error
+ path: |
+ dist/*
+ release/evidence/${{ env.VERSION }}/*
+ - name: Create or update GitHub prerelease
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
+ gh release upload "$RELEASE_TAG" --clobber \
+ dist/* release/evidence/"$VERSION"/*
+ gh release edit "$RELEASE_TAG" \
+ --prerelease \
+ --title "OpenRath $VERSION" \
+ --notes-file "release/notes/v${VERSION}.md"
+ else
+ gh release create "$RELEASE_TAG" \
+ dist/* release/evidence/"$VERSION"/* \
+ --verify-tag \
+ --prerelease \
+ --title "OpenRath $VERSION" \
+ --notes-file "release/notes/v${VERSION}.md"
+ fi
diff --git a/README.md b/README.md
index 0e990d7..96c39fa 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,35 @@ Most agent frameworks begin with an agent loop. OpenRath begins with **Session**
OpenRath is designed for this: many agents collaborating across many branchable sessions, while still tracing every role, workspace, memory write, and final output.
+## v2.0.0 durable runtime (release candidate)
+
+The `2.0.0rc1` candidate adds explicit `@step` / `@router` execution plans, durable
+Runs and checkpoints, effect reconciliation, tenant-scoped Agent Server APIs,
+and governed Provider/Tool/Sandbox/Memory adapters. The HTTP contract is
+currently **Beta**; v1 JSONL imports are historical and cannot resume an active
+Run.
+
+Embedded mode is intended for a trusted process. Agent Server mode is the
+strict durable profile: tokens need explicit action grants, object access is
+tenant/project scoped, and synchronous steps cannot declare a preemptive
+timeout. Use an async step or isolated executor for enforceable deadlines.
+
+```python
+runtime = LocalRuntime(
+ store,
+ effect_ledger=ledger,
+ production_mode=True,
+)
+server = AgentServer(store, runtime, auth=auth, audit_sink=audit)
+```
+
+Production PostgreSQL schema migration is a separate operation:
+`openrath-migrate` followed by `openrath-migrate --check`. Runtime identities
+do not need DDL privileges. See
+[`deploy/docs/operations-v2.md`](deploy/docs/operations-v2.md),
+[`deploy/docs/migration-v2.md`](deploy/docs/migration-v2.md), and the generated
+[`deploy/docs/openapi-v2.json`](deploy/docs/openapi-v2.json).
+
diff --git a/README_zh.md b/README_zh.md
index 3082295..87ea319 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -54,6 +54,17 @@
OpenRath 为此而设计:多个 Agent 在多个可分支 Session 上协作,同时仍能追踪每个 role、workspace、memory 写入和最终输出。
+## v2.0.0 durable runtime(候选版本)
+
+`2.0.0rc1` 新增显式 `@step` / `@router` 执行计划、durable Run 与
+Checkpoint、effect reconciliation、tenant-scoped Agent Server API,以及受
+治理的 Provider/Tool/Sandbox/Memory adapter。HTTP contract 在 RC 阶段仍为
+**Beta**;v1 JSONL 导入仅作为历史记录,不能恢复 active Run。
+
+Embedded mode 面向可信本地进程。Agent Server mode 是严格的 durable
+profile:token 必须具有显式 action grants,对象访问按 tenant/project
+隔离;需要强制 deadline 时应使用 async step 或 isolated executor。
+
diff --git a/benchmarks/v2_runtime.py b/benchmarks/v2_runtime.py
new file mode 100644
index 0000000..7441bee
--- /dev/null
+++ b/benchmarks/v2_runtime.py
@@ -0,0 +1,85 @@
+"""Reproducible local v2 runtime throughput/latency profile."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import platform
+import statistics
+import tempfile
+import time
+from pathlib import Path
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import LocalRuntime, SQLiteRunStore
+from rath.session import Session
+
+
+class OneStep(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def execute(self, state, context): # type: ignore[no-untyped-def]
+ return {"value": state["value"] + 1}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def percentile(values: list[float], fraction: float) -> float:
+ ordered = sorted(values)
+ return ordered[min(len(ordered) - 1, int(len(ordered) * fraction))]
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--runs", type=int, default=500)
+ parser.add_argument("--output", type=Path)
+ args = parser.parse_args()
+ if args.runs < 10:
+ parser.error("--runs must be at least 10")
+ latencies: list[float] = []
+ started = time.perf_counter()
+ with tempfile.TemporaryDirectory(prefix="openrath-benchmark-") as directory:
+ store = SQLiteRunStore(Path(directory) / "runtime.db")
+ runtime = LocalRuntime(store)
+ context = RunContext.local(revision_id=uuid4())
+ workflow = OneStep()
+ for index in range(args.runs):
+ before = time.perf_counter()
+ runtime.submit(
+ workflow,
+ session_id=uuid4(),
+ context=context,
+ state={"value": index},
+ )
+ runtime.work_once(worker_id="benchmark")
+ latencies.append((time.perf_counter() - before) * 1000)
+ duration = time.perf_counter() - started
+ report = {
+ "schema": "openrath.v2.benchmark/1",
+ "profile": "sqlite-single-worker-one-step",
+ "runs": args.runs,
+ "throughput_runs_per_second": args.runs / duration,
+ "latency_ms": {
+ "mean": statistics.mean(latencies),
+ "p50": percentile(latencies, 0.50),
+ "p95": percentile(latencies, 0.95),
+ "p99": percentile(latencies, 0.99),
+ },
+ "environment": {
+ "python": platform.python_version(),
+ "platform": platform.platform(),
+ "processor": platform.processor(),
+ },
+ }
+ value = json.dumps(report, indent=2)
+ if args.output is not None:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(value, encoding="utf-8")
+ print(value)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/deploy/compose/compose.yaml b/deploy/compose/compose.yaml
new file mode 100644
index 0000000..650ab63
--- /dev/null
+++ b/deploy/compose/compose.yaml
@@ -0,0 +1,127 @@
+name: openrath-v2
+
+services:
+ migrate:
+ build:
+ context: ../..
+ dockerfile: docker/Dockerfile
+ image: openrath:2.0.0rc1
+ entrypoint: ["openrath-migrate"]
+ environment:
+ OPENRATH_POSTGRES_DSN: postgresql://openrath:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/openrath
+ depends_on:
+ postgres:
+ condition: service_healthy
+ restart: "no"
+ read_only: true
+ tmpfs:
+ - /tmp:size=64m,mode=1777
+ security_opt:
+ - no-new-privileges:true
+ cap_drop: [ALL]
+
+ api:
+ build:
+ context: ../..
+ dockerfile: docker/Dockerfile
+ image: openrath:2.0.0rc1
+ environment:
+ OPENRATH_APP: examples.v2_server_app:app
+ OPENRATH_POSTGRES_DSN: postgresql://openrath:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/openrath
+ OPENRATH_TOKEN: ${OPENRATH_TOKEN:?set OPENRATH_TOKEN}
+ OPENRATH_TENANT_ID: ${OPENRATH_TENANT_ID:-default}
+ OPENRATH_GRANTS: assistant.read,session.read,session.create,run.read,run.create,run.cancel,run.resume,interrupt.read,interrupt.decide,feedback.create,metrics.read
+ OPENRATH_EMBEDDED_WORKER: "false"
+ ports:
+ - "${OPENRATH_PORT:-8000}:8000"
+ depends_on:
+ migrate:
+ condition: service_completed_successfully
+ healthcheck:
+ test:
+ - CMD
+ - python
+ - -c
+ - "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health/ready', timeout=2)"
+ interval: 10s
+ timeout: 3s
+ retries: 6
+ start_period: 10s
+ restart: unless-stopped
+ read_only: true
+ tmpfs:
+ - /tmp:size=128m,mode=1777
+ security_opt:
+ - no-new-privileges:true
+ cap_drop: [ALL]
+
+ worker:
+ build:
+ context: ../..
+ dockerfile: docker/Dockerfile
+ image: openrath:2.0.0rc1
+ entrypoint: ["openrath-worker"]
+ command: ["--app", "examples.v2_server_app:server"]
+ environment:
+ OPENRATH_POSTGRES_DSN: postgresql://openrath:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/openrath
+ OPENRATH_TOKEN: ${OPENRATH_TOKEN:?set OPENRATH_TOKEN}
+ OPENRATH_TENANT_ID: ${OPENRATH_TENANT_ID:-default}
+ OPENRATH_GRANTS: assistant.read,session.read,session.create,run.read,run.create,run.cancel,run.resume,interrupt.read,interrupt.decide,feedback.create,metrics.read
+ OPENRATH_EMBEDDED_WORKER: "false"
+ depends_on:
+ migrate:
+ condition: service_completed_successfully
+ restart: unless-stopped
+ read_only: true
+ tmpfs:
+ - /tmp:size=128m,mode=1777
+ security_opt:
+ - no-new-privileges:true
+ cap_drop: [ALL]
+
+ postgres:
+ image: postgres:17-alpine@sha256:742f40ea20b9ff2ff31db5458d127452988a2164df9e17441e191f3b72252193
+ environment:
+ POSTGRES_DB: openrath
+ POSTGRES_USER: openrath
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U openrath -d openrath"]
+ interval: 5s
+ timeout: 3s
+ retries: 12
+ restart: unless-stopped
+
+ redis:
+ image: redis:8-alpine@sha256:8096655e437712b07503796fb64d81359256cfcff0ab29d95a7da72863786efb
+ command: ["redis-server", "--save", "", "--appendonly", "no"]
+ profiles: ["signals"]
+ healthcheck:
+ test: ["CMD", "redis-cli", "ping"]
+ interval: 5s
+ timeout: 3s
+ retries: 12
+ restart: unless-stopped
+ read_only: true
+ tmpfs:
+ - /data:size=64m
+ security_opt:
+ - no-new-privileges:true
+ cap_drop: [ALL]
+
+ minio:
+ image: minio/minio:RELEASE.2025-09-07T16-13-09Z@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
+ command: ["server", "/data", "--console-address", ":9001"]
+ profiles: ["artifacts"]
+ environment:
+ MINIO_ROOT_USER: ${MINIO_ROOT_USER:-openrath-local}
+ MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set MINIO_ROOT_PASSWORD}
+ volumes:
+ - minio-data:/data
+ restart: unless-stopped
+
+volumes:
+ postgres-data:
+ minio-data:
diff --git a/deploy/docs/api-governance-v2.md b/deploy/docs/api-governance-v2.md
new file mode 100644
index 0000000..1f08f95
--- /dev/null
+++ b/deploy/docs/api-governance-v2.md
@@ -0,0 +1,89 @@
+# OpenRath v2 API and maintenance policy
+
+This policy is part of the v2.0.0 release candidate. The RC publishes it for
+compatibility feedback; final Stable promotions and the v1 maintenance window
+still require repository-owner approval before GA.
+
+## Stability levels
+
+- **Stable**: documented public Python symbols, the `/v1` HTTP resource model,
+ persisted v2 schemas, stable error codes, and migration CLI. Breaking changes
+ require a new major version.
+- **Beta**: explicitly labelled evaluation, deployment-helper, or adapter SDK
+ surfaces. A breaking change requires release notes, a migration path, and at
+ least one minor release of notice.
+- **Experimental**: explicitly labelled research integrations and extension
+ hooks. They may change in a minor release and must not be required for the
+ durable Run, security, or storage contracts.
+- Unlabelled v2 additions are not Stable. They remain Experimental until a
+ release note and this policy explicitly classify them. Internal modules and
+ names beginning with `_` are not public contracts.
+
+The Agent Server OpenAPI document currently labels `/v1` operations **Beta**.
+Stable error codes and persisted fields may be promoted independently only
+after the RC evidence gate passes.
+
+For `2.0.0rc1`, the Python v1 façade remains supported and the Agent Server
+remains Beta. The RC does not begin or end a maintenance window.
+
+## Action and object authorization
+
+Authentication alone grants no access. Tokens carry explicit action grants;
+`*` is an intentionally privileged reference-only grant. The service enforces
+the following minimum actions:
+
+| Resource | Read | Mutate/control |
+| --- | --- | --- |
+| Assistant | `assistant.read` | `assistant.create` |
+| Session | `session.read` | `session.create` |
+| Run | `run.read` | `run.create`, `run.cancel`, `run.resume` |
+| Interrupt | `interrupt.read` | `interrupt.decide` |
+| Feedback | — | `feedback.create` |
+| Memory | `memory.search` | `memory.put`, `memory.delete` |
+| Metrics | `metrics.read` | — |
+
+Run, Session, Interrupt, Feedback, and Memory operations also verify tenant and
+project scope. A user-scoped memory namespace cannot name another principal
+unless the token has `memory.admin`. Cross-scope objects are returned as not
+found to avoid disclosing their existence. Control-plane mutations emit
+redacted security audit events when an `AuditSink` is configured.
+
+## SemVer and deprecation
+
+- Patch releases contain compatible fixes, security updates, and documentation.
+- Minor releases may add compatible functionality.
+- Breaking Stable API or persisted-schema changes require a new major release.
+- Stable APIs are deprecated before removal. The default notice is two minor
+ releases and at least six months, unless retaining the API would preserve an
+ actively exploitable vulnerability.
+- Database migrations are forward-only and additive during the rollback
+ window. Application rollback precedes removal of old columns or tables.
+
+## v1 compatibility
+
+The v1 Python facade remains available through the owner-approved maintenance
+window. v1 JSONL Sessions import as non-resumable historical evidence because
+they do not contain a durable program counter or effect outcome. The exact end
+date for v1 security and critical-fix support must be approved in
+`review/v2.0.0/release-approval.md`; the implementation does not invent that
+organizational commitment.
+
+## Security reporting
+
+Report suspected vulnerabilities privately through the repository's GitHub
+Security Advisory flow. Do not open a public issue with exploit details,
+credentials, tenant data, or unredacted traces. Maintainers should acknowledge,
+triage severity, coordinate a fix and advisory, and publish remediation and
+affected-version information. Secrets found in reports must be rotated rather
+than copied into tests or logs.
+
+## Release evidence
+
+Every release candidate must link:
+
+- compatibility, migration, and rollback evidence;
+- unit, conformance, real-backend, chaos, and tenant/security tests;
+- a reproducible image digest and dependency lock;
+- a CycloneDX SBOM and zero-unaccepted HIGH/CRITICAL scan;
+- hardware-bound benchmark and soak profiles;
+- explicit owner approval for tag, push, image publication, and deployment.
diff --git a/deploy/docs/drills-v2.md b/deploy/docs/drills-v2.md
new file mode 100644
index 0000000..63a4cd6
--- /dev/null
+++ b/deploy/docs/drills-v2.md
@@ -0,0 +1,113 @@
+# OpenRath v2 target validation and recovery drills
+
+These procedures produce Gate C evidence for one immutable source commit. Run
+them only in an approved, isolated target-like environment with an operations
+owner, a rollback decision maker, tested backups, and a documented maintenance
+window. A Docker Desktop rehearsal does not satisfy this gate.
+
+## Evidence directory
+
+Create one runner-local directory below the configured
+`OPENRATH_GA_EVIDENCE_ROOT`. Its leaf name is the bundle ID used when
+dispatching `Collect v2.0.0 Gate C evidence`.
+
+```text
+//
+ tests.json
+ live-adapters.json
+ performance.json
+ soak.json
+ drills.json
+ compatibility.json
+ evidence/
+ ...
+```
+
+Every command and target observation must be written below `evidence/`.
+Never place credentials, bearer headers, kubeconfig content, database
+passwords, or provider responses containing user data in these files. The
+collector accepts only UTF-8 JSON/log/text/XML/CSV files and rejects common
+credential patterns before upload.
+
+## Live adapters
+
+Capture logs for the required live Provider, OpenSandbox, and OpenViking
+lifecycle tests. Skips, `continue-on-error`, or a successful offline-only run
+are failures. Record the gate with `record_gate.py`; the details object must
+set `provider`, `opensandbox`, and `openviking` to `passed`.
+
+## Capacity and scaling
+
+Deploy the same image digest and source commit for all samples. Run
+`load_v2.py` for a minimum of five minutes for:
+
+1. single-host, one embedded worker;
+2. split profile, one worker replica;
+3. split profile, two worker replicas;
+4. split profile, four worker replicas.
+
+The authentication token is read from `OPENRATH_TOKEN`; it is never a command
+argument or report field. Combine the four raw samples with
+`build_performance_report.py`. Four-worker throughput must be at least 70% of
+linear scaling from the one-worker split baseline.
+
+## Eight-hour soak
+
+Run `load_v2.py` against the split target for at least 28,800 seconds without
+`--max-runs`. Capture resource snapshots before warm-up and after completion.
+Each snapshot uses:
+
+```json
+{
+ "schema": "openrath.v2.resource-snapshot/1",
+ "source_commit": "<40 hex>",
+ "phase": "before",
+ "captured_at": "",
+ "components": {
+ "api": {"memory_bytes": 0, "restarts": 0},
+ "worker": {"memory_bytes": 0, "restarts": 0},
+ "postgres": {"connections": 0, "storage_bytes": 0}
+ }
+}
+```
+
+An operations owner compares time-series telemetry, queue age, database
+connections/storage, pod restarts, memory, and error logs. The signed-off
+assessment must use `openrath.v2.resource-assessment/1`, identify the same
+commit and assessor, explain the observed delta, and set
+`unexplained_resource_growth` to `false`. Build `soak.json` with
+`build_soak_report.py`.
+
+## Fault and recovery matrix
+
+Stop immediately if data integrity is uncertain, the backup cannot be read, a
+non-idempotent effect is replayed automatically, or rollback cannot complete.
+Record start/end timestamps, operator, recovery time, observed state, and data
+loss for every drill:
+
+1. terminate an active worker and verify lease expiry, fencing, and requeue;
+2. terminate an API replica and verify readiness, reconnect, and SSE resume;
+3. interrupt PostgreSQL and verify readiness becomes 503 with no false success;
+4. interrupt Redis and verify durable state remains in PostgreSQL;
+5. restart S3/object storage and verify hashes and bounded retry semantics;
+6. restore PostgreSQL and artifacts into an isolated namespace, run
+ `openrath-migrate --check`, and verify RPO 0 / RTO at most 60 minutes;
+7. roll from the previous supported release to the candidate, roll the
+ application back while retaining additive schema, then roll forward again.
+
+Put the structured results in `openrath.v2.drill-results/1` and bind the raw
+operator logs with `build_drill_report.py`. The builder records evidence only;
+it never injects faults.
+
+## Collection
+
+Verify locally on the target runner:
+
+```bash
+uv run python scripts/release/verify_gate_reports.py \
+ "$OPENRATH_GA_EVIDENCE_ROOT/" \
+ --source-commit "$(git rev-parse HEAD)"
+```
+
+Then dispatch the protected collector from `main`. Do not move, edit, or reuse
+the bundle after collection.
diff --git a/deploy/docs/known-limitations-v2.md b/deploy/docs/known-limitations-v2.md
new file mode 100644
index 0000000..8052a41
--- /dev/null
+++ b/deploy/docs/known-limitations-v2.md
@@ -0,0 +1,27 @@
+# OpenRath v2.0.0 release-candidate limitations
+
+These limitations are part of the `2.0.0rc1` contract and must not be omitted
+from release notes.
+
+- The Agent Server `/v1` HTTP contract is Beta during the RC. Stable error
+ codes and persisted fields are promoted only after compatibility review.
+- v1 JSONL Sessions import as non-resumable history. They do not contain a
+ durable program counter or an effect outcome.
+- Embedded mode trusts the local process. It is not a multi-tenant isolation
+ boundary.
+- A synchronous Python step cannot be preempted safely in-process. The durable
+ server profile rejects synchronous timeout declarations; use an async or
+ isolated executor.
+- Redis improves wake, cancel, and stream latency but never stores final Run
+ state. Its loss falls back to bounded PostgreSQL polling.
+- Exactly-once behavior is not promised for arbitrary external side effects.
+ Non-idempotent ambiguous outcomes stop in `NEEDS_REVIEW`.
+- The static-token reference application is a deployment example. Operators
+ must integrate their identity provider, secret manager, TLS ingress, audit
+ collector, retention, and network policy.
+- OpenViking and live provider support remains conditional on the published
+ compatibility range and successful lifecycle validation with the selected
+ service.
+- Capacity numbers are hardware/workload profiles, not universal SLA values.
+- Webhooks, cron triggers, enterprise UI, SAML/SCIM, billing, and cross-region
+ active-active storage are outside the v2.0.0 scope.
diff --git a/deploy/docs/migration-v2.md b/deploy/docs/migration-v2.md
new file mode 100644
index 0000000..486ceb2
--- /dev/null
+++ b/deploy/docs/migration-v2.md
@@ -0,0 +1,74 @@
+# OpenRath v1 → v2 migration
+
+OpenRath v2 uses durable Runs, checkpoints, effect ledgers, immutable
+revisions, and tenant-scoped resources. A v1 JSONL Session contains a
+transcript but no reliable program counter or external-side-effect outcome.
+It is therefore imported as historical evidence and is never resumed as an
+active v2 Run.
+
+## Safe procedure
+
+1. Stop v1 writers or take a filesystem snapshot. Keep the original data
+ read-only throughout the migration.
+2. Back up PostgreSQL and the artifact root.
+3. Run an inventory (no writes):
+
+ ```bash
+ python scripts/migrate_v1_to_v2.py \
+ --source /data/v1/sessions \
+ --report migration-inventory.json \
+ --tenant TENANT_ID
+ ```
+
+4. Review every `invalid` or partial Session. Partial Sessions import as
+ `NEEDS_REVIEW`; closed Sessions import as historical `SUCCEEDED` Runs.
+5. Apply with explicit storage targets:
+
+ ```bash
+ python scripts/migrate_v1_to_v2.py \
+ --source /data/v1/sessions \
+ --report migration-result.json \
+ --tenant TENANT_ID \
+ --apply \
+ --postgres-dsn "$OPENRATH_POSTGRES_DSN" \
+ --artifact-root /data/openrath-artifacts
+ ```
+
+The import is idempotent per legacy Session ID. Imported content carries
+`provenance=legacy-import`, `trust=untrusted`, and `resumable=false`.
+Remote sandbox identities are not reattached. Credentials are not copied.
+An invalid filename or malformed Session is isolated into the JSON report and
+does not abort the remaining batch.
+
+On Windows PowerShell, use the same dry-run/apply split:
+
+```powershell
+uv run python scripts/migrate_v1_to_v2.py `
+ --source C:\data\v1\sessions `
+ --report .\migration-inventory.json `
+ --tenant TENANT_ID
+
+uv run python scripts/migrate_v1_to_v2.py `
+ --source C:\data\v1\sessions `
+ --report .\migration-result.json `
+ --tenant TENANT_ID `
+ --apply `
+ --postgres-dsn $env:OPENRATH_POSTGRES_DSN `
+ --artifact-root C:\data\openrath-artifacts
+```
+
+Run database schema migration separately with a DDL-capable identity:
+
+```bash
+openrath-migrate
+openrath-migrate --check
+```
+
+`PostgresRunStore` does not auto-migrate by default; API and worker roles need
+only runtime DML privileges.
+
+## Rollback
+
+The migration does not mutate v1 files. Roll back application traffic to v1
+and retain the v2 database and artifacts for investigation. Do not down-migrate
+v2 Runs into v1 JSONL because checkpoint and effect semantics would be lost.
diff --git a/deploy/docs/openapi-v2.json b/deploy/docs/openapi-v2.json
new file mode 100644
index 0000000..de58914
--- /dev/null
+++ b/deploy/docs/openapi-v2.json
@@ -0,0 +1,2537 @@
+{
+ "components": {
+ "schemas": {
+ "Assistant": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "kind": {
+ "enum": [
+ "template",
+ "alias"
+ ],
+ "type": "string"
+ },
+ "revision_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "template_id": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "template_id",
+ "revision_id",
+ "kind"
+ ],
+ "type": "object"
+ },
+ "CreateAssistantRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "template_id": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "template_id"
+ ],
+ "type": "object"
+ },
+ "CreateRunRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "assistant_id": {
+ "type": "string"
+ },
+ "priority": {
+ "type": "integer"
+ },
+ "session_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "state": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "assistant_id",
+ "session_id"
+ ],
+ "type": "object"
+ },
+ "CreateSessionRunRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "assistant_id": {
+ "type": "string"
+ },
+ "priority": {
+ "type": "integer"
+ },
+ "state": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "assistant_id"
+ ],
+ "type": "object"
+ },
+ "ErrorResponse": {
+ "properties": {
+ "error": {
+ "properties": {
+ "code": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "code",
+ "message"
+ ],
+ "type": "object"
+ }
+ },
+ "required": [
+ "error"
+ ],
+ "type": "object"
+ },
+ "Feedback": {
+ "additionalProperties": true,
+ "type": "object"
+ },
+ "FeedbackRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "key": {
+ "type": "string"
+ },
+ "run_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "score": {
+ "maximum": 1,
+ "minimum": -1,
+ "type": [
+ "number",
+ "null"
+ ]
+ },
+ "value": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "run_id",
+ "key"
+ ],
+ "type": "object"
+ },
+ "Health": {
+ "properties": {
+ "status": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "status"
+ ],
+ "type": "object"
+ },
+ "Info": {
+ "additionalProperties": true,
+ "type": "object"
+ },
+ "InterruptDecisionRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "kind": {
+ "enum": [
+ "approve",
+ "edit",
+ "reject"
+ ],
+ "type": "string"
+ },
+ "payload": {
+ "type": "object"
+ },
+ "reason": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "kind",
+ "reason"
+ ],
+ "type": "object"
+ },
+ "ItemPage": {
+ "properties": {
+ "items": {
+ "items": {},
+ "type": "array"
+ },
+ "next": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "items",
+ "next"
+ ],
+ "type": "object"
+ },
+ "MemoryRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "agent_id": {
+ "type": "string"
+ },
+ "payload": {
+ "type": "object"
+ },
+ "session_id": {
+ "type": "string"
+ },
+ "tenant_id": {
+ "type": "string"
+ },
+ "user_id": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ResumeRunRequest": {
+ "additionalProperties": false,
+ "properties": {
+ "confirm": {
+ "const": true
+ }
+ },
+ "required": [
+ "confirm"
+ ],
+ "type": "object"
+ },
+ "Run": {
+ "properties": {
+ "id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "next_nodes": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "plan_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "revision_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "session_id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "state": {
+ "type": "object"
+ },
+ "status": {
+ "enum": [
+ "queued",
+ "running",
+ "waiting",
+ "succeeded",
+ "failed",
+ "cancelled",
+ "timed_out",
+ "needs_review"
+ ],
+ "type": "string"
+ },
+ "version": {
+ "minimum": 0,
+ "type": "integer"
+ }
+ },
+ "required": [
+ "id",
+ "plan_id",
+ "revision_id",
+ "session_id",
+ "status",
+ "version"
+ ],
+ "type": "object"
+ },
+ "Session": {
+ "properties": {
+ "created_at": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "id": {
+ "format": "uuid",
+ "type": "string"
+ },
+ "runs": {
+ "items": {
+ "$ref": "#/components/schemas/Run"
+ },
+ "type": "array"
+ },
+ "tenant_id": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "tenant_id",
+ "created_at"
+ ],
+ "type": "object"
+ }
+ },
+ "securitySchemes": {
+ "bearerAuth": {
+ "scheme": "bearer",
+ "type": "http"
+ }
+ }
+ },
+ "info": {
+ "description": "Beta v2 durable Agent Server API.",
+ "title": "OpenRath Agent Server",
+ "version": "2.0.0rc1"
+ },
+ "openapi": "3.1.0",
+ "paths": {
+ "/health/live": {
+ "get": {
+ "operationId": "live",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Health"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [],
+ "summary": "Process liveness",
+ "x-openrath-action": null,
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/health/ready": {
+ "get": {
+ "operationId": "ready",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Health"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [],
+ "summary": "Dependency readiness",
+ "x-openrath-action": null,
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/info": {
+ "get": {
+ "operationId": "info",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Info"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [],
+ "summary": "Server capabilities",
+ "x-openrath-action": null,
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/metrics": {
+ "get": {
+ "operationId": "metrics",
+ "responses": {
+ "200": {
+ "content": {
+ "text/plain": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Prometheus metrics",
+ "x-openrath-action": "metrics.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/assistants": {
+ "get": {
+ "operationId": "listAssistants",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ItemPage"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "List deployment templates and tenant aliases",
+ "x-openrath-action": "assistant.read",
+ "x-openrath-stability": "beta"
+ },
+ "post": {
+ "operationId": "createAssistantAlias",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/CreateAssistantRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "201": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Assistant"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Create a tenant assistant alias",
+ "x-openrath-action": "assistant.create",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/assistants/{assistant_id}": {
+ "get": {
+ "operationId": "getAssistant",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "assistant_id",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Assistant"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Get an assistant template or alias",
+ "x-openrath-action": "assistant.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/feedback": {
+ "post": {
+ "operationId": "createFeedback",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/FeedbackRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "201": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Feedback"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Create run feedback",
+ "x-openrath-action": "feedback.create",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/interrupts": {
+ "get": {
+ "operationId": "listInterrupts",
+ "parameters": [
+ {
+ "in": "query",
+ "name": "after",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "limit",
+ "required": false,
+ "schema": {
+ "maximum": 200,
+ "minimum": 1,
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ItemPage"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "List pending durable interrupts",
+ "x-openrath-action": "interrupt.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/interrupts/{interrupt_id}/decision": {
+ "post": {
+ "operationId": "decideInterrupt",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "interrupt_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/InterruptDecisionRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Submit a durable interrupt decision",
+ "x-openrath-action": "interrupt.decide",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs": {
+ "get": {
+ "operationId": "listRuns",
+ "parameters": [
+ {
+ "in": "query",
+ "name": "after",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "limit",
+ "required": false,
+ "schema": {
+ "maximum": 200,
+ "minimum": 1,
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ItemPage"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "List runs by cursor",
+ "x-openrath-action": "run.read",
+ "x-openrath-stability": "beta"
+ },
+ "post": {
+ "operationId": "createRun",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/CreateRunRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "201": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Create a durable run",
+ "x-openrath-action": "run.create",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs/{run_id}": {
+ "get": {
+ "operationId": "getRun",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "run_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Get a durable run",
+ "x-openrath-action": "run.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs/{run_id}/cancel": {
+ "post": {
+ "operationId": "cancelRun",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "run_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Cancel a run",
+ "x-openrath-action": "run.cancel",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs/{run_id}/events": {
+ "get": {
+ "operationId": "listRunEvents",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "run_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "after",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "limit",
+ "required": false,
+ "schema": {
+ "maximum": 200,
+ "minimum": 1,
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ItemPage"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Replay ordered durable run events",
+ "x-openrath-action": "run.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs/{run_id}/resume": {
+ "post": {
+ "operationId": "resumeRun",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "run_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ResumeRunRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Resume a run requiring operator review",
+ "x-openrath-action": "run.resume",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/runs/{run_id}/stream": {
+ "get": {
+ "operationId": "streamRunEvents",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "run_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "after",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "limit",
+ "required": false,
+ "schema": {
+ "maximum": 200,
+ "minimum": 1,
+ "type": "integer"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "text/event-stream": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Stream ordered run events with cursor resume",
+ "x-openrath-action": "run.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/sessions": {
+ "post": {
+ "operationId": "createSession",
+ "responses": {
+ "201": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Session"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Create a durable session",
+ "x-openrath-action": "session.create",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/sessions/{session_id}": {
+ "get": {
+ "operationId": "getSession",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Session"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Get a durable session",
+ "x-openrath-action": "session.read",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/sessions/{session_id}/runs": {
+ "post": {
+ "operationId": "createSessionRun",
+ "parameters": [
+ {
+ "in": "path",
+ "name": "session_id",
+ "required": true,
+ "schema": {
+ "format": "uuid",
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/CreateSessionRunRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "201": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Run"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Create a run in an existing session",
+ "x-openrath-action": "run.create",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/store/items": {
+ "delete": {
+ "operationId": "deleteStoreItem",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/MemoryRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Delete a governed memory item",
+ "x-openrath-action": "memory.delete",
+ "x-openrath-stability": "beta"
+ },
+ "post": {
+ "operationId": "putStoreItem",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/MemoryRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Write a governed memory item",
+ "x-openrath-action": "memory.put",
+ "x-openrath-stability": "beta"
+ }
+ },
+ "/v1/store/search": {
+ "post": {
+ "operationId": "searchStore",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/MemoryRequest"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ },
+ "description": "Success"
+ },
+ "400": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Invalid request"
+ },
+ "401": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Unauthenticated"
+ },
+ "403": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Forbidden"
+ },
+ "404": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Not found"
+ },
+ "409": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Conflict"
+ },
+ "429": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ },
+ "description": "Resource exhausted"
+ }
+ },
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "summary": "Search governed memory",
+ "x-openrath-action": "memory.search",
+ "x-openrath-stability": "beta"
+ }
+ }
+ }
+}
diff --git a/deploy/docs/operations-v2.md b/deploy/docs/operations-v2.md
new file mode 100644
index 0000000..106a8f0
--- /dev/null
+++ b/deploy/docs/operations-v2.md
@@ -0,0 +1,85 @@
+# OpenRath v2 operations
+
+## Release and upgrade
+
+- Build immutable images by Git commit digest; never deploy a mutable `latest`.
+- Replace every review tag in `deploy/kubernetes/openrath.yaml` with the exact
+ `image@sha256:...` produced for the candidate. A manifest containing a tag is
+ a template, not release evidence.
+- Run `openrath-migrate --check` before traffic and `openrath-migrate` as a
+ single pre-deploy Job.
+- Database changes are additive in v2.0.0. Roll application pods back first;
+ retain added columns/tables until the rollback window closes.
+- Take and restore-test PostgreSQL and artifact backups before an upgrade.
+
+The server durable profile rejects synchronous steps that declare a timeout:
+an in-process Python thread cannot be preempted safely. Use an async handler or
+an isolated executor. Embedded compatibility mode waits for a synchronous
+handler to return before recording timeout and must never be presented as a
+preemptive cancellation guarantee.
+
+`LocalTrustedPolicy` is limited to an explicit local `trusted_host` grant. It
+allows same-process filesystem/network behavior and is unsuitable for
+untrusted tenants. Service deployments should supply a fail-closed policy,
+governed adapter executors, durable effect ledger, and audit sink.
+
+The reference server requires `OPENRATH_GRANTS` with explicit actions and
+rejects the wildcard grant. It emits redacted newline-delimited JSON audit
+records to stdout. Production operators must configure a collector, retention,
+access control, and delivery alert for that stream; an in-memory sink is never
+production evidence.
+
+The Kubernetes template is fail closed for egress. PostgreSQL, Redis, S3, and
+an HTTPS egress gateway must run in a namespace labelled
+`openrath.io/data-plane=allowed`; DNS is limited to `kube-system`. If the CNI
+supports FQDN policies, restrict provider and object-store hostnames there.
+Do not replace this with unrestricted `to: []` egress.
+
+## Incident runbooks
+
+### PostgreSQL unavailable
+
+Stop accepting new Runs (`/health/ready` returns 503), keep existing pods from
+restart loops, restore database connectivity, verify schema and lease expiry,
+then let workers requeue expired leases. Never substitute Redis as state.
+
+### Redis unavailable
+
+Runs remain durable. Alert on signal failures and increased queue latency,
+restore Redis, and allow polling to continue. Do not reconstruct Run state
+from Redis.
+
+### Worker terminated or stuck
+
+Confirm the worker lease has expired, call the orphan reconciliation loop, and
+verify the fencing token increased. A stale worker must fail its next commit.
+Inspect dispatched non-idempotent ToolInvocations; they must enter
+`NEEDS_REVIEW`, not automatic retry.
+
+### Queue backlog
+
+Measure queued age, database lock time, provider saturation, and artifact
+latency. Scale replicas only after confirming PostgreSQL connection capacity.
+Rate-limit tenants producing disproportionate load.
+
+### Artifact store unavailable
+
+Keep the Run/checkpoint durable, fail or pause the affected step, and do not
+inline payloads beyond the configured limit. Restore object storage and verify
+SHA-256 before resuming.
+
+## Backup/restore exercise
+
+Quarterly, restore PostgreSQL and artifacts into an isolated environment,
+run `openrath-migrate --check`, fetch historical Runs and artifacts, requeue
+an expired lease, and verify a non-idempotent ambiguous invocation remains
+blocked for review.
+
+## RC evidence boundary
+
+Offline tests, a locally built wheel, a mutable image tag, or a Fake provider
+do not approve a release. RC evidence must be generated from one immutable
+commit and include real provider/sandbox/memory lifecycles, PostgreSQL/Redis/S3
+restart drills, backup/restore, rollback, scale, soak, SBOM, vulnerability scan,
+and the published image digest. Missing infrastructure is recorded as a
+release blocker rather than silently skipped.
diff --git a/deploy/docs/plans/2026-07-30-ga-gate-c-design.md b/deploy/docs/plans/2026-07-30-ga-gate-c-design.md
new file mode 100644
index 0000000..dc6e314
--- /dev/null
+++ b/deploy/docs/plans/2026-07-30-ga-gate-c-design.md
@@ -0,0 +1,60 @@
+# OpenRath v2.0.0 Gate C Design
+
+## Objective and trust boundary
+
+Gate C must turn target-environment observations into a reproducible,
+same-commit artifact without treating local tests, handwritten status, or a
+short rehearsal as production evidence. The release preparation workflow may
+consume only an artifact produced by the dedicated `Collect v2.0.0 Gate C
+evidence` workflow. That workflow must run from `main`, on the exact candidate
+commit, in a protected `ga-evidence` environment, and on a runner labelled
+`openrath-ga`.
+
+The target runner owns infrastructure access. GitHub-hosted release jobs do not
+receive Kubernetes, provider, database, or object-store credentials. Operators
+place a bundle below a configured runner-local evidence root. The bundle name
+is a restricted identifier, not an arbitrary path. The collector copies the
+bundle to an isolated temporary directory, validates every report and referenced
+file, and uploads it as `openrath-v2.0.0-ga-input`.
+
+The GA preparation workflow independently verifies the source SHA, workflow
+name, event type, branch, report semantics, and referenced hashes before it
+builds any public candidate.
+
+## Reports and target tooling
+
+Six reports use `openrath.ga-gate-report/1`: tests, live adapters, performance,
+soak, drills, and compatibility. Every report identifies the exact source
+commit, a timezone-aware generation time, a target-like environment profile,
+structured details, open risks, and at least one evidence file. Evidence
+entries are relative paths with byte size and SHA-256; absolute paths,
+traversal, symlinks, missing files, and hash mismatches fail closed.
+
+`record_gate.py` records tests, live-adapter, drill, and compatibility outcomes
+from immutable logs produced by the approved operator commands.
+`load_v2.py` executes bounded authenticated HTTP lifecycle load against a
+deployed OpenRath API without printing credentials. Separate single-host and
+one/two/four-worker samples are combined by `build_performance_report.py`,
+which calculates four-worker scaling efficiency.
+
+The existing local SQLite soak remains a review tool. Target soak evidence is
+recorded from an eight-hour run plus resource snapshots and must explicitly
+state zero errors and no unexplained growth. Drill recording never injects a
+fault itself: destructive PostgreSQL, Redis, S3, API, worker, backup/restore,
+and rollout/rollback operations remain operator-controlled and require
+target-specific runbooks.
+
+## Recovery and verification
+
+Collector reruns are immutable at the report level: all files are copied and
+hashed before upload, and a changed bundle produces a different artifact. A
+failed or cancelled run cannot authorize preparation. Release preparation
+checks the collector workflow identity instead of accepting an artifact from
+any successful workflow.
+
+Unit tests cover path containment, symlink rejection, evidence hashing, gate
+semantics, performance calculations, target/rehearsal separation, and workflow
+identity checks. Actionlint and zizmor validate the workflows. Short local
+HTTP tests validate the load client, while real Gate C execution remains
+blocked until the approved secrets, target cluster, and protected runner are
+available.
diff --git a/deploy/docs/plans/2026-07-30-ga-gate-c-implementation.md b/deploy/docs/plans/2026-07-30-ga-gate-c-implementation.md
new file mode 100644
index 0000000..1a612c5
--- /dev/null
+++ b/deploy/docs/plans/2026-07-30-ga-gate-c-implementation.md
@@ -0,0 +1,103 @@
+# OpenRath v2.0.0 Gate C Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
+
+**Goal:** Build a fail-closed target-evidence toolchain and dedicated workflow
+that produces the exact same-SHA Gate C artifact required by the GA preparation
+workflow.
+
+**Architecture:** Target-side tools record immutable evidence files and six
+strict gate reports. A protected self-hosted collector validates and uploads
+the bundle; the GA preparation workflow accepts only that workflow identity
+and exact candidate SHA.
+
+**Tech Stack:** Python 3.12, httpx, pytest, GitHub Actions, pinned GitHub
+actions, actionlint, zizmor.
+
+---
+
+### Task 1: Harden the Gate C report contract
+
+**Files:**
+- Modify: `scripts/release/verify_gate_reports.py`
+- Create: `scripts/release/record_gate.py`
+- Modify: `release/evidence/schema/ga-gate-report.schema.json`
+- Modify: `tests/deployment/test_ga_gate_reports.py`
+
+**Steps:**
+1. Add failing tests for target-like environment requirements, evidence file
+ hashes, traversal, symlinks, and missing evidence.
+2. Run `uv run pytest tests/deployment/test_ga_gate_reports.py -q`.
+3. Implement strict evidence validation and the reusable report recorder.
+4. Run the targeted test again and confirm it passes.
+
+### Task 2: Add bounded target load and performance reporting
+
+**Files:**
+- Create: `scripts/release/load_v2.py`
+- Create: `scripts/release/build_performance_report.py`
+- Create: `tests/deployment/test_release_load.py`
+
+**Steps:**
+1. Add tests for authentication redaction, lifecycle completion, sample
+ validation, profile coverage, and scaling efficiency.
+2. Implement an httpx lifecycle load client that writes raw JSON samples.
+3. Implement a combiner requiring single-host plus split one/two/four-worker
+ samples and zero errors.
+4. Run `uv run pytest tests/deployment/test_release_load.py -q`.
+
+### Task 3: Add target soak and drill recording
+
+**Files:**
+- Create: `scripts/release/build_soak_report.py`
+- Create: `scripts/release/build_drill_report.py`
+- Create: `deploy/docs/drills-v2.md`
+- Create: `tests/deployment/test_release_operations_evidence.py`
+
+**Steps:**
+1. Add failing tests for the 28,800-second minimum, zero-error requirement,
+ resource-growth decision, complete fault matrix, backup/restore, and
+ rollout/rollback.
+2. Implement report builders that bind raw logs and resource snapshots without
+ executing destructive operations.
+3. Document exact operator evidence and stop conditions.
+4. Run the targeted operations-evidence tests.
+
+### Task 4: Add the protected collector workflow
+
+**Files:**
+- Create: `.github/workflows/collect-v2-ga-evidence.yml`
+- Modify: `.github/workflows/release-v2-ga.yml`
+- Modify: `tests/deployment/test_release_version.py`
+- Modify: `release/checklists/v2.0.0-ga.md`
+
+**Steps:**
+1. Add workflow contract tests requiring `main`, the exact SHA, the protected
+ environment, fixed self-hosted labels, safe bundle identifiers, and the
+ exact artifact name.
+2. Implement the collector with pinned actions and minimal permissions.
+3. Restrict GA preparation to a successful workflow-dispatch run named
+ `Collect v2.0.0 Gate C evidence` on `main`.
+4. Run workflow contract tests, actionlint, and zizmor.
+
+### Task 5: Verify and publish the PR update
+
+**Files:**
+- Modify: PR #51 description
+
+**Steps:**
+1. Run Ruff, MyPy, targeted tests, and the complete non-external suite.
+2. Run actionlint, zizmor, YAML parsing, and `git diff --check`.
+3. Commit the exact Gate C files and push the existing PR branch.
+4. Update PR #51 with the new trust boundary and validation results.
+5. Monitor all PR checks to completion.
+
+### External handoff
+
+1. Configure approved Provider/OpenViking secrets without sharing values.
+2. Register a Linux self-hosted runner labelled `openrath-ga`.
+3. Configure the protected `ga-evidence` environment and its evidence-root
+ variable.
+4. Provision the target cluster and run the documented 1/2/4-worker, eight-hour
+ soak, and recovery drills on the final SHA.
+5. Dispatch the collector and provide its run ID to GA preparation.
diff --git a/deploy/docs/threat-model-v2.md b/deploy/docs/threat-model-v2.md
new file mode 100644
index 0000000..e784766
--- /dev/null
+++ b/deploy/docs/threat-model-v2.md
@@ -0,0 +1,66 @@
+# OpenRath v2 threat model
+
+Status: release-candidate baseline. Residual risks remain blocking for GA until
+the linked target-environment evidence is attached.
+
+## Assets and security objectives
+
+| Asset | Required property |
+| --- | --- |
+| Provider, Tool, Sandbox, Memory, database, object-store credentials | Confidential; referenced rather than persisted in Run state |
+| Tenant and project data | Isolated at every API, store, adapter, and artifact boundary |
+| Run, Event, Checkpoint, Interrupt, and Effect records | Durable, ordered, attributable, and protected from stale writers |
+| Artifact content | Tenant scoped, size bounded, integrity checked |
+| Revision and ExecutionPlan | Immutable identity bound to deployed content |
+| Security audit records | Redacted, correlated, append-only at the configured collector |
+
+## Trust boundaries
+
+1. HTTP ingress is untrusted until the authentication provider produces a
+ `SecurityContext`. Request tenant/project fields never override that context.
+2. Provider, Tool, MCP, Sandbox, Memory, and recalled content are external and
+ untrusted. Each adapter call receives a reduced context and policy decision.
+3. PostgreSQL is the durable source of truth. Redis is only a wake/cancel/fanout
+ accelerator and cannot reconstruct Run state.
+4. S3-compatible storage is outside the process boundary. Artifact size,
+ tenant scope, and SHA-256 are checked independently of object metadata.
+5. Workers are replaceable and may be stale. Lease expiry and fencing tokens
+ prevent an old worker from committing after ownership changes.
+6. Operators, registry publishers, migration identities, and runtime identities
+ are separate roles. Runtime identities do not need DDL or release rights.
+
+## Principal abuse cases and controls
+
+| Abuse case | Control | Required evidence |
+| --- | --- | --- |
+| Tenant/project/object bypass | `SecurityContext` authority, action grants, scoped store queries, not-found masking | Cross-scope API/store negative tests |
+| Bearer or provider secret leakage | `SecretRef`, redacted repr/log/trace/audit/error paths | Secret canary tests and repository scan |
+| SSRF through URL ingestion | Explicit allowed HTTP hosts, redirect rejection, bounded response | Loopback/link-local/private-range and redirect tests |
+| Path or symlink escape | Canonical root checks, symlink rejection, bounded file operations | Traversal/symlink tests on supported platforms |
+| Prompt or recalled-content privilege escalation | Trust/provenance labels; external text never becomes SYSTEM authority | Trust-preservation tests |
+| Duplicate delivery or stale worker commit | CAS, idempotency key, lease and fencing token | Duplicate/stale-token chaos tests |
+| Ambiguous non-idempotent effect replay | Durable effect ledger and `NEEDS_REVIEW` | Kill-after-dispatch test |
+| Queue, body, page, or SSE exhaustion | Body/page/queue bounds, deadlines, bounded SSE batches and backoff | Resource-exhaustion tests and load report |
+| Revision substitution | Canonical plan/revision digest and resume compatibility check | Revision mismatch tests |
+| Audit suppression | Production reference app wires a structured audit sink; sink failures propagate | Audit delivery and redaction tests |
+
+## Residual risks for the RC
+
+- The Agent Server HTTP surface remains **Beta** in `2.0.0rc1`.
+- Live provider and OpenViking lifecycle evidence requires approved external
+ credentials and is not replaced by offline contracts.
+- The reference static-token authenticator is suitable for a bounded
+ self-hosted example, not a complete enterprise identity provider.
+- Container stdout audit durability depends on an operator-configured collector
+ and retention policy.
+- A local SQLite soak or single-host benchmark is not production capacity
+ evidence.
+- Arbitrary third-party non-idempotent side effects cannot be guaranteed
+ exactly once.
+
+## GA closure
+
+GA requires a candidate-SHA-bound report covering live adapters, explicit
+tenant/security negatives, image/dependency/secret scans, an eight-hour
+target-like soak, worker scaling, backup/restore, and rollout/rollback. Any
+accepted exception records an owner, mitigation, expiry, and target version.
diff --git a/deploy/kubernetes/openrath.yaml b/deploy/kubernetes/openrath.yaml
new file mode 100644
index 0000000..7272c64
--- /dev/null
+++ b/deploy/kubernetes/openrath.yaml
@@ -0,0 +1,277 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: openrath
+automountServiceAccountToken: false
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: openrath-migrate
+automountServiceAccountToken: false
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: openrath
+data:
+ OPENRATH_APP: examples.v2_server_app:app
+ OPENRATH_EMBEDDED_WORKER: "false"
+ OPENRATH_DB_SCHEMA: openrath
+ OPENRATH_TENANT_ID: default
+ OPENRATH_GRANTS: assistant.read,session.read,session.create,run.read,run.create,run.cancel,run.resume,interrupt.read,interrupt.decide,feedback.create,metrics.read
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: openrath-migrate
+spec:
+ backoffLimit: 3
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: openrath-migrate
+ spec:
+ serviceAccountName: openrath-migrate
+ restartPolicy: OnFailure
+ securityContext:
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ containers:
+ - name: migrate
+ image: ghcr.io/rath-team/openrath:2.0.0rc1
+ # Release automation must replace the review tag with image@sha256.
+ imagePullPolicy: Always
+ command: ["openrath-migrate"]
+ envFrom:
+ - configMapRef:
+ name: openrath
+ - secretRef:
+ name: openrath-migration
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ readOnlyRootFilesystem: true
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: openrath
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: openrath
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: openrath
+ spec:
+ serviceAccountName: openrath
+ terminationGracePeriodSeconds: 45
+ securityContext:
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ containers:
+ - name: openrath
+ image: ghcr.io/rath-team/openrath:2.0.0rc1
+ # Release automation must replace the review tag with image@sha256.
+ imagePullPolicy: Always
+ envFrom:
+ - configMapRef:
+ name: openrath
+ - secretRef:
+ name: openrath-runtime
+ ports:
+ - name: http
+ containerPort: 8000
+ readinessProbe:
+ httpGet:
+ path: /health/ready
+ port: http
+ periodSeconds: 5
+ timeoutSeconds: 2
+ livenessProbe:
+ httpGet:
+ path: /health/live
+ port: http
+ periodSeconds: 10
+ timeoutSeconds: 2
+ startupProbe:
+ httpGet:
+ path: /health/live
+ port: http
+ failureThreshold: 30
+ periodSeconds: 2
+ resources:
+ requests:
+ cpu: 250m
+ memory: 256Mi
+ limits:
+ cpu: "2"
+ memory: 1Gi
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ readOnlyRootFilesystem: true
+ volumeMounts:
+ - name: tmp
+ mountPath: /tmp
+ volumes:
+ - name: tmp
+ emptyDir:
+ sizeLimit: 128Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: openrath
+spec:
+ selector:
+ app.kubernetes.io/name: openrath
+ ports:
+ - name: http
+ port: 80
+ targetPort: http
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: openrath-worker
+spec:
+ replicas: 2
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: openrath-worker
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: openrath-worker
+ spec:
+ serviceAccountName: openrath
+ terminationGracePeriodSeconds: 45
+ securityContext:
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ containers:
+ - name: worker
+ image: ghcr.io/rath-team/openrath:2.0.0rc1
+ # Release automation must replace the review tag with image@sha256.
+ imagePullPolicy: Always
+ command: ["openrath-worker", "--app", "examples.v2_server_app:server"]
+ envFrom:
+ - configMapRef:
+ name: openrath
+ - secretRef:
+ name: openrath-runtime
+ resources:
+ requests:
+ cpu: 250m
+ memory: 256Mi
+ limits:
+ cpu: "2"
+ memory: 1Gi
+ readinessProbe:
+ exec:
+ command: ["openrath-migrate", "--check"]
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+ startupProbe:
+ exec:
+ command: ["openrath-migrate", "--check"]
+ periodSeconds: 5
+ timeoutSeconds: 3
+ failureThreshold: 12
+ lifecycle:
+ preStop:
+ exec:
+ command: ["/bin/sh", "-c", "sleep 5"]
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop: ["ALL"]
+ readOnlyRootFilesystem: true
+ volumeMounts:
+ - name: tmp
+ mountPath: /tmp
+ volumes:
+ - name: tmp
+ emptyDir:
+ sizeLimit: 128Mi
+---
+apiVersion: policy/v1
+kind: PodDisruptionBudget
+metadata:
+ name: openrath
+spec:
+ minAvailable: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: openrath
+---
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ name: openrath
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: openrath
+ minReplicas: 2
+ maxReplicas: 10
+ behavior:
+ scaleDown:
+ stabilizationWindowSeconds: 300
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 70
+---
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: openrath-default-deny
+spec:
+ podSelector:
+ matchExpressions:
+ - key: app.kubernetes.io/name
+ operator: In
+ values: ["openrath", "openrath-worker", "openrath-migrate"]
+ policyTypes: ["Ingress", "Egress"]
+ ingress:
+ - ports:
+ - protocol: TCP
+ port: 8000
+ egress:
+ - to:
+ - namespaceSelector:
+ matchLabels:
+ kubernetes.io/metadata.name: kube-system
+ ports:
+ - protocol: UDP
+ port: 53
+ - protocol: TCP
+ port: 53
+ - to:
+ - namespaceSelector:
+ matchLabels:
+ openrath.io/data-plane: "allowed"
+ ports:
+ - protocol: TCP
+ port: 5432
+ - protocol: TCP
+ port: 6379
+ - protocol: TCP
+ port: 9000
+ - protocol: TCP
+ port: 443
diff --git a/deploy/kubernetes/secret.example.yaml b/deploy/kubernetes/secret.example.yaml
new file mode 100644
index 0000000..25da76a
--- /dev/null
+++ b/deploy/kubernetes/secret.example.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: openrath-runtime
+type: Opaque
+stringData:
+ # Replace these placeholders using your secret manager. Do not commit values.
+ OPENRATH_POSTGRES_DSN: postgresql://USER:PASSWORD@HOST:5432/DATABASE
+ OPENRATH_TOKEN: REPLACE_ME
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..13623f6
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,38 @@
+# syntax=docker/dockerfile:1.7
+FROM python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de AS builder
+
+ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
+ PIP_NO_CACHE_DIR=1 \
+ UV_PROJECT_ENVIRONMENT=/opt/venv \
+ UV_LINK_MODE=copy \
+ UV_COMPILE_BYTECODE=1
+WORKDIR /build
+COPY pyproject.toml uv.lock README.md README_zh.md LICENSE ./
+COPY src ./src
+RUN pip install uv==0.7.18 \
+ && uv sync --frozen --no-dev --no-editable \
+ --extra server --extra postgres --extra s3 --extra redis --extra otel
+
+FROM python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de AS runtime
+
+ARG OPENRATH_VERSION=0+unknown
+ARG OPENRATH_REVISION=unknown
+LABEL org.opencontainers.image.title="OpenRath" \
+ org.opencontainers.image.source="https://github.com/Rath-Team/OpenRath" \
+ org.opencontainers.image.version="${OPENRATH_VERSION}" \
+ org.opencontainers.image.revision="${OPENRATH_REVISION}"
+
+ENV PATH="/opt/venv/bin:${PATH}" \
+ PYTHONPATH="/app" \
+ PYTHONDONTWRITEBYTECODE=1 \
+ PYTHONUNBUFFERED=1 \
+ OPENRATH_HOST=0.0.0.0 \
+ OPENRATH_PORT=8000
+RUN groupadd --system --gid 10001 openrath \
+ && useradd --system --uid 10001 --gid openrath --home /app openrath
+WORKDIR /app
+COPY --from=builder /opt/venv /opt/venv
+COPY examples ./examples
+USER 10001:10001
+EXPOSE 8000
+ENTRYPOINT ["openrath-server"]
diff --git a/examples/v2_server_app.py b/examples/v2_server_app.py
new file mode 100644
index 0000000..026854c
--- /dev/null
+++ b/examples/v2_server_app.py
@@ -0,0 +1,99 @@
+"""Minimal standalone OpenRath v2 reference application."""
+
+from __future__ import annotations
+
+import asyncio
+import os
+from uuid import UUID
+
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import LocalRuntime, PostgresEffectLedger, PostgresRunStore
+from rath.security import (
+ Principal,
+ PrincipalKind,
+ SecurityContext,
+ StructuredAuditSink,
+)
+from rath.server import AgentServer, StaticTokenAuth
+from rath.session import Session
+
+
+class EchoWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def echo(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "completed": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+class SlowWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY, timeout_seconds=60)
+ async def wait(self, state, context): # type: ignore[no-untyped-def]
+ delay = min(max(float(state.get("delay", 1)), 0), 30)
+ await asyncio.sleep(delay)
+ return {**state, "completed": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+dsn = os.environ["OPENRATH_POSTGRES_DSN"]
+token = os.environ["OPENRATH_TOKEN"]
+tenant_id = os.getenv("OPENRATH_TENANT_ID", "default")
+grants = frozenset(
+ grant.strip()
+ for grant in os.environ["OPENRATH_GRANTS"].split(",")
+ if grant.strip()
+)
+if not grants or "*" in grants:
+ raise RuntimeError(
+ "OPENRATH_GRANTS must contain explicit action grants and must not use '*'"
+ )
+store = PostgresRunStore(
+ dsn,
+ schema=os.getenv("OPENRATH_DB_SCHEMA", "openrath"),
+ auto_migrate=False,
+ pool_max_size=int(os.getenv("OPENRATH_DB_POOL_MAX_SIZE", "20")),
+)
+effect_ledger = PostgresEffectLedger(
+ dsn,
+ schema=os.getenv("OPENRATH_DB_SCHEMA", "openrath"),
+)
+runtime = LocalRuntime(store, effect_ledger=effect_ledger, production_mode=True)
+server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth(
+ {
+ token: SecurityContext(
+ principal=Principal(id="reference-user", kind=PrincipalKind.SERVICE),
+ tenant_id=tenant_id,
+ grants=grants,
+ )
+ }
+ ),
+ audit_sink=StructuredAuditSink(),
+ embedded_worker=os.getenv("OPENRATH_EMBEDDED_WORKER", "true").lower() == "true",
+ worker_id=os.getenv("HOSTNAME", "standalone-worker"),
+ worker_lease_seconds=float(os.getenv("OPENRATH_WORKER_LEASE_SECONDS", "30")),
+)
+server.register_assistant(
+ "echo",
+ EchoWorkflow(),
+ revision_id=UUID(
+ os.getenv("OPENRATH_REVISION_ID", "00000000-0000-4000-8000-000000000001")
+ ),
+)
+server.register_assistant(
+ "slow",
+ SlowWorkflow(),
+ revision_id=UUID(
+ os.getenv(
+ "OPENRATH_SLOW_REVISION_ID",
+ "00000000-0000-4000-8000-000000000002",
+ )
+ ),
+)
+app = server.app
diff --git a/pyproject.toml b/pyproject.toml
index 1ac6aee..0f845af 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "openrath"
-version = "1.3.0"
+version = "2.0.0rc1"
description = "An open-source, torch-like API framework for dynamic multi-agent workflow."
readme = "README.md"
requires-python = ">=3.10,<3.14"
@@ -21,7 +21,7 @@ dependencies = [
"openai>=1.0.0",
"anthropic>=0.40.0",
"pydantic>=2.0.0,<3",
- "mcp>=1.0.0",
+ "mcp>=1.28.1,<2",
]
[project.urls]
@@ -29,17 +29,44 @@ Homepage = "https://github.com/Rath-Team/OpenRath"
Repository = "https://github.com/Rath-Team/OpenRath"
"Bug Tracker" = "https://github.com/Rath-Team/OpenRath/issues"
+[project.scripts]
+openrath-server = "rath.server.cli:server_main"
+openrath-migrate = "rath.server.cli:migrate_main"
+openrath-worker = "rath.server.cli:worker_main"
+
[project.optional-dependencies]
litellm = [
"litellm>=1.80,<1.88",
]
opensandbox = [
- "opensandbox>=0.1.13",
+ "opensandbox>=0.1.15",
"opensandbox-code-interpreter>=0.1.2",
- "opensandbox-server>=0.2.1",
+ "opensandbox-server>=0.2.2",
]
openviking = [
- "openviking>=0.4.7",
+ "openviking>=0.4.11",
+ "aiohttp>=3.14.1",
+ "json-repair>=0.60.1",
+ "pillow>=12.3.0",
+ "soupsieve>=2.8.4",
+]
+server = [
+ "starlette>=1.3.1,<2",
+ "uvicorn>=0.35,<1",
+ "httpx>=0.28,<1",
+]
+postgres = [
+ "psycopg[binary,pool]>=3.2,<4",
+]
+redis = [
+ "redis>=6,<7",
+]
+otel = [
+ "opentelemetry-api>=1.36,<2",
+ "opentelemetry-sdk>=1.36,<2",
+]
+s3 = [
+ "boto3>=1.40,<2",
]
[tool.ruff]
@@ -71,6 +98,7 @@ include = [
[dependency-groups]
dev = [
"mypy>=1.20.2",
+ "opentelemetry-sdk>=1.36,<2",
"pytest>=9.0.3",
"pytest-benchmark>=4.0.0",
"pytest-rerunfailures>=15.0",
diff --git a/release/checklists/v2.0.0-ga.md b/release/checklists/v2.0.0-ga.md
new file mode 100644
index 0000000..df63c81
--- /dev/null
+++ b/release/checklists/v2.0.0-ga.md
@@ -0,0 +1,49 @@
+# OpenRath v2.0.0 GA checklist
+
+Candidate: `v2.0.0`
+
+No item in this checklist is satisfied by the `v2.0.0rc1` publication alone.
+Every machine-readable report must identify the exact final source commit.
+
+## Gate C evidence
+
+- [ ] Required CI report has zero open P0 findings.
+- [ ] Live Provider, OpenSandbox, and OpenViking lifecycles pass without skips.
+- [ ] Single-host and split-profile capacity reports pass.
+- [ ] One-to-four worker scaling efficiency is at least 70%.
+- [ ] Target-like soak runs for at least 28,800 seconds with zero errors and no
+ unexplained resource growth.
+- [ ] PostgreSQL, Redis, S3, API, and worker fault matrix passes.
+- [ ] Target-cluster backup/restore and rollout/rollback drills pass.
+- [ ] API stability, v1 maintenance window, and migration review pass.
+- [ ] The protected `Collect v2.0.0 Gate C evidence` workflow succeeds on the
+ final `main` source commit using the approved `openrath-ga` target runner.
+- [ ] Every report evidence file is contained in that workflow artifact and
+ matches its recorded size and SHA-256.
+
+## Release governance
+
+- [ ] PR review is complete with no unresolved P0/P1 thread.
+- [ ] `main` protection and required checks are active.
+- [ ] The `ga-release` environment has required reviewers.
+- [ ] A PyPI token scoped only to `openrath` is held outside GitHub and the
+ repository for the interactive manual upload.
+- [ ] The annotated `v2.0.0` tag points to a commit reachable from `main`.
+- [ ] The owner explicitly approves merge, version bump, tag, PyPI, GHCR, and
+ GitHub Release actions.
+
+## Publication and external verification
+
+- [ ] Wheel, sdist, OpenAPI, OCI labels, tag, and evidence report `2.0.0`.
+- [ ] Production and all-extras dependency audits pass.
+- [ ] Image and repository secret scans pass.
+- [ ] Final SBOM, immutable image digest, and evidence manifest are attached.
+- [ ] OCI provenance attestation verifies by digest.
+- [ ] The protected preparation artifact is uploaded to PyPI without rebuilding.
+- [ ] PyPI wheel and sdist SHA-256 values match the preparation artifact.
+- [ ] The protected finalization workflow promotes the attested OCI digest and
+ creates the final GitHub Release.
+- [ ] Fresh Python installation from PyPI reports `2.0.0`.
+- [ ] Anonymous GHCR pull by digest succeeds.
+- [ ] GitHub Release is final, not a prerelease.
+- [ ] Post-release smoke and 24h/72h observation owners are active.
diff --git a/release/checklists/v2.0.0-rc.md b/release/checklists/v2.0.0-rc.md
new file mode 100644
index 0000000..3dffa3b
--- /dev/null
+++ b/release/checklists/v2.0.0-rc.md
@@ -0,0 +1,39 @@
+# OpenRath v2.0.0 RC checklist
+
+Candidate: `v2.0.0rc1`
+
+## RC artifact publication
+
+- [x] Package, OpenAPI, image label, tag, and release title report `2.0.0rc1`.
+- [x] Lock, Ruff, mypy, offline tests, integration tests, OpenSandbox, build,
+ dependency audits, image scan, secret scan, and manifest validation pass.
+- [x] Wheel, sdist, SBOM, scan reports, manifest, and immutable image digest are
+ attached to the GitHub prerelease.
+- [x] Release notes state that live provider/OpenViking and target-environment
+ Gate C remain pending.
+- [x] No PyPI publication or shared deployment occurs as part of RC1.
+
+Publication evidence:
+
+- Source commit:
+ `feedcaadb79a349aa60c034618610231d83fb131`.
+- Release workflow:
+ .
+- GitHub prerelease:
+ .
+- OCI artifact:
+ `ghcr.io/rath-team/openrath@sha256:d66a1c7933e410d290528ba5091f73a9f4e94566e1bd9d917f7fd7937c6b9be2`.
+- Anonymous manifest retrieval and GitHub attestation verification passed on
+ 2026-07-30.
+
+## GA-blocking acceptance after RC publication
+
+- [ ] Approved live provider lifecycle.
+- [ ] Approved live OpenViking lifecycle.
+- [ ] Target-like single-host and split-profile capacity report.
+- [ ] One-to-four worker scaling efficiency at least 70%.
+- [ ] Eight-hour target-like soak.
+- [ ] PostgreSQL/Redis/S3/API/worker fault matrix.
+- [ ] Target-cluster backup/restore and rollout/rollback.
+- [ ] Final API stability and v1 maintenance-window owner decision.
+- [ ] Final `2.0.0` evidence regenerated from the GA SHA.
diff --git a/release/evidence/schema/ga-approval.schema.json b/release/evidence/schema/ga-approval.schema.json
new file mode 100644
index 0000000..a160b7f
--- /dev/null
+++ b/release/evidence/schema/ga-approval.schema.json
@@ -0,0 +1,101 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openrath.dev/schemas/ga-approval-v1.json",
+ "title": "OpenRath GA approval",
+ "type": "object",
+ "required": [
+ "schema",
+ "version",
+ "source_commit",
+ "approved",
+ "approved_at",
+ "approvers",
+ "requested_by",
+ "environment",
+ "environment_reviews",
+ "repository",
+ "workflow_run_id",
+ "actions"
+ ],
+ "properties": {
+ "schema": {
+ "const": "openrath.ga-approval/1"
+ },
+ "version": {
+ "const": "2.0.0"
+ },
+ "source_commit": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{40}$"
+ },
+ "approved": {
+ "const": true
+ },
+ "approved_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "approvers": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "requested_by": {
+ "type": "string",
+ "minLength": 1
+ },
+ "environment": {
+ "const": "ga-release"
+ },
+ "environment_reviews": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "required": ["review_id", "reviewer", "approved_at"],
+ "properties": {
+ "review_id": {
+ "type": "string",
+ "pattern": "^[1-9][0-9]*$"
+ },
+ "reviewer": {
+ "type": "string",
+ "minLength": 1
+ },
+ "approved_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "repository": {
+ "type": "string",
+ "pattern": "^[^/\\s]+/[^/\\s]+$"
+ },
+ "workflow_run_id": {
+ "type": "string",
+ "pattern": "^[1-9][0-9]*$"
+ },
+ "actions": {
+ "type": "object",
+ "required": [
+ "pypi",
+ "ghcr",
+ "github_release"
+ ],
+ "properties": {
+ "pypi": {"const": true},
+ "ghcr": {"const": true},
+ "github_release": {"const": true}
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/release/evidence/schema/ga-gate-report.schema.json b/release/evidence/schema/ga-gate-report.schema.json
new file mode 100644
index 0000000..b4e1b41
--- /dev/null
+++ b/release/evidence/schema/ga-gate-report.schema.json
@@ -0,0 +1,95 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openrath.dev/schemas/ga-gate-report-v1.json",
+ "title": "OpenRath GA gate report",
+ "type": "object",
+ "required": [
+ "schema",
+ "gate",
+ "source_commit",
+ "result",
+ "generated_at",
+ "environment",
+ "evidence",
+ "open_risks",
+ "details"
+ ],
+ "properties": {
+ "schema": {
+ "const": "openrath.ga-gate-report/1"
+ },
+ "gate": {
+ "enum": [
+ "tests",
+ "live_adapters",
+ "performance",
+ "soak",
+ "drills",
+ "compatibility"
+ ]
+ },
+ "source_commit": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{40}$"
+ },
+ "result": {
+ "const": "passed"
+ },
+ "generated_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "environment": {
+ "type": "object",
+ "required": [
+ "profile",
+ "target_like"
+ ],
+ "properties": {
+ "profile": {
+ "type": "string",
+ "minLength": 1
+ },
+ "target_like": {
+ "const": true
+ }
+ },
+ "additionalProperties": true
+ },
+ "evidence": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "required": [
+ "path",
+ "sha256",
+ "size"
+ ],
+ "properties": {
+ "path": {
+ "type": "string",
+ "minLength": 1,
+ "pattern": "^[^\\\\:]+$"
+ },
+ "sha256": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{64}$"
+ },
+ "size": {
+ "type": "integer",
+ "minimum": 0
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "open_risks": {
+ "type": "array"
+ },
+ "details": {
+ "type": "object"
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/release/evidence/schema/manifest.schema.json b/release/evidence/schema/manifest.schema.json
new file mode 100644
index 0000000..45fdb86
--- /dev/null
+++ b/release/evidence/schema/manifest.schema.json
@@ -0,0 +1,164 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://openrath.dev/schemas/release-evidence-manifest-v2.json",
+ "title": "OpenRath release evidence manifest v2",
+ "type": "object",
+ "required": [
+ "schema",
+ "release_stage",
+ "version",
+ "tag",
+ "source_commit",
+ "source_tree_clean",
+ "ga_approved",
+ "artifacts",
+ "blocking_gates"
+ ],
+ "properties": {
+ "schema": {
+ "const": "openrath.release-evidence/2"
+ },
+ "release_stage": {
+ "enum": ["rc", "ga"]
+ },
+ "version": {
+ "type": "string"
+ },
+ "tag": {
+ "type": "string"
+ },
+ "source_commit": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{40}$"
+ },
+ "source_tree_clean": {
+ "const": true
+ },
+ "ga_approved": {
+ "type": "boolean"
+ },
+ "artifacts": {
+ "type": "object"
+ },
+ "blocking_gates": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "approval": {
+ "type": "object",
+ "required": [
+ "approvers",
+ "requested_by",
+ "approved_at",
+ "environment",
+ "workflow_run_id",
+ "source_commit",
+ "actions"
+ ],
+ "properties": {
+ "approvers": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "requested_by": {
+ "type": "string",
+ "minLength": 1
+ },
+ "approved_at": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "environment": {
+ "const": "ga-release"
+ },
+ "workflow_run_id": {
+ "type": "string",
+ "pattern": "^[1-9][0-9]*$"
+ },
+ "source_commit": {
+ "type": "string",
+ "pattern": "^[0-9a-f]{40}$"
+ },
+ "actions": {
+ "type": "object",
+ "required": [
+ "pypi",
+ "ghcr",
+ "github_release"
+ ],
+ "properties": {
+ "pypi": {"const": true},
+ "ghcr": {"const": true},
+ "github_release": {"const": true}
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "oneOf": [
+ {
+ "title": "Release candidate",
+ "properties": {
+ "release_stage": {"const": "rc"},
+ "version": {
+ "type": "string",
+ "pattern": "^2\\.0\\.0rc[1-9][0-9]*$"
+ },
+ "tag": {
+ "type": "string",
+ "pattern": "^v2\\.0\\.0rc[1-9][0-9]*$"
+ },
+ "ga_approved": {"const": false},
+ "blocking_gates": {
+ "type": "array",
+ "minItems": 1
+ }
+ },
+ "not": {
+ "required": ["approval"]
+ }
+ },
+ {
+ "title": "General availability",
+ "required": ["approval"],
+ "properties": {
+ "release_stage": {"const": "ga"},
+ "version": {"const": "2.0.0"},
+ "tag": {"const": "v2.0.0"},
+ "ga_approved": {"const": true},
+ "blocking_gates": {
+ "type": "array",
+ "maxItems": 0
+ },
+ "artifacts": {
+ "type": "object",
+ "required": [
+ "approval",
+ "tests",
+ "live_adapters",
+ "performance",
+ "soak",
+ "drills",
+ "compatibility",
+ "sbom",
+ "image_scan",
+ "secret_scan",
+ "dependency_audit_production",
+ "dependency_audit_all",
+ "kubernetes"
+ ]
+ }
+ }
+ }
+ ],
+ "additionalProperties": true
+}
diff --git a/release/evidence/v2.0.0-review/README.md b/release/evidence/v2.0.0-review/README.md
new file mode 100644
index 0000000..36ca875
--- /dev/null
+++ b/release/evidence/v2.0.0-review/README.md
@@ -0,0 +1,59 @@
+# OpenRath v2.0.0 review-remediation evidence
+
+This bundle records the validation performed for implementation commit
+`51a26c4a23850876548c61340da2d2da3bc834ce`. It is review evidence, not a
+v2.0.0 release bundle.
+
+## Decision
+
+- `release_approved`: **false**
+- `package_version`: `1.3.0`
+- `intended_release`: `2.0.0` (unreleased)
+- Local implementation gates: passed
+- Production/RC Gate D: not satisfied
+
+The package version was deliberately not changed to `2.0.0`. A local image ID
+is not a published registry digest, and the unavailable external and
+operational gates cannot be replaced by unit tests or a short local soak.
+
+## Completed validation
+
+| Area | Result |
+|---|---|
+| Lock | `uv lock --check` passed |
+| Lint/format | Ruff check and format check passed |
+| Types | mypy passed for 166 source files |
+| Offline test matrix | 1043 passed, 20 skipped |
+| OpenAPI contract | 2 passed; generated document matches the committed golden file |
+| OpenSandbox real service | 45 passed, 3 skipped in the full run; the single environment-sensitive timing assertion was corrected and its focused rerun passed |
+| PostgreSQL/Redis/S3 integration | 10 passed against real local services |
+| Build | wheel and sdist built; `twine check` passed |
+| Dependency audit | exact production set and all extras/groups: no known vulnerabilities |
+| Container build | current source built as local image `openrath:review` |
+| Image scan | 0 fixed HIGH/CRITICAL findings with Trivy 0.67.2 |
+| Repository secret scan | 0 findings with Trivy 0.67.2 |
+| Reference manifests | Compose validation and strict kubeconform validation passed |
+| Review soak | 143 runs in 10.03 seconds, 0 failures; review profile only |
+
+## Outstanding release gates
+
+The following require external credentials, services, a registry, target
+cluster, or elapsed operational time and remain blocking:
+
+1. Live LLM/provider lifecycle using the approved production provider.
+2. Live OpenViking lifecycle against the approved service.
+3. Published OpenRath OCI artifact addressed by an immutable registry digest.
+4. Eight-hour soak on target-like hardware.
+5. Worker scale test from one to four replicas.
+6. Backup/restore, rollout/rollback, database restart, S3 restart, and Redis
+ loss drills on the target cluster.
+7. Final CI run and release evidence regeneration on the frozen RC commit.
+
+Do not tag, publish, or deploy v2.0.0 from this evidence bundle.
+
+## Included artifacts
+
+- `manifest.json`: machine-readable result and blocker summary.
+- `openrath-v2-review.sbom.cdx.json`: CycloneDX SBOM for the local image.
+- `image-scan-high-critical.json`: Trivy HIGH/CRITICAL image scan.
+- `repository-secret-scan.json`: Trivy repository secret scan.
diff --git a/release/evidence/v2.0.0-review/image-scan-high-critical.json b/release/evidence/v2.0.0-review/image-scan-high-critical.json
new file mode 100644
index 0000000..d95e42c
--- /dev/null
+++ b/release/evidence/v2.0.0-review/image-scan-high-critical.json
@@ -0,0 +1,8309 @@
+{
+ "SchemaVersion": 2,
+ "CreatedAt": "2026-07-28T04:18:30.145618288Z",
+ "ArtifactName": "openrath:review",
+ "ArtifactType": "container_image",
+ "Metadata": {
+ "Size": 239066624,
+ "OS": {
+ "Family": "debian",
+ "Name": "13.6"
+ },
+ "ImageID": "sha256:181247207c0f57e438c42676579a32d98cd7f9ea66c2c6b1bf2c233526723b14",
+ "DiffIDs": [
+ "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f",
+ "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167",
+ "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd",
+ "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f",
+ "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8",
+ "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1",
+ "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f",
+ "sha256:f2776a24e2368b14a6e05e79b2abd1f2b85fb5217de0b9b924fb2a926538d169"
+ ],
+ "RepoTags": [
+ "openrath:review"
+ ],
+ "ImageConfig": {
+ "architecture": "amd64",
+ "created": "2026-07-28T04:16:47.739619966Z",
+ "history": [
+ {
+ "created": "2026-07-13T00:00:00Z",
+ "created_by": "# debian.sh --arch 'amd64' out/ 'trixie' '@1783900800'",
+ "comment": "debuerreotype 0.17"
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV LANG=C.UTF-8",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "RUN /bin/sh -c set -eux; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tca-certificates \t\tnetbase \t\ttzdata \t; \tapt-get dist-clean # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV GPG_KEY=7169605F62C751356D054A26A821E680E5FA6305",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PYTHON_VERSION=3.12.13",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PYTHON_SHA256=c08bc65a81971c1dd5783182826503369466c7e67374d1646519adf05207b684",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "RUN /bin/sh -c set -eux; \t\tsavedAptMark=\"$(apt-mark showmanual)\"; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tdpkg-dev \t\tgcc \t\tgnupg \t\tlibbluetooth-dev \t\tlibbz2-dev \t\tlibc6-dev \t\tlibdb-dev \t\tlibffi-dev \t\tlibgdbm-dev \t\tliblzma-dev \t\tlibncursesw5-dev \t\tlibreadline-dev \t\tlibsqlite3-dev \t\tlibssl-dev \t\tmake \t\ttk-dev \t\tuuid-dev \t\twget \t\txz-utils \t\tzlib1g-dev \t; \t\twget -O python.tar.xz \"https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz\"; \techo \"$PYTHON_SHA256 *python.tar.xz\" | sha256sum -c -; \twget -O python.tar.xz.asc \"https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc\"; \tGNUPGHOME=\"$(mktemp -d)\"; export GNUPGHOME; \tgpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$GPG_KEY\"; \tgpg --batch --verify python.tar.xz.asc python.tar.xz; \tgpgconf --kill all; \trm -rf \"$GNUPGHOME\" python.tar.xz.asc; \tmkdir -p /usr/src/python; \ttar --extract --directory /usr/src/python --strip-components=1 --file python.tar.xz; \trm python.tar.xz; \t\tcd /usr/src/python; \tgnuArch=\"$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)\"; \t./configure \t\t--build=\"$gnuArch\" \t\t--enable-loadable-sqlite-extensions \t\t--enable-optimizations \t\t--enable-option-checking=fatal \t\t--enable-shared \t\t$(test \"${gnuArch%%-*}\" != 'riscv64' \u0026\u0026 echo '--with-lto') \t\t--with-ensurepip \t; \tnproc=\"$(nproc)\"; \tEXTRA_CFLAGS=\"$(dpkg-buildflags --get CFLAGS)\"; \tLDFLAGS=\"$(dpkg-buildflags --get LDFLAGS)\"; \tLDFLAGS=\"${LDFLAGS:-} -Wl,--strip-all\"; \tarch=\"$(dpkg --print-architecture)\"; arch=\"${arch##*-}\"; \tcase \"$arch\" in \t\tamd64|arm64) \t\t\tEXTRA_CFLAGS=\"${EXTRA_CFLAGS:-} -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer\"; \t\t\t;; \t\ti386) \t\t\t;; \t\t*) \t\t\tEXTRA_CFLAGS=\"${EXTRA_CFLAGS:-} -fno-omit-frame-pointer\"; \t\t\t;; \tesac; \tmake -j \"$nproc\" \t\t\"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}\" \t\t\"LDFLAGS=${LDFLAGS:-}\" \t; \trm python; \tmake -j \"$nproc\" \t\t\"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}\" \t\t\"LDFLAGS=${LDFLAGS:-} -Wl,-rpath='\\$\\$ORIGIN/../lib'\" \t\tpython \t; \tmake install; \t\tcd /; \trm -rf /usr/src/python; \t\tfind /usr/local -depth \t\t\\( \t\t\t\\( -type d -a \\( -name test -o -name tests -o -name idle_test \\) \\) \t\t\t-o \\( -type f -a \\( -name '*.pyc' -o -name '*.pyo' -o -name 'libpython*.a' \\) \\) \t\t\\) -exec rm -rf '{}' + \t; \t\tldconfig; \t\tapt-mark auto '.*' \u003e /dev/null; \tapt-mark manual $savedAptMark; \tfind /usr/local -type f -executable -not \\( -name '*tkinter*' \\) -exec ldd '{}' ';' \t\t| awk '/=\u003e/ { so = $(NF-1); if (index(so, \"/usr/local/\") == 1) { next }; gsub(\"^/(usr/)?\", \"\", so); printf \"*%s\\n\", so }' \t\t| sort -u \t\t| xargs -rt dpkg-query --search \t\t| awk 'sub(\":$\", \"\", $1) { print $1 }' \t\t| sort -u \t\t| xargs -r apt-mark manual \t; \tapt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \tapt-get dist-clean; \t\texport PYTHONDONTWRITEBYTECODE=1; \tpython3 --version; \tpip3 --version # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "RUN /bin/sh -c set -eux; \tfor src in idle3 pip3 pydoc3 python3 python3-config; do \t\tdst=\"$(echo \"$src\" | tr -d 3)\"; \t\t[ -s \"/usr/local/bin/$src\" ]; \t\t[ ! -e \"/usr/local/bin/$dst\" ]; \t\tln -svT \"$src\" \"/usr/local/bin/$dst\"; \tdone # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "CMD [\"python3\"]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "ENV PATH=/opt/venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PYTHONPATH=/app PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 OPENRATH_HOST=0.0.0.0 OPENRATH_PORT=8000",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "RUN /bin/sh -c groupadd --system --gid 10001 openrath \u0026\u0026 useradd --system --uid 10001 --gid openrath --home /app openrath # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "WORKDIR /app",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-28T04:16:47Z",
+ "created_by": "COPY /opt/venv /opt/venv # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-28T04:16:47Z",
+ "created_by": "COPY examples ./examples # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-28T04:16:47Z",
+ "created_by": "USER 10001:10001",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-28T04:16:47Z",
+ "created_by": "EXPOSE map[8000/tcp:{}]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-28T04:16:47Z",
+ "created_by": "ENTRYPOINT [\"openrath-server\"]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ }
+ ],
+ "os": "linux",
+ "rootfs": {
+ "type": "layers",
+ "diff_ids": [
+ "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f",
+ "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167",
+ "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd",
+ "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f",
+ "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8",
+ "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1",
+ "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f",
+ "sha256:f2776a24e2368b14a6e05e79b2abd1f2b85fb5217de0b9b924fb2a926538d169"
+ ]
+ },
+ "config": {
+ "Entrypoint": [
+ "openrath-server"
+ ],
+ "Env": [
+ "PATH=/opt/venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "LANG=C.UTF-8",
+ "GPG_KEY=7169605F62C751356D054A26A821E680E5FA6305",
+ "PYTHON_VERSION=3.12.13",
+ "PYTHON_SHA256=c08bc65a81971c1dd5783182826503369466c7e67374d1646519adf05207b684",
+ "PYTHONPATH=/app",
+ "PYTHONDONTWRITEBYTECODE=1",
+ "PYTHONUNBUFFERED=1",
+ "OPENRATH_HOST=0.0.0.0",
+ "OPENRATH_PORT=8000"
+ ],
+ "User": "10001:10001",
+ "WorkingDir": "/app",
+ "ExposedPorts": {
+ "8000/tcp": {}
+ }
+ }
+ },
+ "Layers": [
+ {
+ "Size": 81049600,
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "Size": 4127232,
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "Size": 38094848,
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "Size": 5120,
+ "DiffID": "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f"
+ },
+ {
+ "Size": 11264,
+ "DiffID": "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8"
+ },
+ {
+ "Size": 1536,
+ "DiffID": "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1"
+ },
+ {
+ "Size": 115771392,
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "Size": 5632,
+ "DiffID": "sha256:f2776a24e2368b14a6e05e79b2abd1f2b85fb5217de0b9b924fb2a926538d169"
+ }
+ ]
+ },
+ "Results": [
+ {
+ "Target": "openrath:review (debian 13.6)",
+ "Class": "os-pkgs",
+ "Type": "debian",
+ "Packages": [
+ {
+ "ID": "adduser@3.152",
+ "Name": "adduser",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/adduser@3.152?arch=all\u0026distro=debian-13.6",
+ "UID": "a26e3466c18314ad"
+ },
+ "Version": "3.152",
+ "Arch": "all",
+ "SrcName": "adduser",
+ "SrcVersion": "3.152",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian Adduser Developers \u003cadduser@packages.debian.org\u003e",
+ "DependsOn": [
+ "passwd@1:4.17.4-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/adduser",
+ "/usr/sbin/deluser",
+ "/usr/share/doc/adduser/NEWS.Debian.gz",
+ "/usr/share/doc/adduser/README.gz",
+ "/usr/share/doc/adduser/TODO",
+ "/usr/share/doc/adduser/changelog.gz",
+ "/usr/share/doc/adduser/copyright",
+ "/usr/share/doc/adduser/examples/INSTALL",
+ "/usr/share/doc/adduser/examples/README",
+ "/usr/share/doc/adduser/examples/adduser.conf",
+ "/usr/share/doc/adduser/examples/adduser.local",
+ "/usr/share/doc/adduser/examples/adduser.local.conf",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/bash.bashrc",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/profile",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel.other/index.html",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bash_logout",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bash_profile",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bashrc",
+ "/usr/share/doc/adduser/examples/deluser.conf",
+ "/usr/share/man/da/man5/deluser.conf.5.gz",
+ "/usr/share/man/de/man5/adduser.conf.5.gz",
+ "/usr/share/man/de/man5/deluser.conf.5.gz",
+ "/usr/share/man/de/man8/adduser.8.gz",
+ "/usr/share/man/de/man8/adduser.local.8.gz",
+ "/usr/share/man/de/man8/deluser.8.gz",
+ "/usr/share/man/es/man5/deluser.conf.5.gz",
+ "/usr/share/man/fr/man5/adduser.conf.5.gz",
+ "/usr/share/man/fr/man5/deluser.conf.5.gz",
+ "/usr/share/man/fr/man8/adduser.8.gz",
+ "/usr/share/man/fr/man8/deluser.8.gz",
+ "/usr/share/man/it/man5/deluser.conf.5.gz",
+ "/usr/share/man/man5/adduser.conf.5.gz",
+ "/usr/share/man/man5/deluser.conf.5.gz",
+ "/usr/share/man/man8/adduser.8.gz",
+ "/usr/share/man/man8/adduser.local.8.gz",
+ "/usr/share/man/man8/deluser.8.gz",
+ "/usr/share/man/nl/man5/adduser.conf.5.gz",
+ "/usr/share/man/nl/man5/deluser.conf.5.gz",
+ "/usr/share/man/nl/man8/adduser.8.gz",
+ "/usr/share/man/nl/man8/adduser.local.8.gz",
+ "/usr/share/man/nl/man8/deluser.8.gz",
+ "/usr/share/man/pl/man5/deluser.conf.5.gz",
+ "/usr/share/man/pt/man5/adduser.conf.5.gz",
+ "/usr/share/man/pt/man5/deluser.conf.5.gz",
+ "/usr/share/man/pt/man8/adduser.8.gz",
+ "/usr/share/man/pt/man8/adduser.local.8.gz",
+ "/usr/share/man/pt/man8/deluser.8.gz",
+ "/usr/share/man/ro/man5/adduser.conf.5.gz",
+ "/usr/share/man/ro/man5/deluser.conf.5.gz",
+ "/usr/share/man/ro/man8/adduser.8.gz",
+ "/usr/share/man/ro/man8/adduser.local.8.gz",
+ "/usr/share/man/ro/man8/deluser.8.gz",
+ "/usr/share/man/ru/man5/deluser.conf.5.gz",
+ "/usr/share/man/sv/man5/deluser.conf.5.gz",
+ "/usr/share/perl5/Debian/AdduserCommon.pm",
+ "/usr/share/perl5/Debian/AdduserLogging.pm",
+ "/usr/share/perl5/Debian/AdduserRetvalues.pm"
+ ]
+ },
+ {
+ "ID": "apt@3.0.3",
+ "Name": "apt",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/apt@3.0.3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3c1822d549195c1f"
+ },
+ "Version": "3.0.3",
+ "Arch": "amd64",
+ "SrcName": "apt",
+ "SrcVersion": "3.0.3",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "curl",
+ "BSD-3-Clause",
+ "MIT",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "APT Development Team \u003cdeity@lists.debian.org\u003e",
+ "DependsOn": [
+ "adduser@3.152",
+ "base-passwd@3.6.7",
+ "debian-archive-keyring@2025.1",
+ "libapt-pkg7.0@3.0.3",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "libseccomp2@2.6.0-2",
+ "libssl3t64@3.5.6-1~deb13u2",
+ "libstdc++6@14.2.0-19",
+ "libsystemd0@257.13-1~deb13u1",
+ "sqv@1.3.0-3+b2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/apt",
+ "/usr/bin/apt-cache",
+ "/usr/bin/apt-cdrom",
+ "/usr/bin/apt-config",
+ "/usr/bin/apt-get",
+ "/usr/bin/apt-mark",
+ "/usr/lib/apt/apt-extracttemplates",
+ "/usr/lib/apt/apt-helper",
+ "/usr/lib/apt/apt.systemd.daily",
+ "/usr/lib/apt/methods/cdrom",
+ "/usr/lib/apt/methods/copy",
+ "/usr/lib/apt/methods/file",
+ "/usr/lib/apt/methods/gpgv",
+ "/usr/lib/apt/methods/http",
+ "/usr/lib/apt/methods/mirror",
+ "/usr/lib/apt/methods/rred",
+ "/usr/lib/apt/methods/sqv",
+ "/usr/lib/apt/methods/store",
+ "/usr/lib/apt/solvers/dump",
+ "/usr/lib/dpkg/methods/apt/desc.apt",
+ "/usr/lib/dpkg/methods/apt/install",
+ "/usr/lib/dpkg/methods/apt/names",
+ "/usr/lib/dpkg/methods/apt/setup",
+ "/usr/lib/dpkg/methods/apt/update",
+ "/usr/lib/systemd/system/apt-daily-upgrade.service",
+ "/usr/lib/systemd/system/apt-daily-upgrade.timer",
+ "/usr/lib/systemd/system/apt-daily.service",
+ "/usr/lib/systemd/system/apt-daily.timer",
+ "/usr/lib/x86_64-linux-gnu/libapt-private.so.0.0.0",
+ "/usr/share/apt/default-sequoia.config",
+ "/usr/share/bash-completion/completions/apt",
+ "/usr/share/bug/apt/script",
+ "/usr/share/doc/apt/NEWS.Debian.gz",
+ "/usr/share/doc/apt/README.md.gz",
+ "/usr/share/doc/apt/changelog.gz",
+ "/usr/share/doc/apt/copyright",
+ "/usr/share/doc/apt/examples/apt.conf",
+ "/usr/share/doc/apt/examples/configure-index",
+ "/usr/share/doc/apt/examples/debian.sources",
+ "/usr/share/doc/apt/examples/preferences",
+ "/usr/share/lintian/overrides/apt",
+ "/usr/share/locale/ar/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/da/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/de/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/el/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/es/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/it/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/km/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/th/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/apt.mo",
+ "/usr/share/man/de/man1/apt-transport-http.1.gz",
+ "/usr/share/man/de/man1/apt-transport-https.1.gz",
+ "/usr/share/man/de/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/de/man5/apt.conf.5.gz",
+ "/usr/share/man/de/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/de/man5/apt_preferences.5.gz",
+ "/usr/share/man/de/man5/sources.list.5.gz",
+ "/usr/share/man/de/man7/apt-patterns.7.gz",
+ "/usr/share/man/de/man8/apt-cache.8.gz",
+ "/usr/share/man/de/man8/apt-cdrom.8.gz",
+ "/usr/share/man/de/man8/apt-config.8.gz",
+ "/usr/share/man/de/man8/apt-get.8.gz",
+ "/usr/share/man/de/man8/apt-mark.8.gz",
+ "/usr/share/man/de/man8/apt-secure.8.gz",
+ "/usr/share/man/de/man8/apt.8.gz",
+ "/usr/share/man/es/man5/apt_preferences.5.gz",
+ "/usr/share/man/es/man8/apt-cache.8.gz",
+ "/usr/share/man/es/man8/apt-cdrom.8.gz",
+ "/usr/share/man/es/man8/apt-config.8.gz",
+ "/usr/share/man/fr/man1/apt-transport-http.1.gz",
+ "/usr/share/man/fr/man1/apt-transport-https.1.gz",
+ "/usr/share/man/fr/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/fr/man5/apt.conf.5.gz",
+ "/usr/share/man/fr/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/fr/man5/apt_preferences.5.gz",
+ "/usr/share/man/fr/man5/sources.list.5.gz",
+ "/usr/share/man/fr/man7/apt-patterns.7.gz",
+ "/usr/share/man/fr/man8/apt-cache.8.gz",
+ "/usr/share/man/fr/man8/apt-cdrom.8.gz",
+ "/usr/share/man/fr/man8/apt-config.8.gz",
+ "/usr/share/man/fr/man8/apt-get.8.gz",
+ "/usr/share/man/fr/man8/apt-mark.8.gz",
+ "/usr/share/man/fr/man8/apt-secure.8.gz",
+ "/usr/share/man/fr/man8/apt.8.gz",
+ "/usr/share/man/it/man5/apt.conf.5.gz",
+ "/usr/share/man/it/man5/apt_preferences.5.gz",
+ "/usr/share/man/it/man8/apt-cache.8.gz",
+ "/usr/share/man/it/man8/apt-cdrom.8.gz",
+ "/usr/share/man/it/man8/apt-config.8.gz",
+ "/usr/share/man/it/man8/apt-mark.8.gz",
+ "/usr/share/man/it/man8/apt.8.gz",
+ "/usr/share/man/ja/man5/apt.conf.5.gz",
+ "/usr/share/man/ja/man5/apt_preferences.5.gz",
+ "/usr/share/man/ja/man8/apt-cache.8.gz",
+ "/usr/share/man/ja/man8/apt-cdrom.8.gz",
+ "/usr/share/man/ja/man8/apt-config.8.gz",
+ "/usr/share/man/ja/man8/apt-mark.8.gz",
+ "/usr/share/man/ja/man8/apt.8.gz",
+ "/usr/share/man/man1/apt-transport-http.1.gz",
+ "/usr/share/man/man1/apt-transport-https.1.gz",
+ "/usr/share/man/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/man5/apt.conf.5.gz",
+ "/usr/share/man/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/man5/apt_preferences.5.gz",
+ "/usr/share/man/man5/sources.list.5.gz",
+ "/usr/share/man/man7/apt-patterns.7.gz",
+ "/usr/share/man/man8/apt-cache.8.gz",
+ "/usr/share/man/man8/apt-cdrom.8.gz",
+ "/usr/share/man/man8/apt-config.8.gz",
+ "/usr/share/man/man8/apt-get.8.gz",
+ "/usr/share/man/man8/apt-mark.8.gz",
+ "/usr/share/man/man8/apt-secure.8.gz",
+ "/usr/share/man/man8/apt.8.gz",
+ "/usr/share/man/nl/man1/apt-transport-http.1.gz",
+ "/usr/share/man/nl/man1/apt-transport-https.1.gz",
+ "/usr/share/man/nl/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/nl/man5/apt.conf.5.gz",
+ "/usr/share/man/nl/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/nl/man5/apt_preferences.5.gz",
+ "/usr/share/man/nl/man5/sources.list.5.gz",
+ "/usr/share/man/nl/man7/apt-patterns.7.gz",
+ "/usr/share/man/nl/man8/apt-cache.8.gz",
+ "/usr/share/man/nl/man8/apt-cdrom.8.gz",
+ "/usr/share/man/nl/man8/apt-config.8.gz",
+ "/usr/share/man/nl/man8/apt-get.8.gz",
+ "/usr/share/man/nl/man8/apt-mark.8.gz",
+ "/usr/share/man/nl/man8/apt-secure.8.gz",
+ "/usr/share/man/nl/man8/apt.8.gz",
+ "/usr/share/man/pl/man5/apt_preferences.5.gz",
+ "/usr/share/man/pl/man8/apt-cache.8.gz",
+ "/usr/share/man/pl/man8/apt-cdrom.8.gz",
+ "/usr/share/man/pl/man8/apt-config.8.gz",
+ "/usr/share/man/pt/man1/apt-transport-http.1.gz",
+ "/usr/share/man/pt/man1/apt-transport-https.1.gz",
+ "/usr/share/man/pt/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/pt/man5/apt.conf.5.gz",
+ "/usr/share/man/pt/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/pt/man5/apt_preferences.5.gz",
+ "/usr/share/man/pt/man5/sources.list.5.gz",
+ "/usr/share/man/pt/man7/apt-patterns.7.gz",
+ "/usr/share/man/pt/man8/apt-cache.8.gz",
+ "/usr/share/man/pt/man8/apt-cdrom.8.gz",
+ "/usr/share/man/pt/man8/apt-config.8.gz",
+ "/usr/share/man/pt/man8/apt-get.8.gz",
+ "/usr/share/man/pt/man8/apt-mark.8.gz",
+ "/usr/share/man/pt/man8/apt-secure.8.gz",
+ "/usr/share/man/pt/man8/apt.8.gz"
+ ]
+ },
+ {
+ "ID": "base-files@13.8+deb13u6",
+ "Name": "base-files",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "4bb4c2ef5a12c64b"
+ },
+ "Version": "13.8+deb13u6",
+ "Arch": "amd64",
+ "SrcName": "base-files",
+ "SrcVersion": "13.8+deb13u6",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "verbatim"
+ ],
+ "Maintainer": "Santiago Vila \u003csanvila@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/os-release",
+ "/usr/share/base-files/dot.bashrc",
+ "/usr/share/base-files/dot.profile",
+ "/usr/share/base-files/dot.profile.md5sums",
+ "/usr/share/base-files/info.dir",
+ "/usr/share/base-files/motd",
+ "/usr/share/base-files/profile",
+ "/usr/share/base-files/profile.md5sums",
+ "/usr/share/base-files/staff-group-for-usr-local",
+ "/usr/share/common-licenses/Apache-2.0",
+ "/usr/share/common-licenses/Artistic",
+ "/usr/share/common-licenses/BSD",
+ "/usr/share/common-licenses/CC0-1.0",
+ "/usr/share/common-licenses/GFDL-1.2",
+ "/usr/share/common-licenses/GFDL-1.3",
+ "/usr/share/common-licenses/GPL-1",
+ "/usr/share/common-licenses/GPL-2",
+ "/usr/share/common-licenses/GPL-3",
+ "/usr/share/common-licenses/LGPL-2",
+ "/usr/share/common-licenses/LGPL-2.1",
+ "/usr/share/common-licenses/LGPL-3",
+ "/usr/share/common-licenses/MPL-1.1",
+ "/usr/share/common-licenses/MPL-2.0",
+ "/usr/share/doc/base-files/NEWS.Debian.gz",
+ "/usr/share/doc/base-files/README",
+ "/usr/share/doc/base-files/README.FHS",
+ "/usr/share/doc/base-files/changelog.gz",
+ "/usr/share/doc/base-files/copyright",
+ "/usr/share/lintian/overrides/base-files"
+ ]
+ },
+ {
+ "ID": "base-passwd@3.6.7",
+ "Name": "base-passwd",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64\u0026distro=debian-13.6",
+ "UID": "bc0cc430715927e6"
+ },
+ "Version": "3.6.7",
+ "Arch": "amd64",
+ "SrcName": "base-passwd",
+ "SrcVersion": "3.6.7",
+ "Licenses": [
+ "GPL-2.0-only",
+ "public-domain"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libdebconfclient0@0.280",
+ "libselinux1@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/update-passwd",
+ "/usr/share/base-passwd/group.master",
+ "/usr/share/base-passwd/passwd.master",
+ "/usr/share/doc-base/base-passwd.users-and-groups",
+ "/usr/share/doc/base-passwd/README",
+ "/usr/share/doc/base-passwd/changelog.gz",
+ "/usr/share/doc/base-passwd/copyright",
+ "/usr/share/doc/base-passwd/users-and-groups.html",
+ "/usr/share/doc/base-passwd/users-and-groups.txt.gz",
+ "/usr/share/lintian/overrides/base-passwd",
+ "/usr/share/man/de/man8/update-passwd.8.gz",
+ "/usr/share/man/es/man8/update-passwd.8.gz",
+ "/usr/share/man/fr/man8/update-passwd.8.gz",
+ "/usr/share/man/ja/man8/update-passwd.8.gz",
+ "/usr/share/man/man8/update-passwd.8.gz",
+ "/usr/share/man/pl/man8/update-passwd.8.gz",
+ "/usr/share/man/ro/man8/update-passwd.8.gz",
+ "/usr/share/man/ru/man8/update-passwd.8.gz"
+ ]
+ },
+ {
+ "ID": "bash@5.2.37-2+b9",
+ "Name": "bash",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64\u0026distro=debian-13.6",
+ "UID": "2c8d7060f3972831"
+ },
+ "Version": "5.2.37",
+ "Release": "2+b9",
+ "Arch": "amd64",
+ "SrcName": "bash",
+ "SrcVersion": "5.2.37",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-only",
+ "GFDL-1.3-only",
+ "Latex2e",
+ "BSD-4-Clause-UC",
+ "MIT",
+ "permissive"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "DependsOn": [
+ "base-files@13.8+deb13u6",
+ "debianutils@5.23.2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/bash",
+ "/usr/bin/bashbug",
+ "/usr/bin/clear_console",
+ "/usr/share/debianutils/shells.d/bash",
+ "/usr/share/doc/bash/CHANGES.gz",
+ "/usr/share/doc/bash/COMPAT.gz",
+ "/usr/share/doc/bash/INTRO.gz",
+ "/usr/share/doc/bash/NEWS.gz",
+ "/usr/share/doc/bash/POSIX.gz",
+ "/usr/share/doc/bash/RBASH",
+ "/usr/share/doc/bash/README.Debian.gz",
+ "/usr/share/doc/bash/README.abs-guide",
+ "/usr/share/doc/bash/README.commands.gz",
+ "/usr/share/doc/bash/README.gz",
+ "/usr/share/doc/bash/changelog.Debian.amd64.gz",
+ "/usr/share/doc/bash/changelog.Debian.gz",
+ "/usr/share/doc/bash/changelog.gz",
+ "/usr/share/doc/bash/copyright",
+ "/usr/share/doc/bash/inputrc.arrows",
+ "/usr/share/lintian/overrides/bash",
+ "/usr/share/locale/af/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/da/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/de/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/el/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/en@quot/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/es/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/et/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/id/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/it/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/bash.mo",
+ "/usr/share/man/man1/bash.1.gz",
+ "/usr/share/man/man1/bashbug.1.gz",
+ "/usr/share/man/man1/clear_console.1.gz",
+ "/usr/share/man/man1/rbash.1.gz",
+ "/usr/share/man/man7/bash-builtins.7.gz",
+ "/usr/share/menu/bash"
+ ]
+ },
+ {
+ "ID": "bsdutils@1:2.41-5",
+ "Name": "bsdutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "c9de60be80a96a27"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/logger",
+ "/usr/bin/renice",
+ "/usr/bin/script",
+ "/usr/bin/scriptlive",
+ "/usr/bin/scriptreplay",
+ "/usr/bin/wall",
+ "/usr/share/bash-completion/completions/logger",
+ "/usr/share/bash-completion/completions/renice",
+ "/usr/share/bash-completion/completions/script",
+ "/usr/share/bash-completion/completions/scriptlive",
+ "/usr/share/bash-completion/completions/scriptreplay",
+ "/usr/share/bash-completion/completions/wall",
+ "/usr/share/doc/bsdutils/NEWS.Debian.gz",
+ "/usr/share/doc/bsdutils/changelog.Debian.gz",
+ "/usr/share/doc/bsdutils/changelog.gz",
+ "/usr/share/doc/bsdutils/copyright",
+ "/usr/share/lintian/overrides/bsdutils",
+ "/usr/share/man/man1/logger.1.gz",
+ "/usr/share/man/man1/renice.1.gz",
+ "/usr/share/man/man1/script.1.gz",
+ "/usr/share/man/man1/scriptlive.1.gz",
+ "/usr/share/man/man1/scriptreplay.1.gz",
+ "/usr/share/man/man1/wall.1.gz"
+ ]
+ },
+ {
+ "ID": "ca-certificates@20250419",
+ "Name": "ca-certificates",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ca-certificates@20250419?arch=all\u0026distro=debian-13.6",
+ "UID": "6365e842529686ef"
+ },
+ "Version": "20250419",
+ "Arch": "all",
+ "SrcName": "ca-certificates",
+ "SrcVersion": "20250419",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "MPL-2.0"
+ ],
+ "Maintainer": "Julien Cristau \u003cjcristau@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "openssl@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/update-ca-certificates",
+ "/usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt",
+ "/usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt",
+ "/usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM_SERVIDORES_SEGUROS.crt",
+ "/usr/share/ca-certificates/mozilla/ANF_Secure_Server_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_Root_CA_ECC_TLS_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_Root_CA_RSA_TLS_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt",
+ "/usr/share/ca-certificates/mozilla/BJCA_Global_Root_CA1.crt",
+ "/usr/share/ca-certificates/mozilla/BJCA_Global_Root_CA2.crt",
+ "/usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt",
+ "/usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt",
+ "/usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Certainly_Root_E1.crt",
+ "/usr/share/ca-certificates/mozilla/Certainly_Root_R1.crt",
+ "/usr/share/ca-certificates/mozilla/Certigna.crt",
+ "/usr/share/ca-certificates/mozilla/Certigna_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_EC-384_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_ECC_Root-01.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_ECC_Root-02.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_RSA_Root-01.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_RSA_Root-02.crt",
+ "/usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_BR_Root_CA_1_2020.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_BR_Root_CA_2_2023.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_EV_Root_CA_1_2020.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_EV_Root_CA_2_2023.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_TLS_ECC_P384_Root_G5.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_TLS_RSA4096_Root_G5.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/FIRMAPROFESIONAL_CA_ROOT-A_WEB.crt",
+ "/usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt",
+ "/usr/share/ca-certificates/mozilla/GLOBALTRUST_2020.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R1.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R2.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R3.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R4.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_E46.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_R46.crt",
+ "/usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/HARICA_TLS_ECC_Root_CA_2021.crt",
+ "/usr/share/ca-certificates/mozilla/HARICA_TLS_RSA_Root_CA_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt",
+ "/usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt",
+ "/usr/share/ca-certificates/mozilla/HiPKI_Root_CA_-_G1.crt",
+ "/usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt",
+ "/usr/share/ca-certificates/mozilla/ISRG_Root_X2.crt",
+ "/usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/Izenpe.com.crt",
+ "/usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt",
+ "/usr/share/ca-certificates/mozilla/Microsoft_ECC_Root_Certificate_Authority_2017.crt",
+ "/usr/share/ca-certificates/mozilla/Microsoft_RSA_Root_Certificate_Authority_2017.crt",
+ "/usr/share/ca-certificates/mozilla/NAVER_Global_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt",
+ "/usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt",
+ "/usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_TLS_ECC_Root_CA_2022.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_TLS_RSA_Root_CA_2022.crt",
+ "/usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt",
+ "/usr/share/ca-certificates/mozilla/Sectigo_Public_Server_Authentication_Root_E46.crt",
+ "/usr/share/ca-certificates/mozilla/Sectigo_Public_Server_Authentication_Root_R46.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA12.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA14.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA15.crt",
+ "/usr/share/ca-certificates/mozilla/SecureTrust_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Secure_Global_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Security_Communication_ECC_RootCA1.crt",
+ "/usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt",
+ "/usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt",
+ "/usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_CYBER_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Telekom_Security_TLS_ECC_Root_2020.crt",
+ "/usr/share/ca-certificates/mozilla/Telekom_Security_TLS_RSA_Root_2023.crt",
+ "/usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt",
+ "/usr/share/ca-certificates/mozilla/Telia_Root_CA_v2.crt",
+ "/usr/share/ca-certificates/mozilla/TrustAsia_Global_Root_CA_G3.crt",
+ "/usr/share/ca-certificates/mozilla/TrustAsia_Global_Root_CA_G4.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_ECC_P256_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_ECC_P384_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/TunTrust_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/UCA_Extended_Validation_Root.crt",
+ "/usr/share/ca-certificates/mozilla/UCA_Global_G2_Root.crt",
+ "/usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt",
+ "/usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt",
+ "/usr/share/ca-certificates/mozilla/certSIGN_Root_CA_G2.crt",
+ "/usr/share/ca-certificates/mozilla/e-Szigno_Root_CA_2017.crt",
+ "/usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_C3.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_Root_CA_-_C1.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_Root_CA_-_G1.crt",
+ "/usr/share/ca-certificates/mozilla/vTrus_ECC_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/vTrus_Root_CA.crt",
+ "/usr/share/doc/ca-certificates/README.Debian",
+ "/usr/share/doc/ca-certificates/changelog.gz",
+ "/usr/share/doc/ca-certificates/copyright",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/Makefile",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/README",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/ca-certificates-local.triggers",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/changelog",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/compat",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/control",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/copyright",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/postrm",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/rules",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/source/format",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/local/Local_Root_CA.crt",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/local/Makefile",
+ "/usr/share/man/man8/update-ca-certificates.8.gz"
+ ]
+ },
+ {
+ "ID": "coreutils@9.7-3",
+ "Name": "coreutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/coreutils@9.7-3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a90cbdbcbab1768e"
+ },
+ "Version": "9.7",
+ "Release": "3",
+ "Arch": "amd64",
+ "SrcName": "coreutils",
+ "SrcVersion": "9.7",
+ "SrcRelease": "3",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "BSD-4-Clause-UC",
+ "GPL-3.0-only",
+ "ISC",
+ "FSFULLR",
+ "GFDL-1.3-no-invariants-only",
+ "GFDL-1.3-only"
+ ],
+ "Maintainer": "Michael Stone \u003cmstone@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/[",
+ "/usr/bin/arch",
+ "/usr/bin/b2sum",
+ "/usr/bin/base32",
+ "/usr/bin/base64",
+ "/usr/bin/basename",
+ "/usr/bin/basenc",
+ "/usr/bin/cat",
+ "/usr/bin/chcon",
+ "/usr/bin/chgrp",
+ "/usr/bin/chmod",
+ "/usr/bin/chown",
+ "/usr/bin/cksum",
+ "/usr/bin/comm",
+ "/usr/bin/cp",
+ "/usr/bin/csplit",
+ "/usr/bin/cut",
+ "/usr/bin/date",
+ "/usr/bin/dd",
+ "/usr/bin/df",
+ "/usr/bin/dir",
+ "/usr/bin/dircolors",
+ "/usr/bin/dirname",
+ "/usr/bin/du",
+ "/usr/bin/echo",
+ "/usr/bin/env",
+ "/usr/bin/expand",
+ "/usr/bin/expr",
+ "/usr/bin/factor",
+ "/usr/bin/false",
+ "/usr/bin/fmt",
+ "/usr/bin/fold",
+ "/usr/bin/groups",
+ "/usr/bin/head",
+ "/usr/bin/hostid",
+ "/usr/bin/id",
+ "/usr/bin/install",
+ "/usr/bin/join",
+ "/usr/bin/link",
+ "/usr/bin/ln",
+ "/usr/bin/logname",
+ "/usr/bin/ls",
+ "/usr/bin/md5sum",
+ "/usr/bin/mkdir",
+ "/usr/bin/mkfifo",
+ "/usr/bin/mknod",
+ "/usr/bin/mktemp",
+ "/usr/bin/mv",
+ "/usr/bin/nice",
+ "/usr/bin/nl",
+ "/usr/bin/nohup",
+ "/usr/bin/nproc",
+ "/usr/bin/numfmt",
+ "/usr/bin/od",
+ "/usr/bin/paste",
+ "/usr/bin/pathchk",
+ "/usr/bin/pinky",
+ "/usr/bin/pr",
+ "/usr/bin/printenv",
+ "/usr/bin/printf",
+ "/usr/bin/ptx",
+ "/usr/bin/pwd",
+ "/usr/bin/readlink",
+ "/usr/bin/realpath",
+ "/usr/bin/rm",
+ "/usr/bin/rmdir",
+ "/usr/bin/runcon",
+ "/usr/bin/seq",
+ "/usr/bin/sha1sum",
+ "/usr/bin/sha224sum",
+ "/usr/bin/sha256sum",
+ "/usr/bin/sha384sum",
+ "/usr/bin/sha512sum",
+ "/usr/bin/shred",
+ "/usr/bin/shuf",
+ "/usr/bin/sleep",
+ "/usr/bin/sort",
+ "/usr/bin/split",
+ "/usr/bin/stat",
+ "/usr/bin/stdbuf",
+ "/usr/bin/stty",
+ "/usr/bin/sum",
+ "/usr/bin/sync",
+ "/usr/bin/tac",
+ "/usr/bin/tail",
+ "/usr/bin/tee",
+ "/usr/bin/test",
+ "/usr/bin/timeout",
+ "/usr/bin/touch",
+ "/usr/bin/tr",
+ "/usr/bin/true",
+ "/usr/bin/truncate",
+ "/usr/bin/tsort",
+ "/usr/bin/tty",
+ "/usr/bin/uname",
+ "/usr/bin/unexpand",
+ "/usr/bin/uniq",
+ "/usr/bin/unlink",
+ "/usr/bin/users",
+ "/usr/bin/vdir",
+ "/usr/bin/wc",
+ "/usr/bin/who",
+ "/usr/bin/whoami",
+ "/usr/bin/yes",
+ "/usr/libexec/coreutils/libstdbuf.so",
+ "/usr/sbin/chroot",
+ "/usr/share/doc/coreutils/AUTHORS",
+ "/usr/share/doc/coreutils/NEWS.gz",
+ "/usr/share/doc/coreutils/README.Debian",
+ "/usr/share/doc/coreutils/README.gz",
+ "/usr/share/doc/coreutils/THANKS.gz",
+ "/usr/share/doc/coreutils/TODO.gz",
+ "/usr/share/doc/coreutils/changelog.Debian.gz",
+ "/usr/share/doc/coreutils/changelog.gz",
+ "/usr/share/doc/coreutils/copyright",
+ "/usr/share/info/coreutils.info.gz",
+ "/usr/share/lintian/overrides/coreutils",
+ "/usr/share/locale/af/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/be/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/et/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ia/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/lg/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/coreutils.mo",
+ "/usr/share/man/man1/arch.1.gz",
+ "/usr/share/man/man1/b2sum.1.gz",
+ "/usr/share/man/man1/base32.1.gz",
+ "/usr/share/man/man1/base64.1.gz",
+ "/usr/share/man/man1/basename.1.gz",
+ "/usr/share/man/man1/basenc.1.gz",
+ "/usr/share/man/man1/cat.1.gz",
+ "/usr/share/man/man1/chcon.1.gz",
+ "/usr/share/man/man1/chgrp.1.gz",
+ "/usr/share/man/man1/chmod.1.gz",
+ "/usr/share/man/man1/chown.1.gz",
+ "/usr/share/man/man1/cksum.1.gz",
+ "/usr/share/man/man1/comm.1.gz",
+ "/usr/share/man/man1/cp.1.gz",
+ "/usr/share/man/man1/csplit.1.gz",
+ "/usr/share/man/man1/cut.1.gz",
+ "/usr/share/man/man1/date.1.gz",
+ "/usr/share/man/man1/dd.1.gz",
+ "/usr/share/man/man1/df.1.gz",
+ "/usr/share/man/man1/dir.1.gz",
+ "/usr/share/man/man1/dircolors.1.gz",
+ "/usr/share/man/man1/dirname.1.gz",
+ "/usr/share/man/man1/du.1.gz",
+ "/usr/share/man/man1/echo.1.gz",
+ "/usr/share/man/man1/env.1.gz",
+ "/usr/share/man/man1/expand.1.gz",
+ "/usr/share/man/man1/expr.1.gz",
+ "/usr/share/man/man1/factor.1.gz",
+ "/usr/share/man/man1/false.1.gz",
+ "/usr/share/man/man1/fmt.1.gz",
+ "/usr/share/man/man1/fold.1.gz",
+ "/usr/share/man/man1/groups.1.gz",
+ "/usr/share/man/man1/head.1.gz",
+ "/usr/share/man/man1/hostid.1.gz",
+ "/usr/share/man/man1/id.1.gz",
+ "/usr/share/man/man1/install.1.gz",
+ "/usr/share/man/man1/join.1.gz",
+ "/usr/share/man/man1/link.1.gz",
+ "/usr/share/man/man1/ln.1.gz",
+ "/usr/share/man/man1/logname.1.gz",
+ "/usr/share/man/man1/ls.1.gz",
+ "/usr/share/man/man1/md5sum.1.gz",
+ "/usr/share/man/man1/mkdir.1.gz",
+ "/usr/share/man/man1/mkfifo.1.gz",
+ "/usr/share/man/man1/mknod.1.gz",
+ "/usr/share/man/man1/mktemp.1.gz",
+ "/usr/share/man/man1/mv.1.gz",
+ "/usr/share/man/man1/nice.1.gz",
+ "/usr/share/man/man1/nl.1.gz",
+ "/usr/share/man/man1/nohup.1.gz",
+ "/usr/share/man/man1/nproc.1.gz",
+ "/usr/share/man/man1/numfmt.1.gz",
+ "/usr/share/man/man1/od.1.gz",
+ "/usr/share/man/man1/paste.1.gz",
+ "/usr/share/man/man1/pathchk.1.gz",
+ "/usr/share/man/man1/pinky.1.gz",
+ "/usr/share/man/man1/pr.1.gz",
+ "/usr/share/man/man1/printenv.1.gz",
+ "/usr/share/man/man1/printf.1.gz",
+ "/usr/share/man/man1/ptx.1.gz",
+ "/usr/share/man/man1/pwd.1.gz",
+ "/usr/share/man/man1/readlink.1.gz",
+ "/usr/share/man/man1/realpath.1.gz",
+ "/usr/share/man/man1/rm.1.gz",
+ "/usr/share/man/man1/rmdir.1.gz",
+ "/usr/share/man/man1/runcon.1.gz",
+ "/usr/share/man/man1/seq.1.gz",
+ "/usr/share/man/man1/sha1sum.1.gz",
+ "/usr/share/man/man1/sha224sum.1.gz",
+ "/usr/share/man/man1/sha256sum.1.gz",
+ "/usr/share/man/man1/sha384sum.1.gz",
+ "/usr/share/man/man1/sha512sum.1.gz",
+ "/usr/share/man/man1/shred.1.gz",
+ "/usr/share/man/man1/shuf.1.gz",
+ "/usr/share/man/man1/sleep.1.gz",
+ "/usr/share/man/man1/sort.1.gz",
+ "/usr/share/man/man1/split.1.gz",
+ "/usr/share/man/man1/stat.1.gz",
+ "/usr/share/man/man1/stdbuf.1.gz",
+ "/usr/share/man/man1/stty.1.gz",
+ "/usr/share/man/man1/sum.1.gz",
+ "/usr/share/man/man1/sync.1.gz",
+ "/usr/share/man/man1/tac.1.gz",
+ "/usr/share/man/man1/tail.1.gz",
+ "/usr/share/man/man1/tee.1.gz",
+ "/usr/share/man/man1/test.1.gz",
+ "/usr/share/man/man1/timeout.1.gz",
+ "/usr/share/man/man1/touch.1.gz",
+ "/usr/share/man/man1/tr.1.gz",
+ "/usr/share/man/man1/true.1.gz",
+ "/usr/share/man/man1/truncate.1.gz",
+ "/usr/share/man/man1/tsort.1.gz",
+ "/usr/share/man/man1/tty.1.gz",
+ "/usr/share/man/man1/uname.1.gz",
+ "/usr/share/man/man1/unexpand.1.gz",
+ "/usr/share/man/man1/uniq.1.gz",
+ "/usr/share/man/man1/unlink.1.gz",
+ "/usr/share/man/man1/users.1.gz",
+ "/usr/share/man/man1/vdir.1.gz",
+ "/usr/share/man/man1/wc.1.gz",
+ "/usr/share/man/man1/who.1.gz",
+ "/usr/share/man/man1/whoami.1.gz",
+ "/usr/share/man/man1/yes.1.gz",
+ "/usr/share/man/man8/chroot.8.gz"
+ ]
+ },
+ {
+ "ID": "cyrus-sasl-lib@2.1.26-24.el7_9",
+ "Name": "cyrus-sasl-lib",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9",
+ "UID": "b814395bf7062155",
+ "BOMRef": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2"
+ },
+ "Version": "2.1.26",
+ "Release": "24.el7_9",
+ "SrcName": "cyrus-sasl-lib",
+ "SrcVersion": "2.1.26",
+ "SrcRelease": "24.el7_9",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "dash@0.5.12-12",
+ "Name": "dash",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/dash@0.5.12-12?arch=amd64\u0026distro=debian-13.6",
+ "UID": "89c835b0985cdc5c"
+ },
+ "Version": "0.5.12",
+ "Release": "12",
+ "Arch": "amd64",
+ "SrcName": "dash",
+ "SrcVersion": "0.5.12",
+ "SrcRelease": "12",
+ "Licenses": [
+ "BSD-3-Clause",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Andrej Shadura \u003candrewsh@debian.org\u003e",
+ "DependsOn": [
+ "debianutils@5.23.2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/dash",
+ "/usr/share/debianutils/shells.d/dash",
+ "/usr/share/doc/dash/README.Debian.diet",
+ "/usr/share/doc/dash/README.source",
+ "/usr/share/doc/dash/changelog.Debian.gz",
+ "/usr/share/doc/dash/changelog.gz",
+ "/usr/share/doc/dash/copyright",
+ "/usr/share/lintian/overrides/dash",
+ "/usr/share/man/man1/dash.1.gz",
+ "/usr/share/menu/dash"
+ ]
+ },
+ {
+ "ID": "debconf@1.5.91",
+ "Name": "debconf",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debconf@1.5.91?arch=all\u0026distro=debian-13.6",
+ "UID": "dbd74d1c32616a65"
+ },
+ "Version": "1.5.91",
+ "Arch": "all",
+ "SrcName": "debconf",
+ "SrcVersion": "1.5.91",
+ "Licenses": [
+ "BSD-2-Clause"
+ ],
+ "Maintainer": "Debconf Developers \u003cdebconf-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/debconf",
+ "/usr/bin/debconf-apt-progress",
+ "/usr/bin/debconf-communicate",
+ "/usr/bin/debconf-copydb",
+ "/usr/bin/debconf-escape",
+ "/usr/bin/debconf-set-selections",
+ "/usr/bin/debconf-show",
+ "/usr/sbin/dpkg-preconfigure",
+ "/usr/sbin/dpkg-reconfigure",
+ "/usr/share/bash-completion/completions/debconf",
+ "/usr/share/debconf/confmodule",
+ "/usr/share/debconf/confmodule.sh",
+ "/usr/share/debconf/debconf.conf",
+ "/usr/share/debconf/fix_db.pl",
+ "/usr/share/debconf/frontend",
+ "/usr/share/doc/debconf/README.Debian",
+ "/usr/share/doc/debconf/changelog.gz",
+ "/usr/share/doc/debconf/copyright",
+ "/usr/share/lintian/overrides/debconf",
+ "/usr/share/man/man1/debconf-apt-progress.1.gz",
+ "/usr/share/man/man1/debconf-communicate.1.gz",
+ "/usr/share/man/man1/debconf-copydb.1.gz",
+ "/usr/share/man/man1/debconf-escape.1.gz",
+ "/usr/share/man/man1/debconf-set-selections.1.gz",
+ "/usr/share/man/man1/debconf-show.1.gz",
+ "/usr/share/man/man1/debconf.1.gz",
+ "/usr/share/man/man8/dpkg-preconfigure.8.gz",
+ "/usr/share/man/man8/dpkg-reconfigure.8.gz",
+ "/usr/share/perl5/Debconf/AutoSelect.pm",
+ "/usr/share/perl5/Debconf/Base.pm",
+ "/usr/share/perl5/Debconf/Client/ConfModule.pm",
+ "/usr/share/perl5/Debconf/ConfModule.pm",
+ "/usr/share/perl5/Debconf/Config.pm",
+ "/usr/share/perl5/Debconf/Db.pm",
+ "/usr/share/perl5/Debconf/DbDriver.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Backup.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Cache.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Copy.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Debug.pm",
+ "/usr/share/perl5/Debconf/DbDriver/DirTree.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Directory.pm",
+ "/usr/share/perl5/Debconf/DbDriver/File.pm",
+ "/usr/share/perl5/Debconf/DbDriver/LDAP.pm",
+ "/usr/share/perl5/Debconf/DbDriver/PackageDir.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Pipe.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Stack.pm",
+ "/usr/share/perl5/Debconf/Element.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/String.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/String.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/String.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/String.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/String.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Web/String.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Text.pm",
+ "/usr/share/perl5/Debconf/Encoding.pm",
+ "/usr/share/perl5/Debconf/Format.pm",
+ "/usr/share/perl5/Debconf/Format/822.pm",
+ "/usr/share/perl5/Debconf/FrontEnd.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Dialog.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Editor.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Gnome.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Kde.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Noninteractive.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Passthrough.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Readline.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/ScreenSize.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Teletype.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Text.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Web.pm",
+ "/usr/share/perl5/Debconf/Gettext.pm",
+ "/usr/share/perl5/Debconf/Iterator.pm",
+ "/usr/share/perl5/Debconf/Log.pm",
+ "/usr/share/perl5/Debconf/Path.pm",
+ "/usr/share/perl5/Debconf/Priority.pm",
+ "/usr/share/perl5/Debconf/Question.pm",
+ "/usr/share/perl5/Debconf/Template.pm",
+ "/usr/share/perl5/Debconf/Template/Transient.pm",
+ "/usr/share/perl5/Debconf/TmpFile.pm",
+ "/usr/share/perl5/Debian/DebConf/Client/ConfModule.pm",
+ "/usr/share/pixmaps/debian-logo.png"
+ ]
+ },
+ {
+ "ID": "debian-archive-keyring@2025.1",
+ "Name": "debian-archive-keyring",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all\u0026distro=debian-13.6",
+ "UID": "3d23f3bc34b84a13"
+ },
+ "Version": "2025.1",
+ "Arch": "all",
+ "SrcName": "debian-archive-keyring",
+ "SrcVersion": "2025.1",
+ "Licenses": [
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian Release Team \u003cpackages@release.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/debian-archive-keyring/NEWS.Debian.gz",
+ "/usr/share/doc/debian-archive-keyring/README",
+ "/usr/share/doc/debian-archive-keyring/changelog.gz",
+ "/usr/share/doc/debian-archive-keyring/copyright",
+ "/usr/share/keyrings/debian-archive-bookworm-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bookworm-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bookworm-stable.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-stable.pgp",
+ "/usr/share/keyrings/debian-archive-keyring.pgp",
+ "/usr/share/keyrings/debian-archive-removed-keys.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-stable.pgp"
+ ]
+ },
+ {
+ "ID": "debianutils@5.23.2",
+ "Name": "debianutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debianutils@5.23.2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1faaee83f4beb2af"
+ },
+ "Version": "5.23.2",
+ "Arch": "amd64",
+ "SrcName": "debianutils",
+ "SrcVersion": "5.23.2",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "public-domain",
+ "SMAIL-GPL"
+ ],
+ "Maintainer": "Ileana Dumitrescu \u003cileanadumitrescu95@gmail.com\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/ischroot",
+ "/usr/bin/run-parts",
+ "/usr/bin/savelog",
+ "/usr/bin/tempfile",
+ "/usr/bin/which.debianutils",
+ "/usr/sbin/add-shell",
+ "/usr/sbin/installkernel",
+ "/usr/sbin/remove-shell",
+ "/usr/sbin/update-shells",
+ "/usr/share/debianutils/shells",
+ "/usr/share/doc/debianutils/README.shells",
+ "/usr/share/doc/debianutils/changelog.gz",
+ "/usr/share/doc/debianutils/copyright",
+ "/usr/share/man/de/man1/which.debianutils.1.gz",
+ "/usr/share/man/de/man8/add-shell.8.gz",
+ "/usr/share/man/de/man8/installkernel.8.gz",
+ "/usr/share/man/de/man8/remove-shell.8.gz",
+ "/usr/share/man/de/man8/run-parts.8.gz",
+ "/usr/share/man/de/man8/savelog.8.gz",
+ "/usr/share/man/es/man1/which.debianutils.1.gz",
+ "/usr/share/man/es/man8/add-shell.8.gz",
+ "/usr/share/man/es/man8/installkernel.8.gz",
+ "/usr/share/man/es/man8/remove-shell.8.gz",
+ "/usr/share/man/es/man8/run-parts.8.gz",
+ "/usr/share/man/es/man8/savelog.8.gz",
+ "/usr/share/man/fr/man1/which.debianutils.1.gz",
+ "/usr/share/man/fr/man8/add-shell.8.gz",
+ "/usr/share/man/fr/man8/installkernel.8.gz",
+ "/usr/share/man/fr/man8/remove-shell.8.gz",
+ "/usr/share/man/fr/man8/run-parts.8.gz",
+ "/usr/share/man/fr/man8/savelog.8.gz",
+ "/usr/share/man/it/man1/which.debianutils.1.gz",
+ "/usr/share/man/it/man8/add-shell.8.gz",
+ "/usr/share/man/it/man8/installkernel.8.gz",
+ "/usr/share/man/it/man8/remove-shell.8.gz",
+ "/usr/share/man/it/man8/run-parts.8.gz",
+ "/usr/share/man/it/man8/savelog.8.gz",
+ "/usr/share/man/ja/man1/which.debianutils.1.gz",
+ "/usr/share/man/ja/man8/add-shell.8.gz",
+ "/usr/share/man/ja/man8/installkernel.8.gz",
+ "/usr/share/man/ja/man8/remove-shell.8.gz",
+ "/usr/share/man/ja/man8/run-parts.8.gz",
+ "/usr/share/man/ja/man8/savelog.8.gz",
+ "/usr/share/man/man1/ischroot.1.gz",
+ "/usr/share/man/man1/tempfile.1.gz",
+ "/usr/share/man/man1/which.debianutils.1.gz",
+ "/usr/share/man/man8/add-shell.8.gz",
+ "/usr/share/man/man8/installkernel.8.gz",
+ "/usr/share/man/man8/remove-shell.8.gz",
+ "/usr/share/man/man8/run-parts.8.gz",
+ "/usr/share/man/man8/savelog.8.gz",
+ "/usr/share/man/man8/update-shells.8.gz",
+ "/usr/share/man/pl/man1/which.debianutils.1.gz",
+ "/usr/share/man/pl/man8/add-shell.8.gz",
+ "/usr/share/man/pl/man8/installkernel.8.gz",
+ "/usr/share/man/pl/man8/remove-shell.8.gz",
+ "/usr/share/man/pl/man8/run-parts.8.gz",
+ "/usr/share/man/pl/man8/savelog.8.gz",
+ "/usr/share/man/pt/man1/which.debianutils.1.gz",
+ "/usr/share/man/pt/man8/add-shell.8.gz",
+ "/usr/share/man/pt/man8/installkernel.8.gz",
+ "/usr/share/man/pt/man8/remove-shell.8.gz",
+ "/usr/share/man/pt/man8/run-parts.8.gz",
+ "/usr/share/man/pt/man8/savelog.8.gz",
+ "/usr/share/man/sl/man1/which.debianutils.1.gz",
+ "/usr/share/man/sl/man8/add-shell.8.gz",
+ "/usr/share/man/sl/man8/installkernel.8.gz",
+ "/usr/share/man/sl/man8/remove-shell.8.gz",
+ "/usr/share/man/sl/man8/run-parts.8.gz",
+ "/usr/share/man/sl/man8/savelog.8.gz"
+ ]
+ },
+ {
+ "ID": "diffutils@1:3.10-4",
+ "Name": "diffutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/diffutils@3.10-4?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "6ae1b70a720e3ebb"
+ },
+ "Version": "3.10",
+ "Release": "4",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "diffutils",
+ "SrcVersion": "3.10",
+ "SrcRelease": "4",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "FSFULLR",
+ "LGPL-2.1-or-later",
+ "GPL-3.0-with-autoconf-exception+",
+ "GPL-3.0-only",
+ "GPL-3+ with texinfo exception",
+ "LGPL-2.0-or-later",
+ "GPL-2.0-or-later",
+ "X11",
+ "FSFAP",
+ "GFDL-1.3-no-invariants-only",
+ "LGPL-3.0-or-later",
+ "LGPL-3.0-only",
+ "public-domain",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-2.0-only",
+ "GFDL-1.3-only"
+ ],
+ "Maintainer": "Santiago Vila \u003csanvila@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/cmp",
+ "/usr/bin/diff",
+ "/usr/bin/diff3",
+ "/usr/bin/sdiff",
+ "/usr/share/doc/diffutils/NEWS.gz",
+ "/usr/share/doc/diffutils/changelog.Debian.gz",
+ "/usr/share/doc/diffutils/changelog.gz",
+ "/usr/share/doc/diffutils/copyright",
+ "/usr/share/info/diffutils.info.gz",
+ "/usr/share/locale/bg/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/he/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/lv/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/diffutils.mo",
+ "/usr/share/man/man1/cmp.1.gz",
+ "/usr/share/man/man1/diff.1.gz",
+ "/usr/share/man/man1/diff3.1.gz",
+ "/usr/share/man/man1/sdiff.1.gz"
+ ]
+ },
+ {
+ "ID": "dpkg@1.22.22",
+ "Name": "dpkg",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/dpkg@1.22.22?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d88bc872d04d38e8"
+ },
+ "Version": "1.22.22",
+ "Arch": "amd64",
+ "SrcName": "dpkg",
+ "SrcVersion": "1.22.22",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "public-domain-s-s-d",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Dpkg Developers \u003cdebian-dpkg@lists.debian.org\u003e",
+ "DependsOn": [
+ "tar@1.35+dfsg-3.1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/dpkg",
+ "/usr/bin/dpkg-deb",
+ "/usr/bin/dpkg-divert",
+ "/usr/bin/dpkg-maintscript-helper",
+ "/usr/bin/dpkg-query",
+ "/usr/bin/dpkg-realpath",
+ "/usr/bin/dpkg-split",
+ "/usr/bin/dpkg-statoverride",
+ "/usr/bin/dpkg-trigger",
+ "/usr/bin/update-alternatives",
+ "/usr/lib/systemd/system/dpkg-db-backup.service",
+ "/usr/lib/systemd/system/dpkg-db-backup.timer",
+ "/usr/libexec/dpkg/dpkg-db-backup",
+ "/usr/libexec/dpkg/dpkg-db-keeper",
+ "/usr/sbin/start-stop-daemon",
+ "/usr/share/doc/dpkg/AUTHORS",
+ "/usr/share/doc/dpkg/README.api",
+ "/usr/share/doc/dpkg/README.bug-usertags.gz",
+ "/usr/share/doc/dpkg/README.feature-removal-schedule.gz",
+ "/usr/share/doc/dpkg/THANKS.gz",
+ "/usr/share/doc/dpkg/changelog.gz",
+ "/usr/share/doc/dpkg/copyright",
+ "/usr/share/dpkg/abitable",
+ "/usr/share/dpkg/cputable",
+ "/usr/share/dpkg/ostable",
+ "/usr/share/dpkg/sh/dpkg-error.sh",
+ "/usr/share/dpkg/tupletable",
+ "/usr/share/lintian/overrides/dpkg",
+ "/usr/share/lintian/profiles/dpkg/main.profile",
+ "/usr/share/locale/ast/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/da/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/de/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/el/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/es/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/et/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/id/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/it/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/km/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/oc/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/th/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/dpkg.mo",
+ "/usr/share/man/de/man1/dpkg-deb.1.gz",
+ "/usr/share/man/de/man1/dpkg-divert.1.gz",
+ "/usr/share/man/de/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/de/man1/dpkg-query.1.gz",
+ "/usr/share/man/de/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/de/man1/dpkg-split.1.gz",
+ "/usr/share/man/de/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/de/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/de/man1/dpkg.1.gz",
+ "/usr/share/man/de/man1/update-alternatives.1.gz",
+ "/usr/share/man/de/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/de/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/es/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/fr/man1/dpkg-divert.1.gz",
+ "/usr/share/man/fr/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/fr/man1/dpkg-query.1.gz",
+ "/usr/share/man/fr/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/fr/man1/dpkg-split.1.gz",
+ "/usr/share/man/fr/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/fr/man1/update-alternatives.1.gz",
+ "/usr/share/man/fr/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/fr/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/it/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/ja/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/man1/dpkg-deb.1.gz",
+ "/usr/share/man/man1/dpkg-divert.1.gz",
+ "/usr/share/man/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/man1/dpkg-query.1.gz",
+ "/usr/share/man/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/man1/dpkg-split.1.gz",
+ "/usr/share/man/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/man1/dpkg.1.gz",
+ "/usr/share/man/man1/update-alternatives.1.gz",
+ "/usr/share/man/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/nl/man1/dpkg-deb.1.gz",
+ "/usr/share/man/nl/man1/dpkg-divert.1.gz",
+ "/usr/share/man/nl/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/nl/man1/dpkg-query.1.gz",
+ "/usr/share/man/nl/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/nl/man1/dpkg-split.1.gz",
+ "/usr/share/man/nl/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/nl/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/nl/man1/dpkg.1.gz",
+ "/usr/share/man/nl/man1/update-alternatives.1.gz",
+ "/usr/share/man/nl/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/nl/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/pl/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/pt/man1/dpkg-deb.1.gz",
+ "/usr/share/man/pt/man1/dpkg-divert.1.gz",
+ "/usr/share/man/pt/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/pt/man1/dpkg-query.1.gz",
+ "/usr/share/man/pt/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/pt/man1/dpkg-split.1.gz",
+ "/usr/share/man/pt/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/pt/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/pt/man1/dpkg.1.gz",
+ "/usr/share/man/pt/man1/update-alternatives.1.gz",
+ "/usr/share/man/pt/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/pt/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/sv/man1/dpkg-deb.1.gz",
+ "/usr/share/man/sv/man1/dpkg-divert.1.gz",
+ "/usr/share/man/sv/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/sv/man1/dpkg-query.1.gz",
+ "/usr/share/man/sv/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/sv/man1/dpkg-split.1.gz",
+ "/usr/share/man/sv/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/sv/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/sv/man1/dpkg.1.gz",
+ "/usr/share/man/sv/man1/update-alternatives.1.gz",
+ "/usr/share/man/sv/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/sv/man8/start-stop-daemon.8.gz",
+ "/usr/share/polkit-1/actions/org.dpkg.pkexec.update-alternatives.policy"
+ ]
+ },
+ {
+ "ID": "findutils@4.10.0-3",
+ "Name": "findutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "111949a4800741f1"
+ },
+ "Version": "4.10.0",
+ "Release": "3",
+ "Arch": "amd64",
+ "SrcName": "findutils",
+ "SrcVersion": "4.10.0",
+ "SrcRelease": "3",
+ "Licenses": [
+ "GFDL-1.3-no-invariants-or-later",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "GPL-2+ with Autoconf-data exception",
+ "GPL-3+ with Autoconf-data exception",
+ "FSFULLR",
+ "GPL-2.0-or-later",
+ "X11",
+ "public-domain",
+ "LGPL-2.1-or-later",
+ "GPL with automake exception",
+ "LGPL-2.0-or-later",
+ "LGPL-3.0-or-later",
+ "BSD-3-Clause",
+ "GPL-3+ with Bison-2.2 exception",
+ "LGPL-3.0-only",
+ "ISC",
+ "GFDL-1.3-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Andreas Metzler \u003cametzler@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/find",
+ "/usr/bin/xargs",
+ "/usr/share/doc-base/findutils.findutils",
+ "/usr/share/doc/findutils/NEWS.gz",
+ "/usr/share/doc/findutils/README.gz",
+ "/usr/share/doc/findutils/TODO",
+ "/usr/share/doc/findutils/changelog.Debian.gz",
+ "/usr/share/doc/findutils/changelog.gz",
+ "/usr/share/doc/findutils/copyright",
+ "/usr/share/info/find-maint.info.gz",
+ "/usr/share/info/find.info.gz",
+ "/usr/share/locale/be/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/et/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/lg/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/findutils.mo",
+ "/usr/share/man/man1/find.1.gz",
+ "/usr/share/man/man1/xargs.1.gz"
+ ]
+ },
+ {
+ "ID": "gcc-14-base@14.2.0-19",
+ "Name": "gcc-14-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a2d64c6b5f038075"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-3.0-only",
+ "GFDL-1.2-only",
+ "Artistic-2.0",
+ "LGPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/gcc-14-base/README.Debian.amd64.gz",
+ "/usr/share/doc/gcc-14-base/TODO.Debian",
+ "/usr/share/doc/gcc-14-base/changelog.Debian.gz",
+ "/usr/share/doc/gcc-14-base/copyright"
+ ]
+ },
+ {
+ "ID": "grep@3.11-4",
+ "Name": "grep",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/grep@3.11-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d450e0ea7fae458f"
+ },
+ "Version": "3.11",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "grep",
+ "SrcVersion": "3.11",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only"
+ ],
+ "Maintainer": "Anibal Monsalve Salazar \u003canibal@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/egrep",
+ "/usr/bin/fgrep",
+ "/usr/bin/grep",
+ "/usr/bin/rgrep",
+ "/usr/share/doc/grep/AUTHORS",
+ "/usr/share/doc/grep/NEWS.Debian.gz",
+ "/usr/share/doc/grep/NEWS.gz",
+ "/usr/share/doc/grep/README",
+ "/usr/share/doc/grep/THANKS.gz",
+ "/usr/share/doc/grep/TODO.gz",
+ "/usr/share/doc/grep/changelog.Debian.gz",
+ "/usr/share/doc/grep/changelog.gz",
+ "/usr/share/doc/grep/copyright",
+ "/usr/share/info/grep.info.gz",
+ "/usr/share/locale/af/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/be/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/da/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/de/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/el/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/es/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/et/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/he/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/id/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/it/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/th/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/grep.mo",
+ "/usr/share/man/man1/grep.1.gz"
+ ]
+ },
+ {
+ "ID": "gzip@1.13-1",
+ "Name": "gzip",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/gzip@1.13-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "60254b2bea6a1f09"
+ },
+ "Version": "1.13",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "gzip",
+ "SrcVersion": "1.13",
+ "SrcRelease": "1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GFDL-1.3+-no-invariant",
+ "FSF-manpages",
+ "GPL-3.0-only",
+ "GFDL-3"
+ ],
+ "Maintainer": "Milan Kupcevic \u003cmilan@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/gunzip",
+ "/usr/bin/gzexe",
+ "/usr/bin/gzip",
+ "/usr/bin/zcat",
+ "/usr/bin/zcmp",
+ "/usr/bin/zdiff",
+ "/usr/bin/zegrep",
+ "/usr/bin/zfgrep",
+ "/usr/bin/zforce",
+ "/usr/bin/zgrep",
+ "/usr/bin/zless",
+ "/usr/bin/zmore",
+ "/usr/bin/znew",
+ "/usr/share/doc/gzip/NEWS.gz",
+ "/usr/share/doc/gzip/README.gz",
+ "/usr/share/doc/gzip/TODO",
+ "/usr/share/doc/gzip/changelog.Debian.gz",
+ "/usr/share/doc/gzip/changelog.gz",
+ "/usr/share/doc/gzip/copyright",
+ "/usr/share/info/gzip.info.gz",
+ "/usr/share/man/man1/gzexe.1.gz",
+ "/usr/share/man/man1/gzip.1.gz",
+ "/usr/share/man/man1/zdiff.1.gz",
+ "/usr/share/man/man1/zforce.1.gz",
+ "/usr/share/man/man1/zgrep.1.gz",
+ "/usr/share/man/man1/zless.1.gz",
+ "/usr/share/man/man1/zmore.1.gz",
+ "/usr/share/man/man1/znew.1.gz"
+ ]
+ },
+ {
+ "ID": "hostname@3.25",
+ "Name": "hostname",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/hostname@3.25?arch=amd64\u0026distro=debian-13.6",
+ "UID": "87ef62957d44b2c"
+ },
+ "Version": "3.25",
+ "Arch": "amd64",
+ "SrcName": "hostname",
+ "SrcVersion": "3.25",
+ "Licenses": [
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Michael Meskes \u003cmeskes@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/hostname",
+ "/usr/share/doc/hostname/changelog.gz",
+ "/usr/share/doc/hostname/copyright",
+ "/usr/share/man/man1/hostname.1.gz"
+ ]
+ },
+ {
+ "ID": "init-system-helpers@1.69~deb13u1",
+ "Name": "init-system-helpers",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all\u0026distro=debian-13.6",
+ "UID": "317be9d9c6744acd"
+ },
+ "Version": "1.69~deb13u1",
+ "Arch": "all",
+ "SrcName": "init-system-helpers",
+ "SrcVersion": "1.69~deb13u1",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/deb-systemd-helper",
+ "/usr/bin/deb-systemd-invoke",
+ "/usr/sbin/invoke-rc.d",
+ "/usr/sbin/service",
+ "/usr/sbin/update-rc.d",
+ "/usr/share/bug/init-system-helpers/control",
+ "/usr/share/doc/init-system-helpers/README.invoke-rc.d.gz",
+ "/usr/share/doc/init-system-helpers/README.policy-rc.d.gz",
+ "/usr/share/doc/init-system-helpers/changelog.gz",
+ "/usr/share/doc/init-system-helpers/copyright",
+ "/usr/share/lintian/overrides/init-system-helpers",
+ "/usr/share/man/man1/deb-systemd-helper.1p.gz",
+ "/usr/share/man/man1/deb-systemd-invoke.1p.gz",
+ "/usr/share/man/man8/invoke-rc.d.8.gz",
+ "/usr/share/man/man8/service.8.gz",
+ "/usr/share/man/man8/update-rc.d.8.gz"
+ ]
+ },
+ {
+ "ID": "keyutils-libs@1.5.8-3.el7",
+ "Name": "keyutils-libs",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7",
+ "UID": "93c3119deb6a93bf",
+ "BOMRef": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9"
+ },
+ "Version": "1.5.8",
+ "Release": "3.el7",
+ "SrcName": "keyutils-libs",
+ "SrcVersion": "1.5.8",
+ "SrcRelease": "3.el7",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "krb5-libs@1.15.1-55.el7_9",
+ "Name": "krb5-libs",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9",
+ "UID": "4f23f9cf8fc8b67c",
+ "BOMRef": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#8cee64e9f2ddb592df8075ecb6489ed5727979b245606ae73dae382890f54ed5"
+ },
+ "Version": "1.15.1",
+ "Release": "55.el7_9",
+ "SrcName": "krb5-libs",
+ "SrcVersion": "1.15.1",
+ "SrcRelease": "55.el7_9",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "libacl1@2.3.2-2+b1",
+ "Name": "libacl1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "82548f6f7baf25f3"
+ },
+ "Version": "2.3.2",
+ "Release": "2+b1",
+ "Arch": "amd64",
+ "SrcName": "acl",
+ "SrcVersion": "2.3.2",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libacl.so.1.1.2302",
+ "/usr/share/doc/libacl1/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libacl1/changelog.Debian.gz",
+ "/usr/share/doc/libacl1/changelog.gz",
+ "/usr/share/doc/libacl1/copyright",
+ "/usr/share/lintian/overrides/libacl1"
+ ]
+ },
+ {
+ "ID": "libapt-pkg7.0@3.0.3",
+ "Name": "libapt-pkg7.0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "df08f16788e2e8a6"
+ },
+ "Version": "3.0.3",
+ "Arch": "amd64",
+ "SrcName": "apt",
+ "SrcVersion": "3.0.3",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "curl",
+ "BSD-3-Clause",
+ "MIT",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "APT Development Team \u003cdeity@lists.debian.org\u003e",
+ "DependsOn": [
+ "libbz2-1.0@1.0.8-6",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "liblz4-1@1.10.0-4",
+ "liblzma5@5.8.1-1+deb13u1",
+ "libssl3t64@3.5.6-1~deb13u2",
+ "libstdc++6@14.2.0-19",
+ "libsystemd0@257.13-1~deb13u1",
+ "libudev1@257.13-1~deb13u1",
+ "libxxhash0@0.8.3-2",
+ "libzstd1@1.5.7+dfsg-1",
+ "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libapt-pkg.so.7.0.0",
+ "/usr/share/doc/libapt-pkg7.0/NEWS.Debian.gz",
+ "/usr/share/doc/libapt-pkg7.0/changelog.gz",
+ "/usr/share/doc/libapt-pkg7.0/copyright",
+ "/usr/share/locale/ar/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/da/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/de/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/el/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/es/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/it/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/km/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/th/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/libapt-pkg7.0.mo"
+ ]
+ },
+ {
+ "ID": "libattr1@1:2.5.2-3",
+ "Name": "libattr1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "953f1d1395118b4b"
+ },
+ "Version": "2.5.2",
+ "Release": "3",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "attr",
+ "SrcVersion": "2.5.2",
+ "SrcRelease": "3",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libattr.so.1.1.2502",
+ "/usr/share/doc/libattr1/changelog.Debian.gz",
+ "/usr/share/doc/libattr1/changelog.gz",
+ "/usr/share/doc/libattr1/copyright",
+ "/usr/share/lintian/overrides/libattr1"
+ ]
+ },
+ {
+ "ID": "libaudit-common@1:4.0.2-2",
+ "Name": "libaudit-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "4845289e49197cbd"
+ },
+ "Version": "4.0.2",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "all",
+ "SrcName": "audit",
+ "SrcVersion": "4.0.2",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Laurent Bigonville \u003cbigon@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/libaudit-common/changelog.Debian.gz",
+ "/usr/share/doc/libaudit-common/changelog.gz",
+ "/usr/share/doc/libaudit-common/copyright",
+ "/usr/share/man/man5/libaudit.conf.5.gz"
+ ]
+ },
+ {
+ "ID": "libaudit1@1:4.0.2-2+b2",
+ "Name": "libaudit1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "c9ebadb6608e2305"
+ },
+ "Version": "4.0.2",
+ "Release": "2+b2",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "audit",
+ "SrcVersion": "4.0.2",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Laurent Bigonville \u003cbigon@debian.org\u003e",
+ "DependsOn": [
+ "libaudit-common@1:4.0.2-2",
+ "libc6@2.41-12+deb13u3",
+ "libcap-ng0@0.8.5-4+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libaudit.so.1.0.0",
+ "/usr/share/doc/libaudit1/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libaudit1/changelog.Debian.gz",
+ "/usr/share/doc/libaudit1/changelog.gz",
+ "/usr/share/doc/libaudit1/copyright"
+ ]
+ },
+ {
+ "ID": "libblkid1@2.41-5",
+ "Name": "libblkid1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c427952a98b1e3ee"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libblkid.so.1.1.0",
+ "/usr/share/doc/libblkid1/NEWS.Debian.gz",
+ "/usr/share/doc/libblkid1/changelog.Debian.gz",
+ "/usr/share/doc/libblkid1/changelog.gz",
+ "/usr/share/doc/libblkid1/copyright",
+ "/usr/share/lintian/overrides/libblkid1"
+ ]
+ },
+ {
+ "ID": "libbsd0@0.12.2-2",
+ "Name": "libbsd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "6a35c140077b4eb4"
+ },
+ "Version": "0.12.2",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libbsd",
+ "SrcVersion": "0.12.2",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-3-Clause",
+ "BSD-3-clause-Regents",
+ "BSD-2-Clause-NetBSD",
+ "BSD-3-clause-author",
+ "BSD-3-clause-John-Birrell",
+ "BSD-5-clause-Peter-Wemm",
+ "BSD-2-Clause",
+ "BSD-2-clause-verbatim",
+ "BSD-2-clause-author",
+ "ISC",
+ "ISC-Original",
+ "MIT",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libmd0@1.1.0-2+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libbsd.so.0.12.2",
+ "/usr/share/doc/libbsd0/changelog.Debian.gz",
+ "/usr/share/doc/libbsd0/changelog.gz",
+ "/usr/share/doc/libbsd0/copyright",
+ "/usr/share/lintian/overrides/libbsd0"
+ ]
+ },
+ {
+ "ID": "libbz2-1.0@1.0.8-6",
+ "Name": "libbz2-1.0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "395e7ab13e254394"
+ },
+ "Version": "1.0.8",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "bzip2",
+ "SrcVersion": "1.0.8",
+ "SrcRelease": "6",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Anibal Monsalve Salazar \u003canibal@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libbz2.so.1.0.4",
+ "/usr/share/doc/libbz2-1.0/changelog.Debian.gz",
+ "/usr/share/doc/libbz2-1.0/changelog.gz",
+ "/usr/share/doc/libbz2-1.0/copyright"
+ ]
+ },
+ {
+ "ID": "libc-bin@2.41-12+deb13u3",
+ "Name": "libc-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c17717cca0e61621"
+ },
+ "Version": "2.41",
+ "Release": "12+deb13u3",
+ "Arch": "amd64",
+ "SrcName": "glibc",
+ "SrcVersion": "2.41",
+ "SrcRelease": "12+deb13u3",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1+-with-link-exception",
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GPL-2+-with-link-exception",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "Carnegie",
+ "Inner-Net",
+ "MIT-like-Lord",
+ "BSD-like-Spencer",
+ "PCRE",
+ "BSD-3-clause-Carnegie",
+ "Unicode-DFS-2016",
+ "BSL-1.0",
+ "SunPro",
+ "CORE-MATH",
+ "BSD-3-clause-Berkeley",
+ "BSD-3-clause-WIDE",
+ "BSD-2-Clause",
+ "BSD-3-clause-Oracle",
+ "DEC",
+ "IBM",
+ "ISC",
+ "Univ-Coimbra",
+ "public-domain",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/getconf",
+ "/usr/bin/getent",
+ "/usr/bin/iconv",
+ "/usr/bin/ldd",
+ "/usr/bin/locale",
+ "/usr/bin/localedef",
+ "/usr/bin/pldd",
+ "/usr/bin/tzselect",
+ "/usr/bin/zdump",
+ "/usr/lib/locale/C.utf8/LC_ADDRESS",
+ "/usr/lib/locale/C.utf8/LC_COLLATE",
+ "/usr/lib/locale/C.utf8/LC_CTYPE",
+ "/usr/lib/locale/C.utf8/LC_IDENTIFICATION",
+ "/usr/lib/locale/C.utf8/LC_MEASUREMENT",
+ "/usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES",
+ "/usr/lib/locale/C.utf8/LC_MONETARY",
+ "/usr/lib/locale/C.utf8/LC_NAME",
+ "/usr/lib/locale/C.utf8/LC_NUMERIC",
+ "/usr/lib/locale/C.utf8/LC_PAPER",
+ "/usr/lib/locale/C.utf8/LC_TELEPHONE",
+ "/usr/lib/locale/C.utf8/LC_TIME",
+ "/usr/sbin/iconvconfig",
+ "/usr/sbin/ldconfig",
+ "/usr/sbin/zic",
+ "/usr/share/doc/libc-bin/changelog.Debian.gz",
+ "/usr/share/doc/libc-bin/changelog.gz",
+ "/usr/share/doc/libc-bin/copyright",
+ "/usr/share/libc-bin/nsswitch.conf",
+ "/usr/share/lintian/overrides/libc-bin",
+ "/usr/share/man/man1/getconf.1.gz",
+ "/usr/share/man/man1/tzselect.1.gz"
+ ]
+ },
+ {
+ "ID": "libc6@2.41-12+deb13u3",
+ "Name": "libc6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "19d151c4d1229080"
+ },
+ "Version": "2.41",
+ "Release": "12+deb13u3",
+ "Arch": "amd64",
+ "SrcName": "glibc",
+ "SrcVersion": "2.41",
+ "SrcRelease": "12+deb13u3",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1+-with-link-exception",
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GPL-2+-with-link-exception",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "Carnegie",
+ "Inner-Net",
+ "MIT-like-Lord",
+ "BSD-like-Spencer",
+ "PCRE",
+ "BSD-3-clause-Carnegie",
+ "Unicode-DFS-2016",
+ "BSL-1.0",
+ "SunPro",
+ "CORE-MATH",
+ "BSD-3-clause-Berkeley",
+ "BSD-3-clause-WIDE",
+ "BSD-2-Clause",
+ "BSD-3-clause-Oracle",
+ "DEC",
+ "IBM",
+ "ISC",
+ "Univ-Coimbra",
+ "public-domain",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libgcc-s1@14.2.0-19"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/gconv/ANSI_X3.110.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ARMSCII-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ASMO_449.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BIG5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BIG5HKSCS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BRF.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP10007.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1125.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1250.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1251.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1252.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1253.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1254.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1255.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1256.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1257.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1258.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP737.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP770.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP771.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP772.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP773.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP774.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP775.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP932.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CSN_369103.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CWI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/DEC-MCS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-CA-FR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-S.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IS-FRISS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-PT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-UK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-US.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ECMA-CYRILLIC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-CN.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JP-MS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JP.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-KR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-TW.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GB18030.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBBIG5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBGBK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-ACADEMY.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-PS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GOST_19768-74.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK-CCITT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK7-OLD.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-GREEK8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN9.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-THAI8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-TURKISH8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM037.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM038.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1004.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1008.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1008_420.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1025.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1026.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1046.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1047.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1097.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1112.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1122.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1123.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1124.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1129.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1130.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1132.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1133.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1137.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1140.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1141.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1142.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1143.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1144.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1145.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1146.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1147.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1148.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1149.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1153.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1154.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1155.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1156.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1157.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1158.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1160.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1161.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1162.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1163.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1164.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1166.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1167.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM12712.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1364.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1371.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1388.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1390.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1399.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM16804.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM256.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM273.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM274.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM275.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM277.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM278.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM280.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM281.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM284.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM285.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM290.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM297.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM420.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM423.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM424.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM437.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4517.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4899.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4909.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4971.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM500.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM5347.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM803.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM850.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM851.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM852.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM855.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM856.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM857.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM858.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM860.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM861.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM862.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM863.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM864.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM865.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM866.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM866NAV.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM868.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM869.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM870.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM871.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM874.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM875.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM880.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM891.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM901.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM902.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM903.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9030.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM904.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM905.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9066.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM918.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM921.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM922.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM930.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM932.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM933.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM935.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM937.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM939.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM943.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9448.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IEC_P27-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS-CYRILLIC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISIRI-3342.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN-EXT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP-3.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-KR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-IR-197.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-IR-209.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO646.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-10.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-11.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-13.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-14.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-15.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-16.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-3.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-4.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-6.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-9.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-9E.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_10367-BOX.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_11548-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_2033.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5427-EXT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5427.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5428.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_6937-2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_6937.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/JOHAB.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-R.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-RU.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-T.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-U.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-CENTRALEUROPE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-IS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-SAMI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-UK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MACINTOSH.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MIK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/NATS-DANO.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/NATS-SEFI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/PT154.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/RK1048.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SAMI-WS2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SHIFT_JISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SJIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/T.61.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TCVN5712-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TIS-620.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TSCII.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UHC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UNICODE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-16.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-32.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/VISCII.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.d/gconv-modules-extra.conf",
+ "/usr/lib/x86_64-linux-gnu/gconv/libCNS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libGB.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libISOIR165.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libJIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libJISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libKSC.so",
+ "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2",
+ "/usr/lib/x86_64-linux-gnu/libBrokenLocale.so.1",
+ "/usr/lib/x86_64-linux-gnu/libanl.so.1",
+ "/usr/lib/x86_64-linux-gnu/libc.so.6",
+ "/usr/lib/x86_64-linux-gnu/libc_malloc_debug.so.0",
+ "/usr/lib/x86_64-linux-gnu/libdl.so.2",
+ "/usr/lib/x86_64-linux-gnu/libm.so.6",
+ "/usr/lib/x86_64-linux-gnu/libmemusage.so",
+ "/usr/lib/x86_64-linux-gnu/libmvec.so.1",
+ "/usr/lib/x86_64-linux-gnu/libnsl.so.1",
+ "/usr/lib/x86_64-linux-gnu/libnss_compat.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_dns.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_files.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_hesiod.so.2",
+ "/usr/lib/x86_64-linux-gnu/libpcprofile.so",
+ "/usr/lib/x86_64-linux-gnu/libpthread.so.0",
+ "/usr/lib/x86_64-linux-gnu/libresolv.so.2",
+ "/usr/lib/x86_64-linux-gnu/librt.so.1",
+ "/usr/lib/x86_64-linux-gnu/libthread_db.so.1",
+ "/usr/lib/x86_64-linux-gnu/libutil.so.1",
+ "/usr/share/doc/libc6/NEWS.Debian.gz",
+ "/usr/share/doc/libc6/NEWS.gz",
+ "/usr/share/doc/libc6/README.Debian.gz",
+ "/usr/share/doc/libc6/README.hesiod.gz",
+ "/usr/share/doc/libc6/changelog.Debian.gz",
+ "/usr/share/doc/libc6/changelog.gz",
+ "/usr/share/doc/libc6/copyright",
+ "/usr/share/lintian/overrides/libc6"
+ ]
+ },
+ {
+ "ID": "libcap-ng0@0.8.5-4+b1",
+ "Name": "libcap-ng0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "853c3a4f587b1e09"
+ },
+ "Version": "0.8.5",
+ "Release": "4+b1",
+ "Arch": "amd64",
+ "SrcName": "libcap-ng",
+ "SrcVersion": "0.8.5",
+ "SrcRelease": "4",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "GPL-2.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Håvard F. Aasen \u003chavard.f.aasen@pfft.no\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcap-ng.so.0.0.0",
+ "/usr/lib/x86_64-linux-gnu/libdrop_ambient.so.0.0.0",
+ "/usr/share/doc/libcap-ng0/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libcap-ng0/changelog.Debian.gz",
+ "/usr/share/doc/libcap-ng0/changelog.gz",
+ "/usr/share/doc/libcap-ng0/copyright"
+ ]
+ },
+ {
+ "ID": "libcap2@1:2.75-10+deb13u1+b1",
+ "Name": "libcap2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "451a510e42b50c7c"
+ },
+ "Version": "2.75",
+ "Release": "10+deb13u1+b1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "libcap2",
+ "SrcVersion": "2.75",
+ "SrcRelease": "10+deb13u1",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Christian Kastner \u003cckk@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcap.so.2.75",
+ "/usr/lib/x86_64-linux-gnu/libpsx.so.2.75",
+ "/usr/share/doc/libcap2/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libcap2/changelog.Debian.gz",
+ "/usr/share/doc/libcap2/changelog.gz",
+ "/usr/share/doc/libcap2/copyright"
+ ]
+ },
+ {
+ "ID": "libcom_err@1.42.9-19.el7",
+ "Name": "libcom_err",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/libcom_err@1.42.9-19.el7",
+ "UID": "dd13ac5974bf1c3f",
+ "BOMRef": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce"
+ },
+ "Version": "1.42.9",
+ "Release": "19.el7",
+ "SrcName": "libcom_err",
+ "SrcVersion": "1.42.9",
+ "SrcRelease": "19.el7",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "libcrypt1@1:4.4.38-1",
+ "Name": "libcrypt1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "185d1b457ef399b8"
+ },
+ "Version": "4.4.38",
+ "Release": "1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "libxcrypt",
+ "SrcVersion": "4.4.38",
+ "SrcRelease": "1",
+ "SrcEpoch": 1,
+ "Maintainer": "Marco d'Itri \u003cmd@linux.it\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0",
+ "/usr/share/doc/libcrypt1/changelog.Debian.gz",
+ "/usr/share/doc/libcrypt1/changelog.gz",
+ "/usr/share/doc/libcrypt1/copyright"
+ ]
+ },
+ {
+ "ID": "libdb5.3t64@5.3.28+dfsg2-9",
+ "Name": "libdb5.3t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1d93101a053d025d"
+ },
+ "Version": "5.3.28+dfsg2",
+ "Release": "9",
+ "Arch": "amd64",
+ "SrcName": "db5.3",
+ "SrcVersion": "5.3.28+dfsg2",
+ "SrcRelease": "9",
+ "Licenses": [
+ "Sleepycat",
+ "BSD-3-Clause",
+ "MS-PL",
+ "GPL-2.0-or-later",
+ "Artistic-2.0",
+ "X11",
+ "MIT-old",
+ "TCL-like",
+ "BSD-3-clause-fjord",
+ "GPL-3.0-only",
+ "Zlib"
+ ],
+ "Maintainer": "Debian QA Group \u003cpackages@qa.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libdb-5.3.so",
+ "/usr/share/doc/libdb5.3t64/build_signature_amd64.txt",
+ "/usr/share/doc/libdb5.3t64/changelog.Debian.gz",
+ "/usr/share/doc/libdb5.3t64/copyright",
+ "/usr/share/lintian/overrides/libdb5.3t64"
+ ]
+ },
+ {
+ "ID": "libdebconfclient0@0.280",
+ "Name": "libdebconfclient0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f4d35c54ea8ebcdc"
+ },
+ "Version": "0.280",
+ "Arch": "amd64",
+ "SrcName": "cdebconf",
+ "SrcVersion": "0.280",
+ "Licenses": [
+ "BSD-2-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian Install System Team \u003cdebian-boot@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libdebconfclient.so.0.0.0",
+ "/usr/share/doc/libdebconfclient0/changelog.gz",
+ "/usr/share/doc/libdebconfclient0/copyright"
+ ]
+ },
+ {
+ "ID": "libffi8@3.4.8-2",
+ "Name": "libffi8",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d78c144a996938aa"
+ },
+ "Version": "3.4.8",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libffi",
+ "SrcVersion": "3.4.8",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT",
+ "X11",
+ "GPL-2.0-or-later",
+ "GPL-3.0-or-later",
+ "MPL-1.1",
+ "LGPL-2.1-or-later",
+ "public-domain"
+ ],
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libffi.so.8.1.4",
+ "/usr/share/doc/libffi8/changelog.Debian.gz",
+ "/usr/share/doc/libffi8/copyright"
+ ]
+ },
+ {
+ "ID": "libgcc-s1@14.2.0-19",
+ "Name": "libgcc-s1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a939ab1a9133b3fa"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "gcc-14-base@14.2.0-19",
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgcc_s.so.1",
+ "/usr/share/lintian/overrides/libgcc-s1"
+ ]
+ },
+ {
+ "ID": "libgdbm6t64@1.24-2",
+ "Name": "libgdbm6t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "79fdad8a6bd05b2d"
+ },
+ "Version": "1.24",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "gdbm",
+ "SrcVersion": "1.24",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GFDL-1.3-no-invariants-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Nicolas Mora \u003cbabelouest@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgdbm.so.6.0.0",
+ "/usr/share/doc/libgdbm6t64/changelog.Debian.gz",
+ "/usr/share/doc/libgdbm6t64/changelog.gz",
+ "/usr/share/doc/libgdbm6t64/copyright",
+ "/usr/share/lintian/overrides/libgdbm6t64"
+ ]
+ },
+ {
+ "ID": "libgmp10@2:6.3.0+dfsg-3",
+ "Name": "libgmp10",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64\u0026distro=debian-13.6\u0026epoch=2",
+ "UID": "8d1eefd06321d7f5"
+ },
+ "Version": "6.3.0+dfsg",
+ "Release": "3",
+ "Epoch": 2,
+ "Arch": "amd64",
+ "SrcName": "gmp",
+ "SrcVersion": "6.3.0+dfsg",
+ "SrcRelease": "3",
+ "SrcEpoch": 2,
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-or-later",
+ "GPL-3+ with Bison exception",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Debian Science Maintainers \u003cdebian-science-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgmp.so.10.5.0",
+ "/usr/share/doc/libgmp10/README.Debian",
+ "/usr/share/doc/libgmp10/changelog.Debian.gz",
+ "/usr/share/doc/libgmp10/changelog.gz",
+ "/usr/share/doc/libgmp10/copyright"
+ ]
+ },
+ {
+ "ID": "libhogweed6t64@3.10.1-1",
+ "Name": "libhogweed6t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8c7c2e41ab9a40c8"
+ },
+ "Version": "3.10.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "nettle",
+ "SrcVersion": "3.10.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "MIT",
+ "GPL-3.0-with-autoconf-exception+",
+ "public-domain",
+ "GPL-2.0-only",
+ "GAP"
+ ],
+ "Maintainer": "Magnus Holmgren \u003cholmgren@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libgmp10@2:6.3.0+dfsg-3",
+ "libnettle8t64@3.10.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libhogweed.so.6.10",
+ "/usr/share/doc/libhogweed6t64/changelog.Debian.gz",
+ "/usr/share/doc/libhogweed6t64/changelog.gz",
+ "/usr/share/doc/libhogweed6t64/copyright",
+ "/usr/share/lintian/overrides/libhogweed6t64"
+ ]
+ },
+ {
+ "ID": "liblastlog2-2@2.41-5",
+ "Name": "liblastlog2-2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d5ec9bb1797e1476"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libsqlite3-0@3.46.1-7+deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblastlog2.so.2.0.0",
+ "/usr/share/doc/liblastlog2-2/NEWS.Debian.gz",
+ "/usr/share/doc/liblastlog2-2/changelog.Debian.gz",
+ "/usr/share/doc/liblastlog2-2/changelog.gz",
+ "/usr/share/doc/liblastlog2-2/copyright"
+ ]
+ },
+ {
+ "ID": "liblz4-1@1.10.0-4",
+ "Name": "liblz4-1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d06629bc3067545a"
+ },
+ "Version": "1.10.0",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "lz4",
+ "SrcVersion": "1.10.0",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "BSD-2-Clause",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Nobuhiro Iwamatsu \u003ciwamatsu@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libxxhash0@0.8.3-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblz4.so.1.10.0",
+ "/usr/share/doc/liblz4-1/changelog.Debian.gz",
+ "/usr/share/doc/liblz4-1/copyright"
+ ]
+ },
+ {
+ "ID": "liblzma5@5.8.1-1+deb13u1",
+ "Name": "liblzma5",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "6bb07f060c067c08"
+ },
+ "Version": "5.8.1",
+ "Release": "1+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "xz-utils",
+ "SrcVersion": "5.8.1",
+ "SrcRelease": "1+deb13u1",
+ "Licenses": [
+ "0BSD",
+ "GPL-2.0-or-later",
+ "LGPL-2.1-or-later",
+ "FSFULLR",
+ "GPL-3.0-or-later-WITH-Autoconf-exception-macro",
+ "none",
+ "PD",
+ "permissive-nowarranty",
+ "FSFUL",
+ "noderivs",
+ "PD-debian",
+ "LGPL-2.1-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
+ ],
+ "Maintainer": "Sebastian Andrzej Siewior \u003csebastian@breakpoint.cc\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblzma.so.5.8.1",
+ "/usr/share/doc/liblzma5/AUTHORS",
+ "/usr/share/doc/liblzma5/NEWS.gz",
+ "/usr/share/doc/liblzma5/THANKS.gz",
+ "/usr/share/doc/liblzma5/changelog.Debian.gz",
+ "/usr/share/doc/liblzma5/changelog.gz",
+ "/usr/share/doc/liblzma5/copyright"
+ ]
+ },
+ {
+ "ID": "libmd0@1.1.0-2+b1",
+ "Name": "libmd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8f7242077c74e850"
+ },
+ "Version": "1.1.0",
+ "Release": "2+b1",
+ "Arch": "amd64",
+ "SrcName": "libmd",
+ "SrcVersion": "1.1.0",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-3-Clause",
+ "BSD-3-clause-Aaron-D-Gifford",
+ "BSD-2-Clause",
+ "BSD-2-Clause-NetBSD",
+ "ISC",
+ "Beerware",
+ "public-domain-md4",
+ "public-domain-md5",
+ "public-domain-sha1"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libmd.so.0.1.0",
+ "/usr/share/doc/libmd0/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libmd0/changelog.Debian.gz",
+ "/usr/share/doc/libmd0/changelog.gz",
+ "/usr/share/doc/libmd0/copyright"
+ ]
+ },
+ {
+ "ID": "libmount1@2.41-5",
+ "Name": "libmount1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libmount1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "e4ddbeb1b284f3ca"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libblkid1@2.41-5",
+ "libc6@2.41-12+deb13u3",
+ "libselinux1@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libmount.so.1.1.0",
+ "/usr/share/doc/libmount1/NEWS.Debian.gz",
+ "/usr/share/doc/libmount1/changelog.Debian.gz",
+ "/usr/share/doc/libmount1/changelog.gz",
+ "/usr/share/doc/libmount1/copyright",
+ "/usr/share/lintian/overrides/libmount1"
+ ]
+ },
+ {
+ "ID": "libncursesw6@6.5+20250216-2",
+ "Name": "libncursesw6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "fac6fddb91f7c21c"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libtinfo6@6.5+20250216-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libformw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libmenuw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libncursesw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libpanelw.so.6.5"
+ ]
+ },
+ {
+ "ID": "libnettle8t64@3.10.1-1",
+ "Name": "libnettle8t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3cd10b6383088c9"
+ },
+ "Version": "3.10.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "nettle",
+ "SrcVersion": "3.10.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "MIT",
+ "GPL-3.0-with-autoconf-exception+",
+ "public-domain",
+ "GPL-2.0-only",
+ "GAP"
+ ],
+ "Maintainer": "Magnus Holmgren \u003cholmgren@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libnettle.so.8.10",
+ "/usr/share/doc/libnettle8t64/NEWS.gz",
+ "/usr/share/doc/libnettle8t64/README",
+ "/usr/share/doc/libnettle8t64/changelog.Debian.gz",
+ "/usr/share/doc/libnettle8t64/changelog.gz",
+ "/usr/share/doc/libnettle8t64/copyright",
+ "/usr/share/lintian/overrides/libnettle8t64"
+ ]
+ },
+ {
+ "ID": "libpam-modules@1.7.0-5",
+ "Name": "libpam-modules",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "b9d6f9c66558c40d"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/security/pam_access.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_canonicalize_user.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_debug.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_deny.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_echo.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_env.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_exec.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_faildelay.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_faillock.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_filter.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_ftp.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_group.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_issue.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_keyinit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_limits.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_listfile.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_localuser.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_loginuid.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_mail.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_mkhomedir.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_motd.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_namespace.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_nologin.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_permit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_pwhistory.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_rhosts.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_rootok.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_securetty.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_selinux.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_sepermit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_setquota.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_shells.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_stress.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_succeed_if.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_time.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_timestamp.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_tty_audit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_umask.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_unix.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_userdb.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_usertype.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_warn.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_wheel.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_xauth.so",
+ "/usr/share/doc/libpam-modules/NEWS.Debian.gz",
+ "/usr/share/doc/libpam-modules/changelog.Debian.gz",
+ "/usr/share/doc/libpam-modules/changelog.gz",
+ "/usr/share/doc/libpam-modules/copyright",
+ "/usr/share/doc/libpam-modules/examples/upperLOWER.c",
+ "/usr/share/lintian/overrides/libpam-modules",
+ "/usr/share/pam-configs/mkhomedir"
+ ]
+ },
+ {
+ "ID": "libpam-modules-bin@1.7.0-5",
+ "Name": "libpam-modules-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f047dc4396624183"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam0g@1.7.0-5",
+ "libselinux1@3.8.1-1",
+ "libsystemd0@257.13-1~deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/systemd/system/pam_namespace.service",
+ "/usr/sbin/faillock",
+ "/usr/sbin/mkhomedir_helper",
+ "/usr/sbin/pam_namespace_helper",
+ "/usr/sbin/pam_timestamp_check",
+ "/usr/sbin/pwhistory_helper",
+ "/usr/sbin/unix_chkpwd",
+ "/usr/sbin/unix_update",
+ "/usr/share/doc/libpam-modules-bin/changelog.Debian.gz",
+ "/usr/share/doc/libpam-modules-bin/changelog.gz",
+ "/usr/share/doc/libpam-modules-bin/copyright",
+ "/usr/share/lintian/overrides/libpam-modules-bin"
+ ]
+ },
+ {
+ "ID": "libpam-runtime@1.7.0-5",
+ "Name": "libpam-runtime",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all\u0026distro=debian-13.6",
+ "UID": "2e8bd19930283d52"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "all",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "libpam-modules@1.7.0-5"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/pam-auth-update",
+ "/usr/sbin/pam_getenv",
+ "/usr/share/doc/libpam-runtime/changelog.Debian.gz",
+ "/usr/share/doc/libpam-runtime/changelog.gz",
+ "/usr/share/doc/libpam-runtime/copyright",
+ "/usr/share/lintian/overrides/libpam-runtime",
+ "/usr/share/locale/af/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/am/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ar/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/as/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/az/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/be/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bn_IN/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/da/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/de/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/de_CH/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/el/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/es/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/et/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fa/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/gu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/he/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ia/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/id/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/is/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/it/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/km/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kw_GB/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/lv/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ml/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/my/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/or/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/si/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sq/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sr@latin/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/te/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/tg/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/th/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ur/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/yo/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_HK/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/man/man5/access.conf.5.gz",
+ "/usr/share/man/man5/faillock.conf.5.gz",
+ "/usr/share/man/man5/group.conf.5.gz",
+ "/usr/share/man/man5/limits.conf.5.gz",
+ "/usr/share/man/man5/namespace.conf.5.gz",
+ "/usr/share/man/man5/pam.conf.5.gz",
+ "/usr/share/man/man5/pam_env.conf.5.gz",
+ "/usr/share/man/man5/pwhistory.conf.5.gz",
+ "/usr/share/man/man5/sepermit.conf.5.gz",
+ "/usr/share/man/man5/time.conf.5.gz",
+ "/usr/share/man/man7/PAM.7.gz",
+ "/usr/share/man/man8/faillock.8.gz",
+ "/usr/share/man/man8/mkhomedir_helper.8.gz",
+ "/usr/share/man/man8/pam-auth-update.8.gz",
+ "/usr/share/man/man8/pam_access.8.gz",
+ "/usr/share/man/man8/pam_canonicalize_user.8.gz",
+ "/usr/share/man/man8/pam_debug.8.gz",
+ "/usr/share/man/man8/pam_deny.8.gz",
+ "/usr/share/man/man8/pam_echo.8.gz",
+ "/usr/share/man/man8/pam_env.8.gz",
+ "/usr/share/man/man8/pam_exec.8.gz",
+ "/usr/share/man/man8/pam_faildelay.8.gz",
+ "/usr/share/man/man8/pam_faillock.8.gz",
+ "/usr/share/man/man8/pam_filter.8.gz",
+ "/usr/share/man/man8/pam_ftp.8.gz",
+ "/usr/share/man/man8/pam_getenv.8.gz",
+ "/usr/share/man/man8/pam_group.8.gz",
+ "/usr/share/man/man8/pam_issue.8.gz",
+ "/usr/share/man/man8/pam_keyinit.8.gz",
+ "/usr/share/man/man8/pam_limits.8.gz",
+ "/usr/share/man/man8/pam_listfile.8.gz",
+ "/usr/share/man/man8/pam_localuser.8.gz",
+ "/usr/share/man/man8/pam_loginuid.8.gz",
+ "/usr/share/man/man8/pam_mail.8.gz",
+ "/usr/share/man/man8/pam_mkhomedir.8.gz",
+ "/usr/share/man/man8/pam_motd.8.gz",
+ "/usr/share/man/man8/pam_namespace.8.gz",
+ "/usr/share/man/man8/pam_namespace_helper.8.gz",
+ "/usr/share/man/man8/pam_nologin.8.gz",
+ "/usr/share/man/man8/pam_permit.8.gz",
+ "/usr/share/man/man8/pam_pwhistory.8.gz",
+ "/usr/share/man/man8/pam_rhosts.8.gz",
+ "/usr/share/man/man8/pam_rootok.8.gz",
+ "/usr/share/man/man8/pam_securetty.8.gz",
+ "/usr/share/man/man8/pam_selinux.8.gz",
+ "/usr/share/man/man8/pam_sepermit.8.gz",
+ "/usr/share/man/man8/pam_setquota.8.gz",
+ "/usr/share/man/man8/pam_shells.8.gz",
+ "/usr/share/man/man8/pam_stress.8.gz",
+ "/usr/share/man/man8/pam_succeed_if.8.gz",
+ "/usr/share/man/man8/pam_time.8.gz",
+ "/usr/share/man/man8/pam_timestamp.8.gz",
+ "/usr/share/man/man8/pam_timestamp_check.8.gz",
+ "/usr/share/man/man8/pam_tty_audit.8.gz",
+ "/usr/share/man/man8/pam_umask.8.gz",
+ "/usr/share/man/man8/pam_unix.8.gz",
+ "/usr/share/man/man8/pam_userdb.8.gz",
+ "/usr/share/man/man8/pam_usertype.8.gz",
+ "/usr/share/man/man8/pam_warn.8.gz",
+ "/usr/share/man/man8/pam_wheel.8.gz",
+ "/usr/share/man/man8/pam_xauth.8.gz",
+ "/usr/share/man/man8/pwhistory_helper.8.gz",
+ "/usr/share/man/man8/unix_chkpwd.8.gz",
+ "/usr/share/man/man8/unix_update.8.gz",
+ "/usr/share/pam-configs/unix",
+ "/usr/share/pam/common-account",
+ "/usr/share/pam/common-account.md5sums",
+ "/usr/share/pam/common-auth",
+ "/usr/share/pam/common-auth.md5sums",
+ "/usr/share/pam/common-password",
+ "/usr/share/pam/common-password.md5sums",
+ "/usr/share/pam/common-session",
+ "/usr/share/pam/common-session-noninteractive",
+ "/usr/share/pam/common-session-noninteractive.md5sums",
+ "/usr/share/pam/common-session.md5sums"
+ ]
+ },
+ {
+ "ID": "libpam0g@1.7.0-5",
+ "Name": "libpam0g",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "5dbda12bb939f426"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libpam.so.0.85.1",
+ "/usr/lib/x86_64-linux-gnu/libpam_misc.so.0.82.1",
+ "/usr/lib/x86_64-linux-gnu/libpamc.so.0.82.1",
+ "/usr/share/doc/libpam0g/Debian-PAM-MiniPolicy.gz",
+ "/usr/share/doc/libpam0g/README",
+ "/usr/share/doc/libpam0g/README.Debian",
+ "/usr/share/doc/libpam0g/TODO.Debian",
+ "/usr/share/doc/libpam0g/changelog.Debian.gz",
+ "/usr/share/doc/libpam0g/changelog.gz",
+ "/usr/share/doc/libpam0g/copyright",
+ "/usr/share/lintian/overrides/libpam0g"
+ ]
+ },
+ {
+ "ID": "libpcre2-8-0@10.46-1~deb13u1",
+ "Name": "libpcre2-8-0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "cb52bbc65534e04d"
+ },
+ "Version": "10.46",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "pcre2",
+ "SrcVersion": "10.46",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "BSD-3-clause-Cambridge with BINARY LIBRARY-LIKE PACKAGES exception",
+ "BSD-3-Clause",
+ "X11",
+ "BSD-2-Clause",
+ "public-domain"
+ ],
+ "Maintainer": "Matthew Vernon \u003cmatthew@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libpcre2-8.so.0.14.0",
+ "/usr/share/doc/libpcre2-8-0/README.Debian",
+ "/usr/share/doc/libpcre2-8-0/changelog.Debian.gz",
+ "/usr/share/doc/libpcre2-8-0/changelog.gz",
+ "/usr/share/doc/libpcre2-8-0/copyright"
+ ]
+ },
+ {
+ "ID": "libreadline8t64@8.2-6",
+ "Name": "libreadline8t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3182860c74d6d08d"
+ },
+ "Version": "8.2",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "readline",
+ "SrcVersion": "8.2",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-or-later",
+ "ISC-no-attribution"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libtinfo6@6.5+20250216-2",
+ "readline-common@8.2-6"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libhistory.so.8.2",
+ "/usr/lib/x86_64-linux-gnu/libreadline.so.8.2",
+ "/usr/share/doc/libreadline8t64/README.Debian",
+ "/usr/share/doc/libreadline8t64/USAGE",
+ "/usr/share/doc/libreadline8t64/changelog.Debian.gz",
+ "/usr/share/doc/libreadline8t64/changelog.gz",
+ "/usr/share/doc/libreadline8t64/copyright",
+ "/usr/share/doc/libreadline8t64/examples/Inputrc",
+ "/usr/share/doc/libreadline8t64/inputrc.arrows"
+ ]
+ },
+ {
+ "ID": "libseccomp2@2.6.0-2",
+ "Name": "libseccomp2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "872fd916e9134574"
+ },
+ "Version": "2.6.0",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libseccomp",
+ "SrcVersion": "2.6.0",
+ "SrcRelease": "2",
+ "Licenses": [
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Kees Cook \u003ckees@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libseccomp.so.2.6.0",
+ "/usr/share/doc/libseccomp2/changelog.Debian.gz",
+ "/usr/share/doc/libseccomp2/changelog.gz",
+ "/usr/share/doc/libseccomp2/copyright"
+ ]
+ },
+ {
+ "ID": "libselinux@2.5-15.el7",
+ "Name": "libselinux",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/libselinux@2.5-15.el7",
+ "UID": "6e37f06bf3057b37",
+ "BOMRef": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed"
+ },
+ "Version": "2.5",
+ "Release": "15.el7",
+ "SrcName": "libselinux",
+ "SrcVersion": "2.5",
+ "SrcRelease": "15.el7",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "libselinux1@3.8.1-1",
+ "Name": "libselinux1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "dad36e826c972129"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libselinux",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "public-domain",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libpcre2-8-0@10.46-1~deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/tmpfiles.d/libselinux1.conf",
+ "/usr/lib/x86_64-linux-gnu/libselinux.so.1",
+ "/usr/share/doc/libselinux1/changelog.Debian.gz",
+ "/usr/share/doc/libselinux1/copyright"
+ ]
+ },
+ {
+ "ID": "libsemanage-common@3.8.1-1",
+ "Name": "libsemanage-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all\u0026distro=debian-13.6",
+ "UID": "82e27fcff653c8e2"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "all",
+ "SrcName": "libsemanage",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/libsemanage-common/changelog.Debian.gz",
+ "/usr/share/doc/libsemanage-common/copyright",
+ "/usr/share/man/man5/semanage.conf.5.gz"
+ ]
+ },
+ {
+ "ID": "libsemanage2@3.8.1-1",
+ "Name": "libsemanage2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "dc362d6ee87a25c7"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libsemanage",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libbz2-1.0@1.0.8-6",
+ "libc6@2.41-12+deb13u3",
+ "libselinux1@3.8.1-1",
+ "libsemanage-common@3.8.1-1",
+ "libsepol2@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsemanage.so.2",
+ "/usr/share/doc/libsemanage2/changelog.Debian.gz",
+ "/usr/share/doc/libsemanage2/copyright"
+ ]
+ },
+ {
+ "ID": "libsepol2@3.8.1-1",
+ "Name": "libsepol2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8a467f0e7ce023a5"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libsepol",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "Zlib",
+ "GPL-2.0-only",
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsepol.so.2",
+ "/usr/share/doc/libsepol2/changelog.Debian.gz",
+ "/usr/share/doc/libsepol2/copyright"
+ ]
+ },
+ {
+ "ID": "libsmartcols1@2.41-5",
+ "Name": "libsmartcols1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "4d10e734941c1d1d"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsmartcols.so.1.1.0",
+ "/usr/share/doc/libsmartcols1/NEWS.Debian.gz",
+ "/usr/share/doc/libsmartcols1/changelog.Debian.gz",
+ "/usr/share/doc/libsmartcols1/changelog.gz",
+ "/usr/share/doc/libsmartcols1/copyright",
+ "/usr/share/lintian/overrides/libsmartcols1"
+ ]
+ },
+ {
+ "ID": "libsqlite3-0@3.46.1-7+deb13u1",
+ "Name": "libsqlite3-0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "49853bfc5d923fa8"
+ },
+ "Version": "3.46.1",
+ "Release": "7+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "sqlite3",
+ "SrcVersion": "3.46.1",
+ "SrcRelease": "7+deb13u1",
+ "Licenses": [
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Laszlo Boszormenyi (GCS) \u003cgcs@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6",
+ "/usr/share/doc/libsqlite3-0/README.Debian",
+ "/usr/share/doc/libsqlite3-0/changelog.Debian.gz",
+ "/usr/share/doc/libsqlite3-0/changelog.gz",
+ "/usr/share/doc/libsqlite3-0/changelog.html.gz",
+ "/usr/share/doc/libsqlite3-0/copyright"
+ ]
+ },
+ {
+ "ID": "libssl3t64@3.5.6-1~deb13u2",
+ "Name": "libssl3t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1ca83fc0831fc12a"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libzstd1@1.5.7+dfsg-1",
+ "openssl-provider-legacy@3.5.6-1~deb13u2",
+ "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/engines-3/afalg.so",
+ "/usr/lib/x86_64-linux-gnu/engines-3/loader_attic.so",
+ "/usr/lib/x86_64-linux-gnu/engines-3/padlock.so",
+ "/usr/lib/x86_64-linux-gnu/libcrypto.so.3",
+ "/usr/lib/x86_64-linux-gnu/libssl.so.3",
+ "/usr/share/doc/libssl3t64/NEWS.Debian.gz",
+ "/usr/share/doc/libssl3t64/changelog.Debian.gz",
+ "/usr/share/doc/libssl3t64/changelog.gz",
+ "/usr/share/doc/libssl3t64/copyright",
+ "/usr/share/lintian/overrides/libssl3t64"
+ ]
+ },
+ {
+ "ID": "libstdc++6@14.2.0-19",
+ "Name": "libstdc++6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "44612415c1730efa"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "gcc-14-base@14.2.0-19",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33",
+ "/usr/share/gcc/python/libstdcxx/__init__.py",
+ "/usr/share/gcc/python/libstdcxx/v6/__init__.py",
+ "/usr/share/gcc/python/libstdcxx/v6/printers.py",
+ "/usr/share/gcc/python/libstdcxx/v6/xmethods.py",
+ "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33-gdb.py"
+ ]
+ },
+ {
+ "ID": "libsystemd0@257.13-1~deb13u1",
+ "Name": "libsystemd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d7f6e0bcc5fd6683"
+ },
+ "Version": "257.13",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "systemd",
+ "SrcVersion": "257.13",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "CC0-1.0",
+ "GPL-2 with Linux-syscall-note exception",
+ "MIT",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libcap2@1:2.75-10+deb13u1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsystemd.so.0.40.0",
+ "/usr/share/doc/libsystemd0/NEWS.Debian.gz",
+ "/usr/share/doc/libsystemd0/changelog.Debian.gz",
+ "/usr/share/doc/libsystemd0/copyright"
+ ]
+ },
+ {
+ "ID": "libtinfo6@6.5+20250216-2",
+ "Name": "libtinfo6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "12095a35cca3541c"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libtic.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libtinfo.so.6.5",
+ "/usr/share/doc/libtinfo6/changelog.Debian.gz",
+ "/usr/share/doc/libtinfo6/changelog.gz",
+ "/usr/share/doc/libtinfo6/copyright"
+ ]
+ },
+ {
+ "ID": "libudev1@257.13-1~deb13u1",
+ "Name": "libudev1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "151b8b6a80baf5ce"
+ },
+ "Version": "257.13",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "systemd",
+ "SrcVersion": "257.13",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "CC0-1.0",
+ "GPL-2 with Linux-syscall-note exception",
+ "MIT",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libcap2@1:2.75-10+deb13u1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libudev.so.1.7.10",
+ "/usr/share/doc/libudev1/NEWS.Debian.gz",
+ "/usr/share/doc/libudev1/changelog.Debian.gz",
+ "/usr/share/doc/libudev1/copyright"
+ ]
+ },
+ {
+ "ID": "libuuid1@2.41-5",
+ "Name": "libuuid1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "ad45ef419bdcd798"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libuuid.so.1.3.0",
+ "/usr/share/doc/libuuid1/NEWS.Debian.gz",
+ "/usr/share/doc/libuuid1/changelog.Debian.gz",
+ "/usr/share/doc/libuuid1/changelog.gz",
+ "/usr/share/doc/libuuid1/copyright"
+ ]
+ },
+ {
+ "ID": "libxxhash0@0.8.3-2",
+ "Name": "libxxhash0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "413b9b44940ce169"
+ },
+ "Version": "0.8.3",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "xxhash",
+ "SrcVersion": "0.8.3",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-2-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Josue Ortega \u003cjosue@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libxxhash.so.0.8.3",
+ "/usr/share/doc/libxxhash0/changelog.Debian.gz",
+ "/usr/share/doc/libxxhash0/changelog.gz",
+ "/usr/share/doc/libxxhash0/copyright"
+ ]
+ },
+ {
+ "ID": "libzstd1@1.5.7+dfsg-1",
+ "Name": "libzstd1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "7262601866572971"
+ },
+ "Version": "1.5.7+dfsg",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libzstd",
+ "SrcVersion": "1.5.7+dfsg",
+ "SrcRelease": "1",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "Zlib",
+ "MIT"
+ ],
+ "Maintainer": "RPM packaging team \u003cteam+pkg-rpm@tracker.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libzstd.so.1.5.7",
+ "/usr/share/doc/libzstd1/changelog.Debian.gz",
+ "/usr/share/doc/libzstd1/changelog.gz",
+ "/usr/share/doc/libzstd1/copyright"
+ ]
+ },
+ {
+ "ID": "login@1:4.16.0-2+really2.41-5",
+ "Name": "login",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "468f3d4a374ef1"
+ },
+ "Version": "4.16.0-2+really2.41",
+ "Release": "5",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam-modules@1.7.0-5",
+ "libpam-runtime@1.7.0-5",
+ "libpam0g@1.7.0-5"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/login",
+ "/usr/bin/newgrp",
+ "/usr/sbin/nologin",
+ "/usr/share/bash-completion/completions/newgrp",
+ "/usr/share/doc/login/NEWS.Debian.gz",
+ "/usr/share/doc/login/changelog.Debian.gz",
+ "/usr/share/doc/login/changelog.gz",
+ "/usr/share/doc/login/copyright",
+ "/usr/share/lintian/overrides/login",
+ "/usr/share/man/de/man1/login.1.gz",
+ "/usr/share/man/de/man8/nologin.8.gz",
+ "/usr/share/man/fr/man1/login.1.gz",
+ "/usr/share/man/man1/login.1.gz",
+ "/usr/share/man/man1/newgrp.1.gz",
+ "/usr/share/man/man8/nologin.8.gz",
+ "/usr/share/man/pl/man1/login.1.gz",
+ "/usr/share/man/pl/man1/newgrp.1.gz",
+ "/usr/share/man/pl/man8/nologin.8.gz",
+ "/usr/share/man/ro/man1/login.1.gz",
+ "/usr/share/man/ro/man1/newgrp.1.gz",
+ "/usr/share/man/ro/man8/nologin.8.gz",
+ "/usr/share/man/sr/man1/login.1.gz",
+ "/usr/share/man/sr/man8/nologin.8.gz",
+ "/usr/share/man/uk/man1/login.1.gz",
+ "/usr/share/man/uk/man1/newgrp.1.gz",
+ "/usr/share/man/uk/man8/nologin.8.gz"
+ ]
+ },
+ {
+ "ID": "login.defs@1:4.17.4-2",
+ "Name": "login.defs",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/login.defs@4.17.4-2?arch=all\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "b2ebc9108569350a"
+ },
+ "Version": "4.17.4",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "all",
+ "SrcName": "shadow",
+ "SrcVersion": "4.17.4",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-1.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/login.defs/NEWS.Debian.gz",
+ "/usr/share/doc/login.defs/changelog.Debian.gz",
+ "/usr/share/doc/login.defs/changelog.gz",
+ "/usr/share/doc/login.defs/copyright",
+ "/usr/share/man/de/man5/login.defs.5.gz",
+ "/usr/share/man/fr/man5/login.defs.5.gz",
+ "/usr/share/man/it/man5/login.defs.5.gz",
+ "/usr/share/man/ja/man5/login.defs.5.gz",
+ "/usr/share/man/man5/login.defs.5.gz",
+ "/usr/share/man/ru/man5/login.defs.5.gz",
+ "/usr/share/man/uk/man5/login.defs.5.gz",
+ "/usr/share/man/zh_CN/man5/login.defs.5.gz"
+ ]
+ },
+ {
+ "ID": "mawk@1.3.4.20250131-1",
+ "Name": "mawk",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "9048a1b0d5acbb7e"
+ },
+ "Version": "1.3.4.20250131",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "mawk",
+ "SrcVersion": "1.3.4.20250131",
+ "SrcRelease": "1",
+ "Licenses": [
+ "GPL-2.0-only",
+ "X11",
+ "CC-BY-3.0"
+ ],
+ "Maintainer": "Boyuan Yang \u003cbyang@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/mawk",
+ "/usr/share/doc/mawk/ACKNOWLEDGMENT",
+ "/usr/share/doc/mawk/README",
+ "/usr/share/doc/mawk/changelog.Debian.gz",
+ "/usr/share/doc/mawk/changelog.gz",
+ "/usr/share/doc/mawk/copyright",
+ "/usr/share/doc/mawk/examples/ct_length.awk",
+ "/usr/share/doc/mawk/examples/decl.awk",
+ "/usr/share/doc/mawk/examples/deps.awk",
+ "/usr/share/doc/mawk/examples/eatc.awk",
+ "/usr/share/doc/mawk/examples/gdecl.awk",
+ "/usr/share/doc/mawk/examples/hcal",
+ "/usr/share/doc/mawk/examples/hical",
+ "/usr/share/doc/mawk/examples/nocomment.awk",
+ "/usr/share/doc/mawk/examples/primes.awk",
+ "/usr/share/doc/mawk/examples/qsort.awk",
+ "/usr/share/man/man1/mawk.1.gz",
+ "/usr/share/man/man7/mawk-arrays.7.gz",
+ "/usr/share/man/man7/mawk-code.7.gz"
+ ]
+ },
+ {
+ "ID": "mount@2.41-5",
+ "Name": "mount",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/mount@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c6fdc5cf989db569"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/mount",
+ "/usr/bin/umount",
+ "/usr/sbin/losetup",
+ "/usr/sbin/swapoff",
+ "/usr/sbin/swapon",
+ "/usr/share/bash-completion/completions/losetup",
+ "/usr/share/bash-completion/completions/mount",
+ "/usr/share/bash-completion/completions/swapoff",
+ "/usr/share/bash-completion/completions/swapon",
+ "/usr/share/bash-completion/completions/umount",
+ "/usr/share/doc/mount/NEWS.Debian.gz",
+ "/usr/share/doc/mount/changelog.Debian.gz",
+ "/usr/share/doc/mount/changelog.gz",
+ "/usr/share/doc/mount/copyright",
+ "/usr/share/doc/mount/examples/filesystems",
+ "/usr/share/doc/mount/examples/fstab",
+ "/usr/share/doc/mount/examples/mount.fstab",
+ "/usr/share/doc/mount/mount.txt",
+ "/usr/share/lintian/overrides/mount",
+ "/usr/share/man/man5/fstab.5.gz",
+ "/usr/share/man/man8/losetup.8.gz",
+ "/usr/share/man/man8/mount.8.gz",
+ "/usr/share/man/man8/swapon.8.gz",
+ "/usr/share/man/man8/umount.8.gz"
+ ]
+ },
+ {
+ "ID": "ncurses-base@6.5+20250216-2",
+ "Name": "ncurses-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all\u0026distro=debian-13.6",
+ "UID": "76a1fb5936f344dc"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "all",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/ncurses-base/FAQ",
+ "/usr/share/doc/ncurses-base/TODO.Debian",
+ "/usr/share/doc/ncurses-base/changelog.Debian.gz",
+ "/usr/share/doc/ncurses-base/changelog.gz",
+ "/usr/share/doc/ncurses-base/copyright",
+ "/usr/share/lintian/overrides/ncurses-base",
+ "/usr/share/tabset/std",
+ "/usr/share/tabset/stdcrt",
+ "/usr/share/tabset/vt100",
+ "/usr/share/tabset/vt300",
+ "/usr/share/terminfo/E/Eterm",
+ "/usr/share/terminfo/a/ansi",
+ "/usr/share/terminfo/c/cons25",
+ "/usr/share/terminfo/c/cygwin",
+ "/usr/share/terminfo/d/dumb",
+ "/usr/share/terminfo/h/hurd",
+ "/usr/share/terminfo/l/linux",
+ "/usr/share/terminfo/m/mach",
+ "/usr/share/terminfo/m/mach-bold",
+ "/usr/share/terminfo/m/mach-color",
+ "/usr/share/terminfo/m/mach-gnu",
+ "/usr/share/terminfo/m/mach-gnu-color",
+ "/usr/share/terminfo/p/pcansi",
+ "/usr/share/terminfo/r/rxvt",
+ "/usr/share/terminfo/r/rxvt-basic",
+ "/usr/share/terminfo/r/rxvt-unicode",
+ "/usr/share/terminfo/r/rxvt-unicode-256color",
+ "/usr/share/terminfo/s/screen",
+ "/usr/share/terminfo/s/screen-256color",
+ "/usr/share/terminfo/s/screen-256color-bce",
+ "/usr/share/terminfo/s/screen-bce",
+ "/usr/share/terminfo/s/screen-s",
+ "/usr/share/terminfo/s/screen-w",
+ "/usr/share/terminfo/s/screen.xterm-256color",
+ "/usr/share/terminfo/s/sun",
+ "/usr/share/terminfo/t/tmux",
+ "/usr/share/terminfo/t/tmux-256color",
+ "/usr/share/terminfo/v/vt100",
+ "/usr/share/terminfo/v/vt102",
+ "/usr/share/terminfo/v/vt220",
+ "/usr/share/terminfo/v/vt52",
+ "/usr/share/terminfo/w/wsvt25",
+ "/usr/share/terminfo/w/wsvt25m",
+ "/usr/share/terminfo/x/xterm",
+ "/usr/share/terminfo/x/xterm-256color",
+ "/usr/share/terminfo/x/xterm-color",
+ "/usr/share/terminfo/x/xterm-mono",
+ "/usr/share/terminfo/x/xterm-r5",
+ "/usr/share/terminfo/x/xterm-r6",
+ "/usr/share/terminfo/x/xterm-vt220",
+ "/usr/share/terminfo/x/xterm-xfree86"
+ ]
+ },
+ {
+ "ID": "ncurses-bin@6.5+20250216-2",
+ "Name": "ncurses-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d03e89ad6a7a5243"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/clear",
+ "/usr/bin/infocmp",
+ "/usr/bin/tabs",
+ "/usr/bin/tic",
+ "/usr/bin/toe",
+ "/usr/bin/tput",
+ "/usr/bin/tset",
+ "/usr/share/doc/ncurses-bin/changelog.Debian.gz",
+ "/usr/share/doc/ncurses-bin/changelog.gz",
+ "/usr/share/doc/ncurses-bin/copyright",
+ "/usr/share/man/man1/captoinfo.1.gz",
+ "/usr/share/man/man1/clear.1.gz",
+ "/usr/share/man/man1/infocmp.1.gz",
+ "/usr/share/man/man1/infotocap.1.gz",
+ "/usr/share/man/man1/tabs.1.gz",
+ "/usr/share/man/man1/tic.1.gz",
+ "/usr/share/man/man1/toe.1.gz",
+ "/usr/share/man/man1/tput.1.gz",
+ "/usr/share/man/man1/tset.1.gz",
+ "/usr/share/man/man5/scr_dump.5.gz",
+ "/usr/share/man/man5/term.5.gz",
+ "/usr/share/man/man5/terminfo.5.gz",
+ "/usr/share/man/man5/user_caps.5.gz",
+ "/usr/share/man/man7/term.7.gz"
+ ]
+ },
+ {
+ "ID": "netbase@6.5",
+ "Name": "netbase",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/netbase@6.5?arch=all\u0026distro=debian-13.6",
+ "UID": "b9a2c240e75fe15e"
+ },
+ "Version": "6.5",
+ "Arch": "all",
+ "SrcName": "netbase",
+ "SrcVersion": "6.5",
+ "Licenses": [
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Marco d'Itri \u003cmd@linux.it\u003e",
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/netbase/changelog.gz",
+ "/usr/share/doc/netbase/copyright"
+ ]
+ },
+ {
+ "ID": "openssl@3.5.6-1~deb13u2",
+ "Name": "openssl",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8f9e5d7117307079"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libssl3t64@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/bin/c_rehash",
+ "/usr/bin/openssl",
+ "/usr/lib/ssl/misc/CA.pl",
+ "/usr/lib/ssl/misc/tsget.pl",
+ "/usr/share/doc/openssl/HOWTO/certificates.txt.gz",
+ "/usr/share/doc/openssl/HOWTO/documenting-functions-and-macros.md.gz",
+ "/usr/share/doc/openssl/HOWTO/keys.txt.gz",
+ "/usr/share/doc/openssl/NEWS.md.gz",
+ "/usr/share/doc/openssl/README-ENGINES.md.gz",
+ "/usr/share/doc/openssl/README-PROVIDERS.md.gz",
+ "/usr/share/doc/openssl/README-QUIC.md.gz",
+ "/usr/share/doc/openssl/README.Debian",
+ "/usr/share/doc/openssl/README.md.gz",
+ "/usr/share/doc/openssl/changelog.Debian.gz",
+ "/usr/share/doc/openssl/changelog.gz",
+ "/usr/share/doc/openssl/copyright",
+ "/usr/share/doc/openssl/fingerprints.txt",
+ "/usr/share/lintian/overrides/openssl",
+ "/usr/share/man/man1/CA.pl.1ssl.gz",
+ "/usr/share/man/man1/openssl-asn1parse.1ssl.gz",
+ "/usr/share/man/man1/openssl-ca.1ssl.gz",
+ "/usr/share/man/man1/openssl-ciphers.1ssl.gz",
+ "/usr/share/man/man1/openssl-cmds.1ssl.gz",
+ "/usr/share/man/man1/openssl-cmp.1ssl.gz",
+ "/usr/share/man/man1/openssl-cms.1ssl.gz",
+ "/usr/share/man/man1/openssl-crl.1ssl.gz",
+ "/usr/share/man/man1/openssl-crl2pkcs7.1ssl.gz",
+ "/usr/share/man/man1/openssl-dgst.1ssl.gz",
+ "/usr/share/man/man1/openssl-dhparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-dsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-dsaparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-ec.1ssl.gz",
+ "/usr/share/man/man1/openssl-ecparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-enc.1ssl.gz",
+ "/usr/share/man/man1/openssl-engine.1ssl.gz",
+ "/usr/share/man/man1/openssl-errstr.1ssl.gz",
+ "/usr/share/man/man1/openssl-fipsinstall.1ssl.gz",
+ "/usr/share/man/man1/openssl-format-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-gendsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-genpkey.1ssl.gz",
+ "/usr/share/man/man1/openssl-genrsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-info.1ssl.gz",
+ "/usr/share/man/man1/openssl-kdf.1ssl.gz",
+ "/usr/share/man/man1/openssl-list.1ssl.gz",
+ "/usr/share/man/man1/openssl-mac.1ssl.gz",
+ "/usr/share/man/man1/openssl-namedisplay-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-nseq.1ssl.gz",
+ "/usr/share/man/man1/openssl-ocsp.1ssl.gz",
+ "/usr/share/man/man1/openssl-passphrase-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-passwd.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs12.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs7.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs8.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkey.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkeyparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkeyutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-prime.1ssl.gz",
+ "/usr/share/man/man1/openssl-rand.1ssl.gz",
+ "/usr/share/man/man1/openssl-rehash.1ssl.gz",
+ "/usr/share/man/man1/openssl-req.1ssl.gz",
+ "/usr/share/man/man1/openssl-rsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-rsautl.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_client.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_server.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_time.1ssl.gz",
+ "/usr/share/man/man1/openssl-sess_id.1ssl.gz",
+ "/usr/share/man/man1/openssl-skeyutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-smime.1ssl.gz",
+ "/usr/share/man/man1/openssl-speed.1ssl.gz",
+ "/usr/share/man/man1/openssl-spkac.1ssl.gz",
+ "/usr/share/man/man1/openssl-srp.1ssl.gz",
+ "/usr/share/man/man1/openssl-storeutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-ts.1ssl.gz",
+ "/usr/share/man/man1/openssl-verification-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-verify.1ssl.gz",
+ "/usr/share/man/man1/openssl-version.1ssl.gz",
+ "/usr/share/man/man1/openssl-x509.1ssl.gz",
+ "/usr/share/man/man1/openssl.1ssl.gz",
+ "/usr/share/man/man1/tsget.1ssl.gz",
+ "/usr/share/man/man5/config.5ssl.gz",
+ "/usr/share/man/man5/fips_config.5ssl.gz",
+ "/usr/share/man/man5/x509v3_config.5ssl.gz",
+ "/usr/share/man/man7/EVP_ASYM_CIPHER-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_ASYM_CIPHER-SM2.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-AES.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-ARIA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-BLOWFISH.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CAMELLIA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CAST.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CHACHA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-DES.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-IDEA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-NULL.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC2.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC4.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC5.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-SEED.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-SM4.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-ARGON2.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-HKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-HMAC-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-KB.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-KRB5KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PBKDF1.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PBKDF2.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PKCS12KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PVKKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SCRYPT.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SS.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SSHKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-TLS13_KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-TLS1_PRF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X942-ASN1.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X942-CONCAT.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X963.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-EC.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-ML-KEM.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-DH.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-ECDH.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-BLAKE2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-CMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-GMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-KMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-Poly1305.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-Siphash.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-BLAKE2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-KECCAK.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD4.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD5-SHA1.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD5.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MDC2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-NULL.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-RIPEMD160.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA1.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA3.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHAKE.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SM3.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-WHIRLPOOL.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-common.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-DH.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-EC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-FFC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-ML-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-ML-KEM.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-SLH-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-SM2.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-CRNG-TEST.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-CTR-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-HASH-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-HMAC-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-JITTER.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-SEED-SRC.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-TEST-RAND.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ECDSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ED25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ML-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-SLH-DSA.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-FIPS.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-base.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-default.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-legacy.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-null.7ssl.gz",
+ "/usr/share/man/man7/OSSL_STORE-winstore.7ssl.gz",
+ "/usr/share/man/man7/RAND.7ssl.gz",
+ "/usr/share/man/man7/RSA-PSS.7ssl.gz",
+ "/usr/share/man/man7/X25519.7ssl.gz",
+ "/usr/share/man/man7/bio.7ssl.gz",
+ "/usr/share/man/man7/ct.7ssl.gz",
+ "/usr/share/man/man7/des_modes.7ssl.gz",
+ "/usr/share/man/man7/evp.7ssl.gz",
+ "/usr/share/man/man7/fips_module.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-cipher.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-digest.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-kdf.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-mac.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-pkey.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-rand.7ssl.gz",
+ "/usr/share/man/man7/openssl-core.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-core_dispatch.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-core_names.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-env.7ssl.gz",
+ "/usr/share/man/man7/openssl-glossary.7ssl.gz",
+ "/usr/share/man/man7/openssl-qlog.7ssl.gz",
+ "/usr/share/man/man7/openssl-quic-concurrency.7ssl.gz",
+ "/usr/share/man/man7/openssl-quic.7ssl.gz",
+ "/usr/share/man/man7/openssl-threads.7ssl.gz",
+ "/usr/share/man/man7/openssl_user_macros.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libcrypto-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libraries-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libssl-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-migration.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-client-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-client-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-multi-stream.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-server-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-server-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-client-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-client-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-server-block.7ssl.gz",
+ "/usr/share/man/man7/ossl_store-file.7ssl.gz",
+ "/usr/share/man/man7/ossl_store.7ssl.gz",
+ "/usr/share/man/man7/passphrase-encoding.7ssl.gz",
+ "/usr/share/man/man7/property.7ssl.gz",
+ "/usr/share/man/man7/provider-asym_cipher.7ssl.gz",
+ "/usr/share/man/man7/provider-base.7ssl.gz",
+ "/usr/share/man/man7/provider-cipher.7ssl.gz",
+ "/usr/share/man/man7/provider-decoder.7ssl.gz",
+ "/usr/share/man/man7/provider-digest.7ssl.gz",
+ "/usr/share/man/man7/provider-encoder.7ssl.gz",
+ "/usr/share/man/man7/provider-kdf.7ssl.gz",
+ "/usr/share/man/man7/provider-kem.7ssl.gz",
+ "/usr/share/man/man7/provider-keyexch.7ssl.gz",
+ "/usr/share/man/man7/provider-keymgmt.7ssl.gz",
+ "/usr/share/man/man7/provider-mac.7ssl.gz",
+ "/usr/share/man/man7/provider-object.7ssl.gz",
+ "/usr/share/man/man7/provider-rand.7ssl.gz",
+ "/usr/share/man/man7/provider-signature.7ssl.gz",
+ "/usr/share/man/man7/provider-skeymgmt.7ssl.gz",
+ "/usr/share/man/man7/provider-storemgmt.7ssl.gz",
+ "/usr/share/man/man7/provider.7ssl.gz",
+ "/usr/share/man/man7/proxy-certificates.7ssl.gz",
+ "/usr/share/man/man7/x509.7ssl.gz"
+ ]
+ },
+ {
+ "ID": "openssl-provider-legacy@3.5.6-1~deb13u2",
+ "Name": "openssl-provider-legacy",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f40d953a73d33d41"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libssl3t64@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/ossl-modules/legacy.so",
+ "/usr/share/doc/openssl-provider-legacy/changelog.Debian.gz",
+ "/usr/share/doc/openssl-provider-legacy/changelog.gz",
+ "/usr/share/doc/openssl-provider-legacy/copyright"
+ ]
+ },
+ {
+ "ID": "passwd@1:4.17.4-2",
+ "Name": "passwd",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "5c48c1fc5bd92522"
+ },
+ "Version": "4.17.4",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "shadow",
+ "SrcVersion": "4.17.4",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-1.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "base-passwd@3.6.7",
+ "libacl1@2.3.2-2+b1",
+ "libattr1@1:2.5.2-3",
+ "libaudit1@1:4.0.2-2+b2",
+ "libbsd0@0.12.2-2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam-modules@1.7.0-5",
+ "libpam0g@1.7.0-5",
+ "libselinux1@3.8.1-1",
+ "libsemanage2@3.8.1-1",
+ "login.defs@1:4.17.4-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/chage",
+ "/usr/bin/chfn",
+ "/usr/bin/chsh",
+ "/usr/bin/expiry",
+ "/usr/bin/gpasswd",
+ "/usr/bin/passwd",
+ "/usr/lib/tmpfiles.d/passwd.conf",
+ "/usr/sbin/chgpasswd",
+ "/usr/sbin/chpasswd",
+ "/usr/sbin/groupadd",
+ "/usr/sbin/groupdel",
+ "/usr/sbin/groupmod",
+ "/usr/sbin/grpck",
+ "/usr/sbin/grpconv",
+ "/usr/sbin/grpunconv",
+ "/usr/sbin/newusers",
+ "/usr/sbin/pwck",
+ "/usr/sbin/pwconv",
+ "/usr/sbin/pwunconv",
+ "/usr/sbin/shadowconfig",
+ "/usr/sbin/useradd",
+ "/usr/sbin/userdel",
+ "/usr/sbin/usermod",
+ "/usr/sbin/vipw",
+ "/usr/share/doc/passwd/NEWS.Debian.gz",
+ "/usr/share/doc/passwd/README.Debian",
+ "/usr/share/doc/passwd/TODO.Debian",
+ "/usr/share/doc/passwd/changelog.Debian.gz",
+ "/usr/share/doc/passwd/changelog.gz",
+ "/usr/share/doc/passwd/copyright",
+ "/usr/share/doc/passwd/examples/passwd.expire.cron",
+ "/usr/share/lintian/overrides/passwd",
+ "/usr/share/locale/bs/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/da/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/de/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/el/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/es/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/he/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/id/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/it/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/km/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sq/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/shadow.mo",
+ "/usr/share/man/cs/man1/expiry.1.gz",
+ "/usr/share/man/cs/man1/gpasswd.1.gz",
+ "/usr/share/man/cs/man5/gshadow.5.gz",
+ "/usr/share/man/cs/man5/passwd.5.gz",
+ "/usr/share/man/cs/man5/shadow.5.gz",
+ "/usr/share/man/cs/man8/groupadd.8.gz",
+ "/usr/share/man/cs/man8/groupdel.8.gz",
+ "/usr/share/man/cs/man8/groupmod.8.gz",
+ "/usr/share/man/cs/man8/grpck.8.gz",
+ "/usr/share/man/cs/man8/vipw.8.gz",
+ "/usr/share/man/da/man1/chfn.1.gz",
+ "/usr/share/man/da/man5/gshadow.5.gz",
+ "/usr/share/man/da/man8/groupdel.8.gz",
+ "/usr/share/man/da/man8/vipw.8.gz",
+ "/usr/share/man/de/man1/chage.1.gz",
+ "/usr/share/man/de/man1/chfn.1.gz",
+ "/usr/share/man/de/man1/chsh.1.gz",
+ "/usr/share/man/de/man1/expiry.1.gz",
+ "/usr/share/man/de/man1/gpasswd.1.gz",
+ "/usr/share/man/de/man1/passwd.1.gz",
+ "/usr/share/man/de/man5/gshadow.5.gz",
+ "/usr/share/man/de/man5/passwd.5.gz",
+ "/usr/share/man/de/man5/shadow.5.gz",
+ "/usr/share/man/de/man8/chgpasswd.8.gz",
+ "/usr/share/man/de/man8/chpasswd.8.gz",
+ "/usr/share/man/de/man8/groupadd.8.gz",
+ "/usr/share/man/de/man8/groupdel.8.gz",
+ "/usr/share/man/de/man8/groupmod.8.gz",
+ "/usr/share/man/de/man8/grpck.8.gz",
+ "/usr/share/man/de/man8/newusers.8.gz",
+ "/usr/share/man/de/man8/pwck.8.gz",
+ "/usr/share/man/de/man8/pwconv.8.gz",
+ "/usr/share/man/de/man8/useradd.8.gz",
+ "/usr/share/man/de/man8/userdel.8.gz",
+ "/usr/share/man/de/man8/usermod.8.gz",
+ "/usr/share/man/de/man8/vipw.8.gz",
+ "/usr/share/man/fi/man1/chfn.1.gz",
+ "/usr/share/man/fi/man1/chsh.1.gz",
+ "/usr/share/man/fr/man1/chage.1.gz",
+ "/usr/share/man/fr/man1/chfn.1.gz",
+ "/usr/share/man/fr/man1/chsh.1.gz",
+ "/usr/share/man/fr/man1/expiry.1.gz",
+ "/usr/share/man/fr/man1/gpasswd.1.gz",
+ "/usr/share/man/fr/man1/passwd.1.gz",
+ "/usr/share/man/fr/man5/gshadow.5.gz",
+ "/usr/share/man/fr/man5/passwd.5.gz",
+ "/usr/share/man/fr/man5/shadow.5.gz",
+ "/usr/share/man/fr/man5/subgid.5.gz",
+ "/usr/share/man/fr/man5/subuid.5.gz",
+ "/usr/share/man/fr/man8/chgpasswd.8.gz",
+ "/usr/share/man/fr/man8/chpasswd.8.gz",
+ "/usr/share/man/fr/man8/groupadd.8.gz",
+ "/usr/share/man/fr/man8/groupdel.8.gz",
+ "/usr/share/man/fr/man8/groupmod.8.gz",
+ "/usr/share/man/fr/man8/grpck.8.gz",
+ "/usr/share/man/fr/man8/newusers.8.gz",
+ "/usr/share/man/fr/man8/pwck.8.gz",
+ "/usr/share/man/fr/man8/pwconv.8.gz",
+ "/usr/share/man/fr/man8/useradd.8.gz",
+ "/usr/share/man/fr/man8/userdel.8.gz",
+ "/usr/share/man/fr/man8/usermod.8.gz",
+ "/usr/share/man/fr/man8/vipw.8.gz",
+ "/usr/share/man/hu/man1/chsh.1.gz",
+ "/usr/share/man/hu/man1/gpasswd.1.gz",
+ "/usr/share/man/hu/man1/passwd.1.gz",
+ "/usr/share/man/hu/man5/passwd.5.gz",
+ "/usr/share/man/id/man1/chsh.1.gz",
+ "/usr/share/man/id/man8/useradd.8.gz",
+ "/usr/share/man/it/man1/chage.1.gz",
+ "/usr/share/man/it/man1/chfn.1.gz",
+ "/usr/share/man/it/man1/chsh.1.gz",
+ "/usr/share/man/it/man1/expiry.1.gz",
+ "/usr/share/man/it/man1/gpasswd.1.gz",
+ "/usr/share/man/it/man1/passwd.1.gz",
+ "/usr/share/man/it/man5/gshadow.5.gz",
+ "/usr/share/man/it/man5/passwd.5.gz",
+ "/usr/share/man/it/man5/shadow.5.gz",
+ "/usr/share/man/it/man8/chgpasswd.8.gz",
+ "/usr/share/man/it/man8/chpasswd.8.gz",
+ "/usr/share/man/it/man8/groupadd.8.gz",
+ "/usr/share/man/it/man8/groupdel.8.gz",
+ "/usr/share/man/it/man8/groupmod.8.gz",
+ "/usr/share/man/it/man8/grpck.8.gz",
+ "/usr/share/man/it/man8/newusers.8.gz",
+ "/usr/share/man/it/man8/pwck.8.gz",
+ "/usr/share/man/it/man8/pwconv.8.gz",
+ "/usr/share/man/it/man8/useradd.8.gz",
+ "/usr/share/man/it/man8/userdel.8.gz",
+ "/usr/share/man/it/man8/usermod.8.gz",
+ "/usr/share/man/it/man8/vipw.8.gz",
+ "/usr/share/man/ja/man1/chage.1.gz",
+ "/usr/share/man/ja/man1/chfn.1.gz",
+ "/usr/share/man/ja/man1/chsh.1.gz",
+ "/usr/share/man/ja/man1/expiry.1.gz",
+ "/usr/share/man/ja/man1/gpasswd.1.gz",
+ "/usr/share/man/ja/man1/passwd.1.gz",
+ "/usr/share/man/ja/man5/passwd.5.gz",
+ "/usr/share/man/ja/man5/shadow.5.gz",
+ "/usr/share/man/ja/man8/chpasswd.8.gz",
+ "/usr/share/man/ja/man8/groupadd.8.gz",
+ "/usr/share/man/ja/man8/groupdel.8.gz",
+ "/usr/share/man/ja/man8/groupmod.8.gz",
+ "/usr/share/man/ja/man8/grpck.8.gz",
+ "/usr/share/man/ja/man8/newusers.8.gz",
+ "/usr/share/man/ja/man8/pwck.8.gz",
+ "/usr/share/man/ja/man8/pwconv.8.gz",
+ "/usr/share/man/ja/man8/useradd.8.gz",
+ "/usr/share/man/ja/man8/userdel.8.gz",
+ "/usr/share/man/ja/man8/usermod.8.gz",
+ "/usr/share/man/ja/man8/vipw.8.gz",
+ "/usr/share/man/ko/man1/chfn.1.gz",
+ "/usr/share/man/ko/man1/chsh.1.gz",
+ "/usr/share/man/ko/man5/passwd.5.gz",
+ "/usr/share/man/ko/man8/vipw.8.gz",
+ "/usr/share/man/man1/chage.1.gz",
+ "/usr/share/man/man1/chfn.1.gz",
+ "/usr/share/man/man1/chsh.1.gz",
+ "/usr/share/man/man1/expiry.1.gz",
+ "/usr/share/man/man1/gpasswd.1.gz",
+ "/usr/share/man/man1/passwd.1.gz",
+ "/usr/share/man/man5/gshadow.5.gz",
+ "/usr/share/man/man5/passwd.5.gz",
+ "/usr/share/man/man5/shadow.5.gz",
+ "/usr/share/man/man5/subgid.5.gz",
+ "/usr/share/man/man5/subuid.5.gz",
+ "/usr/share/man/man8/chgpasswd.8.gz",
+ "/usr/share/man/man8/chpasswd.8.gz",
+ "/usr/share/man/man8/groupadd.8.gz",
+ "/usr/share/man/man8/groupdel.8.gz",
+ "/usr/share/man/man8/groupmod.8.gz",
+ "/usr/share/man/man8/grpck.8.gz",
+ "/usr/share/man/man8/newusers.8.gz",
+ "/usr/share/man/man8/pwck.8.gz",
+ "/usr/share/man/man8/pwconv.8.gz",
+ "/usr/share/man/man8/shadowconfig.8.gz",
+ "/usr/share/man/man8/useradd.8.gz",
+ "/usr/share/man/man8/userdel.8.gz",
+ "/usr/share/man/man8/usermod.8.gz",
+ "/usr/share/man/man8/vipw.8.gz",
+ "/usr/share/man/pl/man1/chage.1.gz",
+ "/usr/share/man/pl/man1/chsh.1.gz",
+ "/usr/share/man/pl/man1/expiry.1.gz",
+ "/usr/share/man/pl/man8/groupadd.8.gz",
+ "/usr/share/man/pl/man8/groupdel.8.gz",
+ "/usr/share/man/pl/man8/groupmod.8.gz",
+ "/usr/share/man/pl/man8/grpck.8.gz",
+ "/usr/share/man/pl/man8/userdel.8.gz",
+ "/usr/share/man/pl/man8/usermod.8.gz",
+ "/usr/share/man/pl/man8/vipw.8.gz",
+ "/usr/share/man/pt_BR/man1/gpasswd.1.gz",
+ "/usr/share/man/pt_BR/man5/passwd.5.gz",
+ "/usr/share/man/pt_BR/man5/shadow.5.gz",
+ "/usr/share/man/pt_BR/man8/groupadd.8.gz",
+ "/usr/share/man/pt_BR/man8/groupdel.8.gz",
+ "/usr/share/man/pt_BR/man8/groupmod.8.gz",
+ "/usr/share/man/ru/man1/chage.1.gz",
+ "/usr/share/man/ru/man1/chfn.1.gz",
+ "/usr/share/man/ru/man1/chsh.1.gz",
+ "/usr/share/man/ru/man1/expiry.1.gz",
+ "/usr/share/man/ru/man1/gpasswd.1.gz",
+ "/usr/share/man/ru/man1/passwd.1.gz",
+ "/usr/share/man/ru/man5/gshadow.5.gz",
+ "/usr/share/man/ru/man5/passwd.5.gz",
+ "/usr/share/man/ru/man5/shadow.5.gz",
+ "/usr/share/man/ru/man8/chgpasswd.8.gz",
+ "/usr/share/man/ru/man8/chpasswd.8.gz",
+ "/usr/share/man/ru/man8/groupadd.8.gz",
+ "/usr/share/man/ru/man8/groupdel.8.gz",
+ "/usr/share/man/ru/man8/groupmod.8.gz",
+ "/usr/share/man/ru/man8/grpck.8.gz",
+ "/usr/share/man/ru/man8/newusers.8.gz",
+ "/usr/share/man/ru/man8/pwck.8.gz",
+ "/usr/share/man/ru/man8/pwconv.8.gz",
+ "/usr/share/man/ru/man8/useradd.8.gz",
+ "/usr/share/man/ru/man8/userdel.8.gz",
+ "/usr/share/man/ru/man8/usermod.8.gz",
+ "/usr/share/man/ru/man8/vipw.8.gz",
+ "/usr/share/man/sv/man1/chage.1.gz",
+ "/usr/share/man/sv/man1/chsh.1.gz",
+ "/usr/share/man/sv/man1/expiry.1.gz",
+ "/usr/share/man/sv/man1/passwd.1.gz",
+ "/usr/share/man/sv/man5/gshadow.5.gz",
+ "/usr/share/man/sv/man5/passwd.5.gz",
+ "/usr/share/man/sv/man8/groupadd.8.gz",
+ "/usr/share/man/sv/man8/groupdel.8.gz",
+ "/usr/share/man/sv/man8/groupmod.8.gz",
+ "/usr/share/man/sv/man8/grpck.8.gz",
+ "/usr/share/man/sv/man8/pwck.8.gz",
+ "/usr/share/man/sv/man8/userdel.8.gz",
+ "/usr/share/man/sv/man8/vipw.8.gz",
+ "/usr/share/man/tr/man1/chage.1.gz",
+ "/usr/share/man/tr/man1/chfn.1.gz",
+ "/usr/share/man/tr/man1/passwd.1.gz",
+ "/usr/share/man/tr/man5/passwd.5.gz",
+ "/usr/share/man/tr/man5/shadow.5.gz",
+ "/usr/share/man/tr/man8/groupadd.8.gz",
+ "/usr/share/man/tr/man8/groupdel.8.gz",
+ "/usr/share/man/tr/man8/groupmod.8.gz",
+ "/usr/share/man/tr/man8/useradd.8.gz",
+ "/usr/share/man/tr/man8/userdel.8.gz",
+ "/usr/share/man/tr/man8/usermod.8.gz",
+ "/usr/share/man/uk/man1/chage.1.gz",
+ "/usr/share/man/uk/man1/chfn.1.gz",
+ "/usr/share/man/uk/man1/chsh.1.gz",
+ "/usr/share/man/uk/man1/expiry.1.gz",
+ "/usr/share/man/uk/man1/gpasswd.1.gz",
+ "/usr/share/man/uk/man1/passwd.1.gz",
+ "/usr/share/man/uk/man5/gshadow.5.gz",
+ "/usr/share/man/uk/man5/passwd.5.gz",
+ "/usr/share/man/uk/man5/shadow.5.gz",
+ "/usr/share/man/uk/man8/chgpasswd.8.gz",
+ "/usr/share/man/uk/man8/chpasswd.8.gz",
+ "/usr/share/man/uk/man8/groupadd.8.gz",
+ "/usr/share/man/uk/man8/groupdel.8.gz",
+ "/usr/share/man/uk/man8/groupmod.8.gz",
+ "/usr/share/man/uk/man8/grpck.8.gz",
+ "/usr/share/man/uk/man8/newusers.8.gz",
+ "/usr/share/man/uk/man8/pwck.8.gz",
+ "/usr/share/man/uk/man8/pwconv.8.gz",
+ "/usr/share/man/uk/man8/useradd.8.gz",
+ "/usr/share/man/uk/man8/userdel.8.gz",
+ "/usr/share/man/uk/man8/usermod.8.gz",
+ "/usr/share/man/uk/man8/vipw.8.gz",
+ "/usr/share/man/zh_CN/man1/chage.1.gz",
+ "/usr/share/man/zh_CN/man1/chfn.1.gz",
+ "/usr/share/man/zh_CN/man1/chsh.1.gz",
+ "/usr/share/man/zh_CN/man1/expiry.1.gz",
+ "/usr/share/man/zh_CN/man1/gpasswd.1.gz",
+ "/usr/share/man/zh_CN/man1/passwd.1.gz",
+ "/usr/share/man/zh_CN/man5/gshadow.5.gz",
+ "/usr/share/man/zh_CN/man5/passwd.5.gz",
+ "/usr/share/man/zh_CN/man5/shadow.5.gz",
+ "/usr/share/man/zh_CN/man8/chgpasswd.8.gz",
+ "/usr/share/man/zh_CN/man8/chpasswd.8.gz",
+ "/usr/share/man/zh_CN/man8/groupadd.8.gz",
+ "/usr/share/man/zh_CN/man8/groupdel.8.gz",
+ "/usr/share/man/zh_CN/man8/groupmod.8.gz",
+ "/usr/share/man/zh_CN/man8/grpck.8.gz",
+ "/usr/share/man/zh_CN/man8/newusers.8.gz",
+ "/usr/share/man/zh_CN/man8/pwck.8.gz",
+ "/usr/share/man/zh_CN/man8/pwconv.8.gz",
+ "/usr/share/man/zh_CN/man8/useradd.8.gz",
+ "/usr/share/man/zh_CN/man8/userdel.8.gz",
+ "/usr/share/man/zh_CN/man8/usermod.8.gz",
+ "/usr/share/man/zh_CN/man8/vipw.8.gz",
+ "/usr/share/man/zh_TW/man1/chfn.1.gz",
+ "/usr/share/man/zh_TW/man1/chsh.1.gz",
+ "/usr/share/man/zh_TW/man5/passwd.5.gz",
+ "/usr/share/man/zh_TW/man8/chpasswd.8.gz",
+ "/usr/share/man/zh_TW/man8/groupadd.8.gz",
+ "/usr/share/man/zh_TW/man8/groupdel.8.gz",
+ "/usr/share/man/zh_TW/man8/groupmod.8.gz",
+ "/usr/share/man/zh_TW/man8/useradd.8.gz",
+ "/usr/share/man/zh_TW/man8/userdel.8.gz",
+ "/usr/share/man/zh_TW/man8/usermod.8.gz"
+ ]
+ },
+ {
+ "ID": "pcre@8.32-17.el7",
+ "Name": "pcre",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/pcre@8.32-17.el7",
+ "UID": "bb3e738eb75d1a13",
+ "BOMRef": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72"
+ },
+ "Version": "8.32",
+ "Release": "17.el7",
+ "SrcName": "pcre",
+ "SrcVersion": "8.32",
+ "SrcRelease": "17.el7",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "perl-base@5.40.1-6",
+ "Name": "perl-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "17f06da2c02a11c6"
+ },
+ "Version": "5.40.1",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "perl",
+ "SrcVersion": "5.40.1",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-1.0-or-later",
+ "Artistic-2.0",
+ "MIT",
+ "REGCOMP",
+ "GPL-2.0-with-bison-exception+",
+ "Unicode",
+ "BZIP",
+ "Zlib",
+ "GPL-2.0-or-later",
+ "FSFAP",
+ "BSD-3-clause-with-weird-numbering",
+ "CC0-1.0",
+ "TEXT-TABS",
+ "BSD-4-clause-POWERDOG",
+ "BSD-3-clause-GENERIC",
+ "BSD-3-Clause",
+ "SDBM-PUBLIC-DOMAIN",
+ "DONT-CHANGE-THE-GPL",
+ "Artistic-dist",
+ "LGPL-2.1-only",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "Artistic-2"
+ ],
+ "Maintainer": "Niko Tyni \u003cntyni@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/perl",
+ "/usr/bin/perl5.40.1",
+ "/usr/lib/x86_64-linux-gnu/perl-base/AutoLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Carp.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Carp/Heavy.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config_git.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config_heavy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Cwd.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/DynaLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Errno.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Exporter.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Exporter/Heavy.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Fcntl.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Basename.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Glob.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Path.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Spec.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Spec/Unix.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Temp.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/FileHandle.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Getopt/Long.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Getopt/Long/Parser.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Hash/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/File.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Handle.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Pipe.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Seekable.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/INET.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/IP.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/UNIX.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IPC/Open2.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IPC/Open3.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/List/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/POSIX.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Scalar/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/SelectSaver.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Socket.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Symbol.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/ParseWords.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/Tabs.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/Wrap.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Tie/Hash.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/XSLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/attributes.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Cwd/Cwd.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Fcntl/Fcntl.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/File/Glob/Glob.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Hash/Util/Util.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/IO/IO.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/List/Util/Util.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/POSIX/POSIX.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Socket/Socket.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/attributes/attributes.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/re/re.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/base.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/builtin.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/bytes.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/constant.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/feature.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/fields.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/integer.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/lib.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/locale.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/overload.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/overloading.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/parent.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/re.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/strict.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Age.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bmg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Cf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Ea.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/EqUIdeo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/GCB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Gc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Hst.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Identif2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Identifi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InPC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InSC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Isc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFCQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFDQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCCF.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKDQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Na1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NameAlia.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nv.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/PerlDeci.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/SB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Sc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Scx.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Tc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Uc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Vo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/WB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlLB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlSCX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V100.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V11.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V110.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V120.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V130.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V140.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V150.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V20.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V30.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V31.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V32.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V40.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V41.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V50.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V51.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V52.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V60.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V61.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V70.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V80.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V90.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Alpha/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/B.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/BN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/CS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/EN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ES.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ET.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/NSM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ON.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/WS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Blk/NB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/O.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CE/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CI/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCF/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWKCF/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWL/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWT/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWU/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Cased/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/A.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/AR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/ATAR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/B.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/BR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/DB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NK.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/OV.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/VR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CompEx/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/DI/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dash/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dep/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dia/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Com.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Enc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Fin.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Font.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Init.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Iso.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Med.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nar.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/NonCanon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sqr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sub.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sup.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Vert.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EBase/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EComp/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EPres/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/A.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/H.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/Na.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/W.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Emoji/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ext/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/ExtPict/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/CN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LV.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LVT.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/PP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/SM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/LC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ll.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/M.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Me.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/No.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/P.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pe.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Po.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ps.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/S.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sk.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/So.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Z.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Zs.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrBase/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrExt/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hex/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hst/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hyphen/T.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdStatus/Allowed.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdStatus/Restrict.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/DefaultI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Exclusio.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Inclusio.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/LimitedU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotChara.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotNFKC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotXID.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Obsolete.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Recommen.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Technica.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Uncommon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ideo/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/10_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/11_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/12_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/12_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/13_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/14_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/15_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/7_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/8_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/9_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Bottom.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/BottomAn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Left.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/LeftAndR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Overstru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Right.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Top.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndBo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndL2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndLe.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndRi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/VisualOr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Avagraha.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Bindu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Cantilla.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona5.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona7.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona9.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consonan.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Geminati.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Invisibl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Nukta.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Number.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Other.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/PureKill.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Syllable.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/ToneMark.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Virama.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Visarga.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Vowel.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelDep.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelInd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Ain.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Alef.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Beh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Dal.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/FarsiYeh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Feh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Gaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Hah.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/HanifiRo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Kaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Lam.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/NoJoinin.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Noon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Qaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Reh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Sad.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Seen.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Tah.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Waw.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Yeh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/D.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/T.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/U.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CJ.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/GL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/ID.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/NS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/OP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/QU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/SA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lower/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Math/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/M.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Di.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/None.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Nu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/100.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/100000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/11.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/12.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/13.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/14.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/15.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/17.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/18.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/19.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/20.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/200.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/20000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/30.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/300.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/30000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3_16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3_4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/40.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/400.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/4000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/40000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/500.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/60.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/600.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/6000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/60000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/7.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/70.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/700.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/7000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/70000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/80.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/800.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/8000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/80000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/9.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/90.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/900.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/9000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/90000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PCM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PatSyn/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Alnum.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Assigned.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Blank.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Graph.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PerlWord.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PosixPun.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Print.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/SpacePer.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Title.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Word.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/XPosixPu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlAny.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCh2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCha.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlFol.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIsI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlNch.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPat.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPr2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPro.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlQuo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/QMark/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/AT.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/CL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/FO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LE.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/SC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/ST.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/Sp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/UP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SD/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/STerm/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Arab.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Beng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cprt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cyrl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Deva.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Dupl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Geor.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Glag.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gonm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gran.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Grek.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gujr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Guru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Han.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hira.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Kana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Knda.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Latn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Limb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Linb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mlym.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mult.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Orya.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Sinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Syrc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Taml.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Telu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zyyy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Adlm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Arab.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Armn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Beng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Bhks.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Bopo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cakm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cham.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Copt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cprt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cyrl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Deva.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Diak.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Dupl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Ethi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Geor.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Glag.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gonm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gran.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Grek.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gujr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Guru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Han.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hebr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hira.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hmng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hmnp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Kana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khar.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khmr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khoj.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Knda.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Kthi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lao.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Latn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Limb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lina.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Linb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mlym.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mult.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mymr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Nand.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Nko.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Orya.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Phlp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Rohg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Shrd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sind.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Syrc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tagb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Takr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Talu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Taml.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Telu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Thaa.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tibt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tirh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Vith.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Xsux.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Yezi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Yi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zyyy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zzzz.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Term/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/UIdeo/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Upper/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/VS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/Tr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/Tu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/U.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/Extend.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/FO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/HL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/KA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/LE.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/ML.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/WSegSpac.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/utf8.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/vars.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/warnings.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/warnings/register.pm",
+ "/usr/share/doc/perl-base/changelog.Debian.gz",
+ "/usr/share/doc/perl-base/changelog.gz",
+ "/usr/share/doc/perl-base/copyright",
+ "/usr/share/doc/perl/AUTHORS.gz",
+ "/usr/share/doc/perl/Documentation",
+ "/usr/share/lintian/overrides/perl-base",
+ "/usr/share/man/man1/perl.1.gz"
+ ]
+ },
+ {
+ "ID": "readline-common@8.2-6",
+ "Name": "readline-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/readline-common@8.2-6?arch=all\u0026distro=debian-13.6",
+ "UID": "7f5f4bcfd1669a46"
+ },
+ "Version": "8.2",
+ "Release": "6",
+ "Arch": "all",
+ "SrcName": "readline",
+ "SrcVersion": "8.2",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-or-later",
+ "ISC-no-attribution"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/readline-common/changelog.Debian.gz",
+ "/usr/share/doc/readline-common/changelog.gz",
+ "/usr/share/doc/readline-common/copyright",
+ "/usr/share/doc/readline-common/inputrc.arrows",
+ "/usr/share/info/rluserman.info.gz",
+ "/usr/share/lintian/overrides/readline-common",
+ "/usr/share/man/man3/history.3readline.gz",
+ "/usr/share/man/man3/readline.3readline.gz",
+ "/usr/share/readline/inputrc"
+ ]
+ },
+ {
+ "ID": "sed@4.9-2+deb13u1",
+ "Name": "sed",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d9e2231b96ca2bda"
+ },
+ "Version": "4.9",
+ "Release": "2+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "sed",
+ "SrcVersion": "4.9",
+ "SrcRelease": "2+deb13u1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "X11",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-only",
+ "ISC",
+ "BSD-4-Clause-UC",
+ "BSL-1",
+ "pcre"
+ ],
+ "Maintainer": "Clint Adams \u003cclint@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/sed",
+ "/usr/share/doc/sed/AUTHORS",
+ "/usr/share/doc/sed/BUGS.gz",
+ "/usr/share/doc/sed/NEWS.gz",
+ "/usr/share/doc/sed/README",
+ "/usr/share/doc/sed/THANKS.gz",
+ "/usr/share/doc/sed/changelog.Debian.gz",
+ "/usr/share/doc/sed/changelog.gz",
+ "/usr/share/doc/sed/copyright",
+ "/usr/share/doc/sed/examples/dc.sed",
+ "/usr/share/doc/sed/sedfaq.txt.gz",
+ "/usr/share/info/sed.info.gz",
+ "/usr/share/locale/af/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/da/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/de/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/el/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/es/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/et/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/he/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/id/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/it/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/sed.mo",
+ "/usr/share/man/man1/sed.1.gz"
+ ]
+ },
+ {
+ "ID": "sqv@1.3.0-3+b2",
+ "Name": "sqv",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "82c65dd56fbcfd0e"
+ },
+ "Version": "1.3.0",
+ "Release": "3+b2",
+ "Arch": "amd64",
+ "SrcName": "rust-sequoia-sqv",
+ "SrcVersion": "1.3.0",
+ "SrcRelease": "3",
+ "Licenses": [
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only"
+ ],
+ "Maintainer": "Debian Rust Maintainers \u003cpkg-rust-maintainers@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "libgmp10@2:6.3.0+dfsg-3",
+ "libhogweed6t64@3.10.1-1",
+ "libnettle8t64@3.10.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/sqv",
+ "/usr/share/bash-completion/completions/sqv.bash",
+ "/usr/share/doc/sqv/NEWS.gz",
+ "/usr/share/doc/sqv/changelog.Debian.amd64.gz",
+ "/usr/share/doc/sqv/changelog.Debian.gz",
+ "/usr/share/doc/sqv/copyright",
+ "/usr/share/fish/completions/sqv.fish",
+ "/usr/share/man/man1/sqv.1.gz",
+ "/usr/share/zsh/vendor-completions/_sqv"
+ ]
+ },
+ {
+ "ID": "sysvinit-utils@3.14-4",
+ "Name": "sysvinit-utils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8699daa05d734d69"
+ },
+ "Version": "3.14",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "sysvinit",
+ "SrcVersion": "3.14",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "LGPL-2.1-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian sysvinit maintainers \u003cdebian-init-diversity@chiark.greenend.org.uk\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/init/init-d-script",
+ "/usr/lib/init/vars.sh",
+ "/usr/lib/lsb/init-functions",
+ "/usr/lib/lsb/init-functions.d/00-verbose",
+ "/usr/sbin/fstab-decode",
+ "/usr/sbin/killall5",
+ "/usr/share/doc/sysvinit-utils/changelog.Debian.gz",
+ "/usr/share/doc/sysvinit-utils/copyright",
+ "/usr/share/man/man5/init-d-script.5.gz",
+ "/usr/share/man/man8/fstab-decode.8.gz",
+ "/usr/share/man/man8/killall5.8.gz",
+ "/usr/share/man/man8/pidof.8.gz"
+ ]
+ },
+ {
+ "ID": "tar@1.35+dfsg-3.1",
+ "Name": "tar",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "50aee76d081ea925"
+ },
+ "Version": "1.35+dfsg",
+ "Release": "3.1",
+ "Arch": "amd64",
+ "SrcName": "tar",
+ "SrcVersion": "1.35+dfsg",
+ "SrcRelease": "3.1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "LGPL-3.0-or-later",
+ "LGPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Janos Lenart \u003cocsi@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/tar",
+ "/usr/lib/mime/packages/tar",
+ "/usr/sbin/rmt-tar",
+ "/usr/sbin/tarcat",
+ "/usr/share/doc/tar/AUTHORS",
+ "/usr/share/doc/tar/NEWS.gz",
+ "/usr/share/doc/tar/README.Debian",
+ "/usr/share/doc/tar/THANKS.gz",
+ "/usr/share/doc/tar/changelog.1.gz",
+ "/usr/share/doc/tar/changelog.Debian.gz",
+ "/usr/share/doc/tar/changelog.gz",
+ "/usr/share/doc/tar/copyright",
+ "/usr/share/locale/bg/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/da/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/de/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/el/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/es/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/et/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/id/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/it/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/tar.mo",
+ "/usr/share/man/man1/tar.1.gz",
+ "/usr/share/man/man1/tarcat.1.gz",
+ "/usr/share/man/man8/rmt-tar.8.gz"
+ ]
+ },
+ {
+ "ID": "tzdata@2026b-0+deb13u1",
+ "Name": "tzdata",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all\u0026distro=debian-13.6",
+ "UID": "6698e2883de2f799"
+ },
+ "Version": "2026b",
+ "Release": "0+deb13u1",
+ "Arch": "all",
+ "SrcName": "tzdata",
+ "SrcVersion": "2026b",
+ "SrcRelease": "0+deb13u1",
+ "Licenses": [
+ "public-domain"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/tzdata/NEWS.Debian.gz",
+ "/usr/share/doc/tzdata/README.Debian",
+ "/usr/share/doc/tzdata/changelog.Debian.gz",
+ "/usr/share/doc/tzdata/changelog.gz",
+ "/usr/share/doc/tzdata/copyright",
+ "/usr/share/lintian/overrides/tzdata",
+ "/usr/share/zoneinfo/Africa/Abidjan",
+ "/usr/share/zoneinfo/Africa/Accra",
+ "/usr/share/zoneinfo/Africa/Addis_Ababa",
+ "/usr/share/zoneinfo/Africa/Algiers",
+ "/usr/share/zoneinfo/Africa/Asmara",
+ "/usr/share/zoneinfo/Africa/Bamako",
+ "/usr/share/zoneinfo/Africa/Bangui",
+ "/usr/share/zoneinfo/Africa/Banjul",
+ "/usr/share/zoneinfo/Africa/Bissau",
+ "/usr/share/zoneinfo/Africa/Blantyre",
+ "/usr/share/zoneinfo/Africa/Brazzaville",
+ "/usr/share/zoneinfo/Africa/Bujumbura",
+ "/usr/share/zoneinfo/Africa/Cairo",
+ "/usr/share/zoneinfo/Africa/Casablanca",
+ "/usr/share/zoneinfo/Africa/Ceuta",
+ "/usr/share/zoneinfo/Africa/Conakry",
+ "/usr/share/zoneinfo/Africa/Dakar",
+ "/usr/share/zoneinfo/Africa/Dar_es_Salaam",
+ "/usr/share/zoneinfo/Africa/Djibouti",
+ "/usr/share/zoneinfo/Africa/Douala",
+ "/usr/share/zoneinfo/Africa/El_Aaiun",
+ "/usr/share/zoneinfo/Africa/Freetown",
+ "/usr/share/zoneinfo/Africa/Gaborone",
+ "/usr/share/zoneinfo/Africa/Harare",
+ "/usr/share/zoneinfo/Africa/Johannesburg",
+ "/usr/share/zoneinfo/Africa/Juba",
+ "/usr/share/zoneinfo/Africa/Kampala",
+ "/usr/share/zoneinfo/Africa/Khartoum",
+ "/usr/share/zoneinfo/Africa/Kigali",
+ "/usr/share/zoneinfo/Africa/Kinshasa",
+ "/usr/share/zoneinfo/Africa/Lagos",
+ "/usr/share/zoneinfo/Africa/Libreville",
+ "/usr/share/zoneinfo/Africa/Lome",
+ "/usr/share/zoneinfo/Africa/Luanda",
+ "/usr/share/zoneinfo/Africa/Lubumbashi",
+ "/usr/share/zoneinfo/Africa/Lusaka",
+ "/usr/share/zoneinfo/Africa/Malabo",
+ "/usr/share/zoneinfo/Africa/Maputo",
+ "/usr/share/zoneinfo/Africa/Maseru",
+ "/usr/share/zoneinfo/Africa/Mbabane",
+ "/usr/share/zoneinfo/Africa/Mogadishu",
+ "/usr/share/zoneinfo/Africa/Monrovia",
+ "/usr/share/zoneinfo/Africa/Nairobi",
+ "/usr/share/zoneinfo/Africa/Ndjamena",
+ "/usr/share/zoneinfo/Africa/Niamey",
+ "/usr/share/zoneinfo/Africa/Nouakchott",
+ "/usr/share/zoneinfo/Africa/Ouagadougou",
+ "/usr/share/zoneinfo/Africa/Porto-Novo",
+ "/usr/share/zoneinfo/Africa/Sao_Tome",
+ "/usr/share/zoneinfo/Africa/Tripoli",
+ "/usr/share/zoneinfo/Africa/Tunis",
+ "/usr/share/zoneinfo/Africa/Windhoek",
+ "/usr/share/zoneinfo/America/Adak",
+ "/usr/share/zoneinfo/America/Anchorage",
+ "/usr/share/zoneinfo/America/Anguilla",
+ "/usr/share/zoneinfo/America/Antigua",
+ "/usr/share/zoneinfo/America/Araguaina",
+ "/usr/share/zoneinfo/America/Argentina/Buenos_Aires",
+ "/usr/share/zoneinfo/America/Argentina/Catamarca",
+ "/usr/share/zoneinfo/America/Argentina/Cordoba",
+ "/usr/share/zoneinfo/America/Argentina/Jujuy",
+ "/usr/share/zoneinfo/America/Argentina/La_Rioja",
+ "/usr/share/zoneinfo/America/Argentina/Mendoza",
+ "/usr/share/zoneinfo/America/Argentina/Rio_Gallegos",
+ "/usr/share/zoneinfo/America/Argentina/Salta",
+ "/usr/share/zoneinfo/America/Argentina/San_Juan",
+ "/usr/share/zoneinfo/America/Argentina/San_Luis",
+ "/usr/share/zoneinfo/America/Argentina/Tucuman",
+ "/usr/share/zoneinfo/America/Argentina/Ushuaia",
+ "/usr/share/zoneinfo/America/Aruba",
+ "/usr/share/zoneinfo/America/Asuncion",
+ "/usr/share/zoneinfo/America/Atikokan",
+ "/usr/share/zoneinfo/America/Bahia",
+ "/usr/share/zoneinfo/America/Bahia_Banderas",
+ "/usr/share/zoneinfo/America/Barbados",
+ "/usr/share/zoneinfo/America/Belem",
+ "/usr/share/zoneinfo/America/Belize",
+ "/usr/share/zoneinfo/America/Blanc-Sablon",
+ "/usr/share/zoneinfo/America/Boa_Vista",
+ "/usr/share/zoneinfo/America/Bogota",
+ "/usr/share/zoneinfo/America/Boise",
+ "/usr/share/zoneinfo/America/Cambridge_Bay",
+ "/usr/share/zoneinfo/America/Campo_Grande",
+ "/usr/share/zoneinfo/America/Cancun",
+ "/usr/share/zoneinfo/America/Caracas",
+ "/usr/share/zoneinfo/America/Cayenne",
+ "/usr/share/zoneinfo/America/Cayman",
+ "/usr/share/zoneinfo/America/Chicago",
+ "/usr/share/zoneinfo/America/Chihuahua",
+ "/usr/share/zoneinfo/America/Ciudad_Juarez",
+ "/usr/share/zoneinfo/America/Costa_Rica",
+ "/usr/share/zoneinfo/America/Coyhaique",
+ "/usr/share/zoneinfo/America/Creston",
+ "/usr/share/zoneinfo/America/Cuiaba",
+ "/usr/share/zoneinfo/America/Curacao",
+ "/usr/share/zoneinfo/America/Danmarkshavn",
+ "/usr/share/zoneinfo/America/Dawson",
+ "/usr/share/zoneinfo/America/Dawson_Creek",
+ "/usr/share/zoneinfo/America/Denver",
+ "/usr/share/zoneinfo/America/Detroit",
+ "/usr/share/zoneinfo/America/Dominica",
+ "/usr/share/zoneinfo/America/Edmonton",
+ "/usr/share/zoneinfo/America/Eirunepe",
+ "/usr/share/zoneinfo/America/El_Salvador",
+ "/usr/share/zoneinfo/America/Fort_Nelson",
+ "/usr/share/zoneinfo/America/Fortaleza",
+ "/usr/share/zoneinfo/America/Glace_Bay",
+ "/usr/share/zoneinfo/America/Goose_Bay",
+ "/usr/share/zoneinfo/America/Grand_Turk",
+ "/usr/share/zoneinfo/America/Grenada",
+ "/usr/share/zoneinfo/America/Guadeloupe",
+ "/usr/share/zoneinfo/America/Guatemala",
+ "/usr/share/zoneinfo/America/Guayaquil",
+ "/usr/share/zoneinfo/America/Guyana",
+ "/usr/share/zoneinfo/America/Halifax",
+ "/usr/share/zoneinfo/America/Havana",
+ "/usr/share/zoneinfo/America/Hermosillo",
+ "/usr/share/zoneinfo/America/Indiana/Indianapolis",
+ "/usr/share/zoneinfo/America/Indiana/Knox",
+ "/usr/share/zoneinfo/America/Indiana/Marengo",
+ "/usr/share/zoneinfo/America/Indiana/Petersburg",
+ "/usr/share/zoneinfo/America/Indiana/Tell_City",
+ "/usr/share/zoneinfo/America/Indiana/Vevay",
+ "/usr/share/zoneinfo/America/Indiana/Vincennes",
+ "/usr/share/zoneinfo/America/Indiana/Winamac",
+ "/usr/share/zoneinfo/America/Inuvik",
+ "/usr/share/zoneinfo/America/Iqaluit",
+ "/usr/share/zoneinfo/America/Jamaica",
+ "/usr/share/zoneinfo/America/Juneau",
+ "/usr/share/zoneinfo/America/Kentucky/Louisville",
+ "/usr/share/zoneinfo/America/Kentucky/Monticello",
+ "/usr/share/zoneinfo/America/La_Paz",
+ "/usr/share/zoneinfo/America/Lima",
+ "/usr/share/zoneinfo/America/Los_Angeles",
+ "/usr/share/zoneinfo/America/Maceio",
+ "/usr/share/zoneinfo/America/Managua",
+ "/usr/share/zoneinfo/America/Manaus",
+ "/usr/share/zoneinfo/America/Martinique",
+ "/usr/share/zoneinfo/America/Matamoros",
+ "/usr/share/zoneinfo/America/Mazatlan",
+ "/usr/share/zoneinfo/America/Menominee",
+ "/usr/share/zoneinfo/America/Merida",
+ "/usr/share/zoneinfo/America/Metlakatla",
+ "/usr/share/zoneinfo/America/Mexico_City",
+ "/usr/share/zoneinfo/America/Miquelon",
+ "/usr/share/zoneinfo/America/Moncton",
+ "/usr/share/zoneinfo/America/Monterrey",
+ "/usr/share/zoneinfo/America/Montevideo",
+ "/usr/share/zoneinfo/America/Montserrat",
+ "/usr/share/zoneinfo/America/Nassau",
+ "/usr/share/zoneinfo/America/New_York",
+ "/usr/share/zoneinfo/America/Nome",
+ "/usr/share/zoneinfo/America/Noronha",
+ "/usr/share/zoneinfo/America/North_Dakota/Beulah",
+ "/usr/share/zoneinfo/America/North_Dakota/Center",
+ "/usr/share/zoneinfo/America/North_Dakota/New_Salem",
+ "/usr/share/zoneinfo/America/Nuuk",
+ "/usr/share/zoneinfo/America/Ojinaga",
+ "/usr/share/zoneinfo/America/Panama",
+ "/usr/share/zoneinfo/America/Paramaribo",
+ "/usr/share/zoneinfo/America/Phoenix",
+ "/usr/share/zoneinfo/America/Port-au-Prince",
+ "/usr/share/zoneinfo/America/Port_of_Spain",
+ "/usr/share/zoneinfo/America/Porto_Velho",
+ "/usr/share/zoneinfo/America/Puerto_Rico",
+ "/usr/share/zoneinfo/America/Punta_Arenas",
+ "/usr/share/zoneinfo/America/Rankin_Inlet",
+ "/usr/share/zoneinfo/America/Recife",
+ "/usr/share/zoneinfo/America/Regina",
+ "/usr/share/zoneinfo/America/Resolute",
+ "/usr/share/zoneinfo/America/Rio_Branco",
+ "/usr/share/zoneinfo/America/Santarem",
+ "/usr/share/zoneinfo/America/Santiago",
+ "/usr/share/zoneinfo/America/Santo_Domingo",
+ "/usr/share/zoneinfo/America/Sao_Paulo",
+ "/usr/share/zoneinfo/America/Scoresbysund",
+ "/usr/share/zoneinfo/America/Sitka",
+ "/usr/share/zoneinfo/America/St_Johns",
+ "/usr/share/zoneinfo/America/St_Kitts",
+ "/usr/share/zoneinfo/America/St_Lucia",
+ "/usr/share/zoneinfo/America/St_Thomas",
+ "/usr/share/zoneinfo/America/St_Vincent",
+ "/usr/share/zoneinfo/America/Swift_Current",
+ "/usr/share/zoneinfo/America/Tegucigalpa",
+ "/usr/share/zoneinfo/America/Thule",
+ "/usr/share/zoneinfo/America/Tijuana",
+ "/usr/share/zoneinfo/America/Toronto",
+ "/usr/share/zoneinfo/America/Tortola",
+ "/usr/share/zoneinfo/America/Vancouver",
+ "/usr/share/zoneinfo/America/Whitehorse",
+ "/usr/share/zoneinfo/America/Winnipeg",
+ "/usr/share/zoneinfo/America/Yakutat",
+ "/usr/share/zoneinfo/Antarctica/Casey",
+ "/usr/share/zoneinfo/Antarctica/Davis",
+ "/usr/share/zoneinfo/Antarctica/DumontDUrville",
+ "/usr/share/zoneinfo/Antarctica/Macquarie",
+ "/usr/share/zoneinfo/Antarctica/Mawson",
+ "/usr/share/zoneinfo/Antarctica/McMurdo",
+ "/usr/share/zoneinfo/Antarctica/Palmer",
+ "/usr/share/zoneinfo/Antarctica/Rothera",
+ "/usr/share/zoneinfo/Antarctica/Syowa",
+ "/usr/share/zoneinfo/Antarctica/Troll",
+ "/usr/share/zoneinfo/Antarctica/Vostok",
+ "/usr/share/zoneinfo/Asia/Aden",
+ "/usr/share/zoneinfo/Asia/Almaty",
+ "/usr/share/zoneinfo/Asia/Amman",
+ "/usr/share/zoneinfo/Asia/Anadyr",
+ "/usr/share/zoneinfo/Asia/Aqtau",
+ "/usr/share/zoneinfo/Asia/Aqtobe",
+ "/usr/share/zoneinfo/Asia/Ashgabat",
+ "/usr/share/zoneinfo/Asia/Atyrau",
+ "/usr/share/zoneinfo/Asia/Baghdad",
+ "/usr/share/zoneinfo/Asia/Bahrain",
+ "/usr/share/zoneinfo/Asia/Baku",
+ "/usr/share/zoneinfo/Asia/Bangkok",
+ "/usr/share/zoneinfo/Asia/Barnaul",
+ "/usr/share/zoneinfo/Asia/Beirut",
+ "/usr/share/zoneinfo/Asia/Bishkek",
+ "/usr/share/zoneinfo/Asia/Brunei",
+ "/usr/share/zoneinfo/Asia/Chita",
+ "/usr/share/zoneinfo/Asia/Colombo",
+ "/usr/share/zoneinfo/Asia/Damascus",
+ "/usr/share/zoneinfo/Asia/Dhaka",
+ "/usr/share/zoneinfo/Asia/Dili",
+ "/usr/share/zoneinfo/Asia/Dubai",
+ "/usr/share/zoneinfo/Asia/Dushanbe",
+ "/usr/share/zoneinfo/Asia/Famagusta",
+ "/usr/share/zoneinfo/Asia/Gaza",
+ "/usr/share/zoneinfo/Asia/Hebron",
+ "/usr/share/zoneinfo/Asia/Ho_Chi_Minh",
+ "/usr/share/zoneinfo/Asia/Hong_Kong",
+ "/usr/share/zoneinfo/Asia/Hovd",
+ "/usr/share/zoneinfo/Asia/Irkutsk",
+ "/usr/share/zoneinfo/Asia/Jakarta",
+ "/usr/share/zoneinfo/Asia/Jayapura",
+ "/usr/share/zoneinfo/Asia/Jerusalem",
+ "/usr/share/zoneinfo/Asia/Kabul",
+ "/usr/share/zoneinfo/Asia/Kamchatka",
+ "/usr/share/zoneinfo/Asia/Karachi",
+ "/usr/share/zoneinfo/Asia/Kathmandu",
+ "/usr/share/zoneinfo/Asia/Khandyga",
+ "/usr/share/zoneinfo/Asia/Kolkata",
+ "/usr/share/zoneinfo/Asia/Krasnoyarsk",
+ "/usr/share/zoneinfo/Asia/Kuala_Lumpur",
+ "/usr/share/zoneinfo/Asia/Kuching",
+ "/usr/share/zoneinfo/Asia/Kuwait",
+ "/usr/share/zoneinfo/Asia/Macau",
+ "/usr/share/zoneinfo/Asia/Magadan",
+ "/usr/share/zoneinfo/Asia/Makassar",
+ "/usr/share/zoneinfo/Asia/Manila",
+ "/usr/share/zoneinfo/Asia/Muscat",
+ "/usr/share/zoneinfo/Asia/Nicosia",
+ "/usr/share/zoneinfo/Asia/Novokuznetsk",
+ "/usr/share/zoneinfo/Asia/Novosibirsk",
+ "/usr/share/zoneinfo/Asia/Omsk",
+ "/usr/share/zoneinfo/Asia/Oral",
+ "/usr/share/zoneinfo/Asia/Phnom_Penh",
+ "/usr/share/zoneinfo/Asia/Pontianak",
+ "/usr/share/zoneinfo/Asia/Pyongyang",
+ "/usr/share/zoneinfo/Asia/Qatar",
+ "/usr/share/zoneinfo/Asia/Qostanay",
+ "/usr/share/zoneinfo/Asia/Qyzylorda",
+ "/usr/share/zoneinfo/Asia/Riyadh",
+ "/usr/share/zoneinfo/Asia/Sakhalin",
+ "/usr/share/zoneinfo/Asia/Samarkand",
+ "/usr/share/zoneinfo/Asia/Seoul",
+ "/usr/share/zoneinfo/Asia/Shanghai",
+ "/usr/share/zoneinfo/Asia/Singapore",
+ "/usr/share/zoneinfo/Asia/Srednekolymsk",
+ "/usr/share/zoneinfo/Asia/Taipei",
+ "/usr/share/zoneinfo/Asia/Tashkent",
+ "/usr/share/zoneinfo/Asia/Tbilisi",
+ "/usr/share/zoneinfo/Asia/Tehran",
+ "/usr/share/zoneinfo/Asia/Thimphu",
+ "/usr/share/zoneinfo/Asia/Tokyo",
+ "/usr/share/zoneinfo/Asia/Tomsk",
+ "/usr/share/zoneinfo/Asia/Ulaanbaatar",
+ "/usr/share/zoneinfo/Asia/Urumqi",
+ "/usr/share/zoneinfo/Asia/Ust-Nera",
+ "/usr/share/zoneinfo/Asia/Vientiane",
+ "/usr/share/zoneinfo/Asia/Vladivostok",
+ "/usr/share/zoneinfo/Asia/Yakutsk",
+ "/usr/share/zoneinfo/Asia/Yangon",
+ "/usr/share/zoneinfo/Asia/Yekaterinburg",
+ "/usr/share/zoneinfo/Asia/Yerevan",
+ "/usr/share/zoneinfo/Atlantic/Azores",
+ "/usr/share/zoneinfo/Atlantic/Bermuda",
+ "/usr/share/zoneinfo/Atlantic/Canary",
+ "/usr/share/zoneinfo/Atlantic/Cape_Verde",
+ "/usr/share/zoneinfo/Atlantic/Faroe",
+ "/usr/share/zoneinfo/Atlantic/Madeira",
+ "/usr/share/zoneinfo/Atlantic/Reykjavik",
+ "/usr/share/zoneinfo/Atlantic/South_Georgia",
+ "/usr/share/zoneinfo/Atlantic/St_Helena",
+ "/usr/share/zoneinfo/Atlantic/Stanley",
+ "/usr/share/zoneinfo/Australia/Adelaide",
+ "/usr/share/zoneinfo/Australia/Brisbane",
+ "/usr/share/zoneinfo/Australia/Broken_Hill",
+ "/usr/share/zoneinfo/Australia/Darwin",
+ "/usr/share/zoneinfo/Australia/Eucla",
+ "/usr/share/zoneinfo/Australia/Hobart",
+ "/usr/share/zoneinfo/Australia/Lindeman",
+ "/usr/share/zoneinfo/Australia/Lord_Howe",
+ "/usr/share/zoneinfo/Australia/Melbourne",
+ "/usr/share/zoneinfo/Australia/Perth",
+ "/usr/share/zoneinfo/Australia/Sydney",
+ "/usr/share/zoneinfo/Etc/GMT",
+ "/usr/share/zoneinfo/Etc/GMT+1",
+ "/usr/share/zoneinfo/Etc/GMT+10",
+ "/usr/share/zoneinfo/Etc/GMT+11",
+ "/usr/share/zoneinfo/Etc/GMT+12",
+ "/usr/share/zoneinfo/Etc/GMT+2",
+ "/usr/share/zoneinfo/Etc/GMT+3",
+ "/usr/share/zoneinfo/Etc/GMT+4",
+ "/usr/share/zoneinfo/Etc/GMT+5",
+ "/usr/share/zoneinfo/Etc/GMT+6",
+ "/usr/share/zoneinfo/Etc/GMT+7",
+ "/usr/share/zoneinfo/Etc/GMT+8",
+ "/usr/share/zoneinfo/Etc/GMT+9",
+ "/usr/share/zoneinfo/Etc/GMT-1",
+ "/usr/share/zoneinfo/Etc/GMT-10",
+ "/usr/share/zoneinfo/Etc/GMT-11",
+ "/usr/share/zoneinfo/Etc/GMT-12",
+ "/usr/share/zoneinfo/Etc/GMT-13",
+ "/usr/share/zoneinfo/Etc/GMT-14",
+ "/usr/share/zoneinfo/Etc/GMT-2",
+ "/usr/share/zoneinfo/Etc/GMT-3",
+ "/usr/share/zoneinfo/Etc/GMT-4",
+ "/usr/share/zoneinfo/Etc/GMT-5",
+ "/usr/share/zoneinfo/Etc/GMT-6",
+ "/usr/share/zoneinfo/Etc/GMT-7",
+ "/usr/share/zoneinfo/Etc/GMT-8",
+ "/usr/share/zoneinfo/Etc/GMT-9",
+ "/usr/share/zoneinfo/Etc/UTC",
+ "/usr/share/zoneinfo/Europe/Amsterdam",
+ "/usr/share/zoneinfo/Europe/Andorra",
+ "/usr/share/zoneinfo/Europe/Astrakhan",
+ "/usr/share/zoneinfo/Europe/Athens",
+ "/usr/share/zoneinfo/Europe/Belgrade",
+ "/usr/share/zoneinfo/Europe/Berlin",
+ "/usr/share/zoneinfo/Europe/Brussels",
+ "/usr/share/zoneinfo/Europe/Bucharest",
+ "/usr/share/zoneinfo/Europe/Budapest",
+ "/usr/share/zoneinfo/Europe/Chisinau",
+ "/usr/share/zoneinfo/Europe/Copenhagen",
+ "/usr/share/zoneinfo/Europe/Dublin",
+ "/usr/share/zoneinfo/Europe/Gibraltar",
+ "/usr/share/zoneinfo/Europe/Guernsey",
+ "/usr/share/zoneinfo/Europe/Helsinki",
+ "/usr/share/zoneinfo/Europe/Isle_of_Man",
+ "/usr/share/zoneinfo/Europe/Istanbul",
+ "/usr/share/zoneinfo/Europe/Jersey",
+ "/usr/share/zoneinfo/Europe/Kaliningrad",
+ "/usr/share/zoneinfo/Europe/Kirov",
+ "/usr/share/zoneinfo/Europe/Kyiv",
+ "/usr/share/zoneinfo/Europe/Lisbon",
+ "/usr/share/zoneinfo/Europe/Ljubljana",
+ "/usr/share/zoneinfo/Europe/London",
+ "/usr/share/zoneinfo/Europe/Luxembourg",
+ "/usr/share/zoneinfo/Europe/Madrid",
+ "/usr/share/zoneinfo/Europe/Malta",
+ "/usr/share/zoneinfo/Europe/Minsk",
+ "/usr/share/zoneinfo/Europe/Monaco",
+ "/usr/share/zoneinfo/Europe/Moscow",
+ "/usr/share/zoneinfo/Europe/Oslo",
+ "/usr/share/zoneinfo/Europe/Paris",
+ "/usr/share/zoneinfo/Europe/Prague",
+ "/usr/share/zoneinfo/Europe/Riga",
+ "/usr/share/zoneinfo/Europe/Rome",
+ "/usr/share/zoneinfo/Europe/Samara",
+ "/usr/share/zoneinfo/Europe/Sarajevo",
+ "/usr/share/zoneinfo/Europe/Saratov",
+ "/usr/share/zoneinfo/Europe/Simferopol",
+ "/usr/share/zoneinfo/Europe/Skopje",
+ "/usr/share/zoneinfo/Europe/Sofia",
+ "/usr/share/zoneinfo/Europe/Stockholm",
+ "/usr/share/zoneinfo/Europe/Tallinn",
+ "/usr/share/zoneinfo/Europe/Tirane",
+ "/usr/share/zoneinfo/Europe/Ulyanovsk",
+ "/usr/share/zoneinfo/Europe/Vaduz",
+ "/usr/share/zoneinfo/Europe/Vienna",
+ "/usr/share/zoneinfo/Europe/Vilnius",
+ "/usr/share/zoneinfo/Europe/Volgograd",
+ "/usr/share/zoneinfo/Europe/Warsaw",
+ "/usr/share/zoneinfo/Europe/Zagreb",
+ "/usr/share/zoneinfo/Europe/Zurich",
+ "/usr/share/zoneinfo/Factory",
+ "/usr/share/zoneinfo/Indian/Antananarivo",
+ "/usr/share/zoneinfo/Indian/Chagos",
+ "/usr/share/zoneinfo/Indian/Christmas",
+ "/usr/share/zoneinfo/Indian/Cocos",
+ "/usr/share/zoneinfo/Indian/Comoro",
+ "/usr/share/zoneinfo/Indian/Kerguelen",
+ "/usr/share/zoneinfo/Indian/Mahe",
+ "/usr/share/zoneinfo/Indian/Maldives",
+ "/usr/share/zoneinfo/Indian/Mauritius",
+ "/usr/share/zoneinfo/Indian/Mayotte",
+ "/usr/share/zoneinfo/Indian/Reunion",
+ "/usr/share/zoneinfo/Pacific/Apia",
+ "/usr/share/zoneinfo/Pacific/Auckland",
+ "/usr/share/zoneinfo/Pacific/Bougainville",
+ "/usr/share/zoneinfo/Pacific/Chatham",
+ "/usr/share/zoneinfo/Pacific/Chuuk",
+ "/usr/share/zoneinfo/Pacific/Easter",
+ "/usr/share/zoneinfo/Pacific/Efate",
+ "/usr/share/zoneinfo/Pacific/Fakaofo",
+ "/usr/share/zoneinfo/Pacific/Fiji",
+ "/usr/share/zoneinfo/Pacific/Funafuti",
+ "/usr/share/zoneinfo/Pacific/Galapagos",
+ "/usr/share/zoneinfo/Pacific/Gambier",
+ "/usr/share/zoneinfo/Pacific/Guadalcanal",
+ "/usr/share/zoneinfo/Pacific/Guam",
+ "/usr/share/zoneinfo/Pacific/Honolulu",
+ "/usr/share/zoneinfo/Pacific/Kanton",
+ "/usr/share/zoneinfo/Pacific/Kiritimati",
+ "/usr/share/zoneinfo/Pacific/Kosrae",
+ "/usr/share/zoneinfo/Pacific/Kwajalein",
+ "/usr/share/zoneinfo/Pacific/Majuro",
+ "/usr/share/zoneinfo/Pacific/Marquesas",
+ "/usr/share/zoneinfo/Pacific/Midway",
+ "/usr/share/zoneinfo/Pacific/Nauru",
+ "/usr/share/zoneinfo/Pacific/Niue",
+ "/usr/share/zoneinfo/Pacific/Norfolk",
+ "/usr/share/zoneinfo/Pacific/Noumea",
+ "/usr/share/zoneinfo/Pacific/Pago_Pago",
+ "/usr/share/zoneinfo/Pacific/Palau",
+ "/usr/share/zoneinfo/Pacific/Pitcairn",
+ "/usr/share/zoneinfo/Pacific/Pohnpei",
+ "/usr/share/zoneinfo/Pacific/Port_Moresby",
+ "/usr/share/zoneinfo/Pacific/Rarotonga",
+ "/usr/share/zoneinfo/Pacific/Saipan",
+ "/usr/share/zoneinfo/Pacific/Tahiti",
+ "/usr/share/zoneinfo/Pacific/Tarawa",
+ "/usr/share/zoneinfo/Pacific/Tongatapu",
+ "/usr/share/zoneinfo/Pacific/Wake",
+ "/usr/share/zoneinfo/Pacific/Wallis",
+ "/usr/share/zoneinfo/iso3166.tab",
+ "/usr/share/zoneinfo/leap-seconds.list",
+ "/usr/share/zoneinfo/leapseconds",
+ "/usr/share/zoneinfo/tzdata.zi",
+ "/usr/share/zoneinfo/zone.tab",
+ "/usr/share/zoneinfo/zone1970.tab",
+ "/usr/share/zoneinfo/zonenow.tab"
+ ]
+ },
+ {
+ "ID": "util-linux@2.41-5",
+ "Name": "util-linux",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/util-linux@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "38be4846f19b7fa"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/choom",
+ "/usr/bin/chrt",
+ "/usr/bin/dmesg",
+ "/usr/bin/fallocate",
+ "/usr/bin/findmnt",
+ "/usr/bin/flock",
+ "/usr/bin/getopt",
+ "/usr/bin/hardlink",
+ "/usr/bin/ionice",
+ "/usr/bin/ipcmk",
+ "/usr/bin/ipcrm",
+ "/usr/bin/ipcs",
+ "/usr/bin/lsblk",
+ "/usr/bin/lscpu",
+ "/usr/bin/lsipc",
+ "/usr/bin/lslocks",
+ "/usr/bin/lslogins",
+ "/usr/bin/lsmem",
+ "/usr/bin/lsns",
+ "/usr/bin/mcookie",
+ "/usr/bin/more",
+ "/usr/bin/mountpoint",
+ "/usr/bin/namei",
+ "/usr/bin/nsenter",
+ "/usr/bin/partx",
+ "/usr/bin/prlimit",
+ "/usr/bin/rename.ul",
+ "/usr/bin/rev",
+ "/usr/bin/setarch",
+ "/usr/bin/setpriv",
+ "/usr/bin/setsid",
+ "/usr/bin/setterm",
+ "/usr/bin/su",
+ "/usr/bin/taskset",
+ "/usr/bin/uclampset",
+ "/usr/bin/unshare",
+ "/usr/bin/wdctl",
+ "/usr/bin/whereis",
+ "/usr/lib/mime/packages/util-linux",
+ "/usr/lib/systemd/system/fstrim.service",
+ "/usr/lib/systemd/system/fstrim.timer",
+ "/usr/sbin/agetty",
+ "/usr/sbin/blkdiscard",
+ "/usr/sbin/blkid",
+ "/usr/sbin/blkzone",
+ "/usr/sbin/blockdev",
+ "/usr/sbin/chcpu",
+ "/usr/sbin/chmem",
+ "/usr/sbin/findfs",
+ "/usr/sbin/fsck",
+ "/usr/sbin/fsfreeze",
+ "/usr/sbin/fstrim",
+ "/usr/sbin/isosize",
+ "/usr/sbin/ldattach",
+ "/usr/sbin/mkfs",
+ "/usr/sbin/mkswap",
+ "/usr/sbin/pivot_root",
+ "/usr/sbin/readprofile",
+ "/usr/sbin/rtcwake",
+ "/usr/sbin/runuser",
+ "/usr/sbin/sulogin",
+ "/usr/sbin/swaplabel",
+ "/usr/sbin/switch_root",
+ "/usr/sbin/wipefs",
+ "/usr/sbin/zramctl",
+ "/usr/share/bash-completion/completions/blkdiscard",
+ "/usr/share/bash-completion/completions/blkid",
+ "/usr/share/bash-completion/completions/blkzone",
+ "/usr/share/bash-completion/completions/blockdev",
+ "/usr/share/bash-completion/completions/chcpu",
+ "/usr/share/bash-completion/completions/chmem",
+ "/usr/share/bash-completion/completions/chrt",
+ "/usr/share/bash-completion/completions/dmesg",
+ "/usr/share/bash-completion/completions/fallocate",
+ "/usr/share/bash-completion/completions/findfs",
+ "/usr/share/bash-completion/completions/findmnt",
+ "/usr/share/bash-completion/completions/flock",
+ "/usr/share/bash-completion/completions/fsck",
+ "/usr/share/bash-completion/completions/fsfreeze",
+ "/usr/share/bash-completion/completions/fstrim",
+ "/usr/share/bash-completion/completions/getopt",
+ "/usr/share/bash-completion/completions/hardlink",
+ "/usr/share/bash-completion/completions/ionice",
+ "/usr/share/bash-completion/completions/ipcmk",
+ "/usr/share/bash-completion/completions/ipcrm",
+ "/usr/share/bash-completion/completions/ipcs",
+ "/usr/share/bash-completion/completions/isosize",
+ "/usr/share/bash-completion/completions/ldattach",
+ "/usr/share/bash-completion/completions/lsblk",
+ "/usr/share/bash-completion/completions/lscpu",
+ "/usr/share/bash-completion/completions/lsipc",
+ "/usr/share/bash-completion/completions/lslocks",
+ "/usr/share/bash-completion/completions/lslogins",
+ "/usr/share/bash-completion/completions/lsmem",
+ "/usr/share/bash-completion/completions/lsns",
+ "/usr/share/bash-completion/completions/mcookie",
+ "/usr/share/bash-completion/completions/mkfs",
+ "/usr/share/bash-completion/completions/mkswap",
+ "/usr/share/bash-completion/completions/more",
+ "/usr/share/bash-completion/completions/mountpoint",
+ "/usr/share/bash-completion/completions/namei",
+ "/usr/share/bash-completion/completions/nsenter",
+ "/usr/share/bash-completion/completions/partx",
+ "/usr/share/bash-completion/completions/pivot_root",
+ "/usr/share/bash-completion/completions/prlimit",
+ "/usr/share/bash-completion/completions/readprofile",
+ "/usr/share/bash-completion/completions/rename.ul",
+ "/usr/share/bash-completion/completions/rev",
+ "/usr/share/bash-completion/completions/rtcwake",
+ "/usr/share/bash-completion/completions/setarch",
+ "/usr/share/bash-completion/completions/setpriv",
+ "/usr/share/bash-completion/completions/setsid",
+ "/usr/share/bash-completion/completions/setterm",
+ "/usr/share/bash-completion/completions/su",
+ "/usr/share/bash-completion/completions/swaplabel",
+ "/usr/share/bash-completion/completions/taskset",
+ "/usr/share/bash-completion/completions/uclampset",
+ "/usr/share/bash-completion/completions/unshare",
+ "/usr/share/bash-completion/completions/wdctl",
+ "/usr/share/bash-completion/completions/whereis",
+ "/usr/share/bash-completion/completions/wipefs",
+ "/usr/share/bash-completion/completions/zramctl",
+ "/usr/share/doc/util-linux/00-about-docs.txt",
+ "/usr/share/doc/util-linux/AUTHORS.gz",
+ "/usr/share/doc/util-linux/NEWS.Debian.gz",
+ "/usr/share/doc/util-linux/PAM-configuration.txt",
+ "/usr/share/doc/util-linux/README.Debian",
+ "/usr/share/doc/util-linux/blkid.txt",
+ "/usr/share/doc/util-linux/cal.txt",
+ "/usr/share/doc/util-linux/changelog.Debian.gz",
+ "/usr/share/doc/util-linux/changelog.gz",
+ "/usr/share/doc/util-linux/col.txt",
+ "/usr/share/doc/util-linux/copyright",
+ "/usr/share/doc/util-linux/deprecated.txt",
+ "/usr/share/doc/util-linux/examples/getopt-example.bash",
+ "/usr/share/doc/util-linux/getopt.txt",
+ "/usr/share/doc/util-linux/getopt_changelog.txt",
+ "/usr/share/doc/util-linux/howto-build-sys.txt",
+ "/usr/share/doc/util-linux/howto-compilation.txt",
+ "/usr/share/doc/util-linux/howto-contribute.txt.gz",
+ "/usr/share/doc/util-linux/howto-debug.txt",
+ "/usr/share/doc/util-linux/howto-man-page.txt",
+ "/usr/share/doc/util-linux/howto-pull-request.txt.gz",
+ "/usr/share/doc/util-linux/howto-tests.txt",
+ "/usr/share/doc/util-linux/howto-usage-function.txt.gz",
+ "/usr/share/doc/util-linux/hwclock.txt",
+ "/usr/share/doc/util-linux/modems-with-agetty.txt",
+ "/usr/share/doc/util-linux/mount.txt",
+ "/usr/share/doc/util-linux/parse-date.txt.gz",
+ "/usr/share/doc/util-linux/pg.txt",
+ "/usr/share/doc/util-linux/poeigl.txt.gz",
+ "/usr/share/doc/util-linux/release-schedule.txt",
+ "/usr/share/doc/util-linux/releases/v2.13-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.14-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.15-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.16-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.17-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.18-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.19-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.20-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.21-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.22-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.23-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.24-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.25-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.26-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.27-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.28-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.29-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.30-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.31-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.32-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.33-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.34-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.35-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.36-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.37-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.38-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.39-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.40-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.41-ReleaseNotes.gz",
+ "/usr/share/lintian/overrides/util-linux",
+ "/usr/share/man/man1/choom.1.gz",
+ "/usr/share/man/man1/chrt.1.gz",
+ "/usr/share/man/man1/dmesg.1.gz",
+ "/usr/share/man/man1/fallocate.1.gz",
+ "/usr/share/man/man1/flock.1.gz",
+ "/usr/share/man/man1/getopt.1.gz",
+ "/usr/share/man/man1/hardlink.1.gz",
+ "/usr/share/man/man1/ionice.1.gz",
+ "/usr/share/man/man1/ipcmk.1.gz",
+ "/usr/share/man/man1/ipcrm.1.gz",
+ "/usr/share/man/man1/ipcs.1.gz",
+ "/usr/share/man/man1/lscpu.1.gz",
+ "/usr/share/man/man1/lsipc.1.gz",
+ "/usr/share/man/man1/lslogins.1.gz",
+ "/usr/share/man/man1/lsmem.1.gz",
+ "/usr/share/man/man1/mcookie.1.gz",
+ "/usr/share/man/man1/more.1.gz",
+ "/usr/share/man/man1/mountpoint.1.gz",
+ "/usr/share/man/man1/namei.1.gz",
+ "/usr/share/man/man1/nsenter.1.gz",
+ "/usr/share/man/man1/prlimit.1.gz",
+ "/usr/share/man/man1/rename.ul.1.gz",
+ "/usr/share/man/man1/rev.1.gz",
+ "/usr/share/man/man1/runuser.1.gz",
+ "/usr/share/man/man1/setpriv.1.gz",
+ "/usr/share/man/man1/setsid.1.gz",
+ "/usr/share/man/man1/setterm.1.gz",
+ "/usr/share/man/man1/su.1.gz",
+ "/usr/share/man/man1/taskset.1.gz",
+ "/usr/share/man/man1/uclampset.1.gz",
+ "/usr/share/man/man1/unshare.1.gz",
+ "/usr/share/man/man1/whereis.1.gz",
+ "/usr/share/man/man5/adjtime_config.5.gz",
+ "/usr/share/man/man5/scols-filter.5.gz",
+ "/usr/share/man/man5/terminal-colors.d.5.gz",
+ "/usr/share/man/man8/agetty.8.gz",
+ "/usr/share/man/man8/blkdiscard.8.gz",
+ "/usr/share/man/man8/blkid.8.gz",
+ "/usr/share/man/man8/blkzone.8.gz",
+ "/usr/share/man/man8/blockdev.8.gz",
+ "/usr/share/man/man8/chcpu.8.gz",
+ "/usr/share/man/man8/chmem.8.gz",
+ "/usr/share/man/man8/findfs.8.gz",
+ "/usr/share/man/man8/findmnt.8.gz",
+ "/usr/share/man/man8/fsck.8.gz",
+ "/usr/share/man/man8/fsfreeze.8.gz",
+ "/usr/share/man/man8/fstrim.8.gz",
+ "/usr/share/man/man8/isosize.8.gz",
+ "/usr/share/man/man8/ldattach.8.gz",
+ "/usr/share/man/man8/lsblk.8.gz",
+ "/usr/share/man/man8/lslocks.8.gz",
+ "/usr/share/man/man8/lsns.8.gz",
+ "/usr/share/man/man8/mkfs.8.gz",
+ "/usr/share/man/man8/mkswap.8.gz",
+ "/usr/share/man/man8/partx.8.gz",
+ "/usr/share/man/man8/pivot_root.8.gz",
+ "/usr/share/man/man8/readprofile.8.gz",
+ "/usr/share/man/man8/rtcwake.8.gz",
+ "/usr/share/man/man8/setarch.8.gz",
+ "/usr/share/man/man8/sulogin.8.gz",
+ "/usr/share/man/man8/swaplabel.8.gz",
+ "/usr/share/man/man8/switch_root.8.gz",
+ "/usr/share/man/man8/wdctl.8.gz",
+ "/usr/share/man/man8/wipefs.8.gz",
+ "/usr/share/man/man8/zramctl.8.gz",
+ "/usr/share/util-linux/logcheck/ignore.d.server/util-linux"
+ ]
+ },
+ {
+ "ID": "zlib1g@1:1.3.dfsg+really1.3.1-1+b1",
+ "Name": "zlib1g",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "202a4bb3bdd0a341"
+ },
+ "Version": "1.3.dfsg+really1.3.1",
+ "Release": "1+b1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "zlib",
+ "SrcVersion": "1.3.dfsg+really1.3.1",
+ "SrcRelease": "1",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "Zlib"
+ ],
+ "Maintainer": "Mark Brown \u003cbroonie@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libz.so.1.3.1",
+ "/usr/share/doc/zlib1g/changelog.Debian.amd64.gz",
+ "/usr/share/doc/zlib1g/changelog.Debian.gz",
+ "/usr/share/doc/zlib1g/changelog.gz",
+ "/usr/share/doc/zlib1g/copyright"
+ ]
+ }
+ ]
+ },
+ {
+ "Target": "Python",
+ "Class": "lang-pkgs",
+ "Type": "python-pkg",
+ "Packages": [
+ {
+ "Name": "PyJWT",
+ "Identifier": {
+ "PURL": "pkg:pypi/pyjwt@2.13.0",
+ "UID": "f4d7837dd486cbcf"
+ },
+ "Version": "2.13.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pyjwt-2.13.0.dist-info/METADATA"
+ },
+ {
+ "Name": "annotated-types",
+ "Identifier": {
+ "PURL": "pkg:pypi/annotated-types@0.7.0",
+ "UID": "a99a645f3910035b"
+ },
+ "Version": "0.7.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/METADATA"
+ },
+ {
+ "Name": "anthropic",
+ "Identifier": {
+ "PURL": "pkg:pypi/anthropic@0.104.1",
+ "UID": "ca201891b230d4bb"
+ },
+ "Version": "0.104.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/anthropic-0.104.1.dist-info/METADATA"
+ },
+ {
+ "Name": "anyio",
+ "Identifier": {
+ "PURL": "pkg:pypi/anyio@4.13.0",
+ "UID": "78cf51208adea85c"
+ },
+ "Version": "4.13.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/anyio-4.13.0.dist-info/METADATA"
+ },
+ {
+ "Name": "attrs",
+ "Identifier": {
+ "PURL": "pkg:pypi/attrs@26.1.0",
+ "UID": "8f465452effcf3f9"
+ },
+ "Version": "26.1.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/attrs-26.1.0.dist-info/METADATA"
+ },
+ {
+ "Name": "boto3",
+ "Identifier": {
+ "PURL": "pkg:pypi/boto3@1.43.56",
+ "UID": "8eb29918eab19e65"
+ },
+ "Version": "1.43.56",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/boto3-1.43.56.dist-info/METADATA"
+ },
+ {
+ "Name": "botocore",
+ "Identifier": {
+ "PURL": "pkg:pypi/botocore@1.43.56",
+ "UID": "843d6fb6c16227e1"
+ },
+ "Version": "1.43.56",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/botocore-1.43.56.dist-info/METADATA"
+ },
+ {
+ "Name": "certifi",
+ "Identifier": {
+ "PURL": "pkg:pypi/certifi@2026.5.20",
+ "UID": "3bdd0c600b32a18b"
+ },
+ "Version": "2026.5.20",
+ "Licenses": [
+ "MPL-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/certifi-2026.5.20.dist-info/METADATA"
+ },
+ {
+ "Name": "cffi",
+ "Identifier": {
+ "PURL": "pkg:pypi/cffi@2.0.0",
+ "UID": "a5634fada0c463fb"
+ },
+ "Version": "2.0.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/cffi-2.0.0.dist-info/METADATA"
+ },
+ {
+ "Name": "click",
+ "Identifier": {
+ "PURL": "pkg:pypi/click@8.4.1",
+ "UID": "ef23f255bd3c7aee"
+ },
+ "Version": "8.4.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/click-8.4.1.dist-info/METADATA"
+ },
+ {
+ "Name": "cryptography",
+ "Identifier": {
+ "PURL": "pkg:pypi/cryptography@49.0.0",
+ "UID": "951dcd36e1ea33b"
+ },
+ "Version": "49.0.0",
+ "Licenses": [
+ "Apache-2.0 OR BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/cryptography-49.0.0.dist-info/METADATA"
+ },
+ {
+ "Name": "distro",
+ "Identifier": {
+ "PURL": "pkg:pypi/distro@1.9.0",
+ "UID": "25523b069f98486e"
+ },
+ "Version": "1.9.0",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/distro-1.9.0.dist-info/METADATA"
+ },
+ {
+ "Name": "docstring_parser",
+ "Identifier": {
+ "PURL": "pkg:pypi/docstring-parser@0.18.0",
+ "UID": "3a7bde97f8e3daaf"
+ },
+ "Version": "0.18.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/docstring_parser-0.18.0.dist-info/METADATA"
+ },
+ {
+ "Name": "h11",
+ "Identifier": {
+ "PURL": "pkg:pypi/h11@0.16.0",
+ "UID": "680805ad174c70d5"
+ },
+ "Version": "0.16.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/h11-0.16.0.dist-info/METADATA"
+ },
+ {
+ "Name": "httpcore",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpcore@1.0.9",
+ "UID": "95d8f0a84544f78b"
+ },
+ "Version": "1.0.9",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpcore-1.0.9.dist-info/METADATA"
+ },
+ {
+ "Name": "httpx",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx@0.28.1",
+ "UID": "5e8f812d1d305e74"
+ },
+ "Version": "0.28.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/METADATA"
+ },
+ {
+ "Name": "httpx-sse",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx-sse@0.4.3",
+ "UID": "f5b099f8cdc33946"
+ },
+ "Version": "0.4.3",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpx_sse-0.4.3.dist-info/METADATA"
+ },
+ {
+ "Name": "idna",
+ "Identifier": {
+ "PURL": "pkg:pypi/idna@3.16",
+ "UID": "7c7fd4fce939f423"
+ },
+ "Version": "3.16",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/idna-3.16.dist-info/METADATA"
+ },
+ {
+ "Name": "jiter",
+ "Identifier": {
+ "PURL": "pkg:pypi/jiter@0.15.0",
+ "UID": "bbe6e5a734f374ee"
+ },
+ "Version": "0.15.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jiter-0.15.0.dist-info/METADATA"
+ },
+ {
+ "Name": "jmespath",
+ "Identifier": {
+ "PURL": "pkg:pypi/jmespath@1.1.0",
+ "UID": "46583dd718d8c745"
+ },
+ "Version": "1.1.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jmespath-1.1.0.dist-info/METADATA"
+ },
+ {
+ "Name": "jsonschema",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema@4.26.0",
+ "UID": "d56df30beb9ba43f"
+ },
+ "Version": "4.26.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jsonschema-4.26.0.dist-info/METADATA"
+ },
+ {
+ "Name": "jsonschema-specifications",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "UID": "5d770867a8968d3e"
+ },
+ "Version": "2025.9.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA"
+ },
+ {
+ "Name": "mcp",
+ "Identifier": {
+ "PURL": "pkg:pypi/mcp@1.28.1",
+ "UID": "a0cb1f0f51dbe65e"
+ },
+ "Version": "1.28.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/mcp-1.28.1.dist-info/METADATA"
+ },
+ {
+ "Name": "openai",
+ "Identifier": {
+ "PURL": "pkg:pypi/openai@2.38.0",
+ "UID": "8a16dec2f2dda139"
+ },
+ "Version": "2.38.0",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/openai-2.38.0.dist-info/METADATA"
+ },
+ {
+ "Name": "openrath",
+ "Identifier": {
+ "PURL": "pkg:pypi/openrath@1.3.0",
+ "UID": "a8edf7fa75f5aec9"
+ },
+ "Version": "1.3.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/openrath-1.3.0.dist-info/METADATA"
+ },
+ {
+ "Name": "opentelemetry-api",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-api@1.42.1",
+ "UID": "a3eb2cda00eccf47"
+ },
+ "Version": "1.42.1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_api-1.42.1.dist-info/METADATA"
+ },
+ {
+ "Name": "opentelemetry-sdk",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "UID": "fd2ac5c873caf297"
+ },
+ "Version": "1.42.1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_sdk-1.42.1.dist-info/METADATA"
+ },
+ {
+ "Name": "opentelemetry-semantic-conventions",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "UID": "807ed19efd6b801f"
+ },
+ "Version": "0.63b1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_semantic_conventions-0.63b1.dist-info/METADATA"
+ },
+ {
+ "Name": "pip",
+ "Identifier": {
+ "PURL": "pkg:pypi/pip@25.0.1",
+ "UID": "6c029e6e913de377"
+ },
+ "Version": "25.0.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "FilePath": "usr/local/lib/python3.12/site-packages/pip-25.0.1.dist-info/METADATA"
+ },
+ {
+ "Name": "psycopg",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg@3.3.4",
+ "UID": "a25eee15aab7acdd"
+ },
+ "Version": "3.3.4",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg-3.3.4.dist-info/METADATA"
+ },
+ {
+ "Name": "psycopg-binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4",
+ "UID": "cddad4642fcf0c56"
+ },
+ "Version": "3.3.4",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg_binary-3.3.4.dist-info/METADATA"
+ },
+ {
+ "Name": "psycopg-pool",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-pool@3.3.1",
+ "UID": "1bb6269f6fec0cf5"
+ },
+ "Version": "3.3.1",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg_pool-3.3.1.dist-info/METADATA"
+ },
+ {
+ "ID": "psycopg_binary@3.3.4",
+ "Name": "psycopg_binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "UID": "76f4c37cac088f9b",
+ "BOMRef": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+ },
+ "Version": "3.3.4",
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "ID": "psycopg_binary@3.3.4",
+ "Name": "psycopg_binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "UID": "56fa9b57c57faa13",
+ "BOMRef": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+ },
+ "Version": "3.3.4",
+ "DependsOn": [
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "cyrus-sasl-lib@2.1.26-24.el7_9",
+ "pcre@8.32-17.el7",
+ "libselinux@2.5-15.el7",
+ "libcom_err@1.42.9-19.el7",
+ "keyutils-libs@1.5.8-3.el7"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ }
+ },
+ {
+ "Name": "pycparser",
+ "Identifier": {
+ "PURL": "pkg:pypi/pycparser@3.0",
+ "UID": "2f3cbfabd774e0bb"
+ },
+ "Version": "3.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pycparser-3.0.dist-info/METADATA"
+ },
+ {
+ "Name": "pydantic",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic@2.13.4",
+ "UID": "85f1de8b45483025"
+ },
+ "Version": "2.13.4",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic-2.13.4.dist-info/METADATA"
+ },
+ {
+ "Name": "pydantic-settings",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-settings@2.14.2",
+ "UID": "6082c4467e82801d"
+ },
+ "Version": "2.14.2",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic_settings-2.14.2.dist-info/METADATA"
+ },
+ {
+ "Name": "pydantic_core",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-core@2.46.4",
+ "UID": "133a20c0f254cad5"
+ },
+ "Version": "2.46.4",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic_core-2.46.4.dist-info/METADATA"
+ },
+ {
+ "Name": "python-dateutil",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "UID": "a82076284c91d9e0"
+ },
+ "Version": "2.9.0.post0",
+ "Licenses": [
+ "BSD-3-Clause",
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA"
+ },
+ {
+ "Name": "python-dotenv",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dotenv@1.2.2",
+ "UID": "1d5512fb54c0f899"
+ },
+ "Version": "1.2.2",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_dotenv-1.2.2.dist-info/METADATA"
+ },
+ {
+ "Name": "python-multipart",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-multipart@0.0.32",
+ "UID": "ed71009179a5e27"
+ },
+ "Version": "0.0.32",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_multipart-0.0.32.dist-info/METADATA"
+ },
+ {
+ "Name": "redis",
+ "Identifier": {
+ "PURL": "pkg:pypi/redis@6.4.0",
+ "UID": "543c60c2609d9982"
+ },
+ "Version": "6.4.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/redis-6.4.0.dist-info/METADATA"
+ },
+ {
+ "Name": "referencing",
+ "Identifier": {
+ "PURL": "pkg:pypi/referencing@0.37.0",
+ "UID": "757400f54970ea7f"
+ },
+ "Version": "0.37.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/referencing-0.37.0.dist-info/METADATA"
+ },
+ {
+ "Name": "rpds-py",
+ "Identifier": {
+ "PURL": "pkg:pypi/rpds-py@0.30.0",
+ "UID": "894f633cf7410059"
+ },
+ "Version": "0.30.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/rpds_py-0.30.0.dist-info/METADATA"
+ },
+ {
+ "Name": "s3transfer",
+ "Identifier": {
+ "PURL": "pkg:pypi/s3transfer@0.19.2",
+ "UID": "ee16e76cffe26363"
+ },
+ "Version": "0.19.2",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/s3transfer-0.19.2.dist-info/METADATA"
+ },
+ {
+ "Name": "six",
+ "Identifier": {
+ "PURL": "pkg:pypi/six@1.17.0",
+ "UID": "3714ed1c9848d5c6"
+ },
+ "Version": "1.17.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA"
+ },
+ {
+ "Name": "sniffio",
+ "Identifier": {
+ "PURL": "pkg:pypi/sniffio@1.3.1",
+ "UID": "143876ac193a8cad"
+ },
+ "Version": "1.3.1",
+ "Licenses": [
+ "MIT",
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/METADATA"
+ },
+ {
+ "Name": "sse-starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/sse-starlette@3.4.4",
+ "UID": "3f2a0e09c4935f68"
+ },
+ "Version": "3.4.4",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/sse_starlette-3.4.4.dist-info/METADATA"
+ },
+ {
+ "Name": "starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/starlette@1.3.1",
+ "UID": "1b21780decf6d95c"
+ },
+ "Version": "1.3.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/starlette-1.3.1.dist-info/METADATA"
+ },
+ {
+ "Name": "tqdm",
+ "Identifier": {
+ "PURL": "pkg:pypi/tqdm@4.67.3",
+ "UID": "bf2ffdca8ce62d66"
+ },
+ "Version": "4.67.3",
+ "Licenses": [
+ "MPL-2.0 AND MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/tqdm-4.67.3.dist-info/METADATA"
+ },
+ {
+ "Name": "typing-inspection",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-inspection@0.4.2",
+ "UID": "74af1e4539fb7b0a"
+ },
+ "Version": "0.4.2",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/typing_inspection-0.4.2.dist-info/METADATA"
+ },
+ {
+ "Name": "typing_extensions",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-extensions@4.15.0",
+ "UID": "6e16270e669f33cc"
+ },
+ "Version": "4.15.0",
+ "Licenses": [
+ "PSF-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/typing_extensions-4.15.0.dist-info/METADATA"
+ },
+ {
+ "Name": "urllib3",
+ "Identifier": {
+ "PURL": "pkg:pypi/urllib3@2.7.0",
+ "UID": "1ee89e08a0369db1"
+ },
+ "Version": "2.7.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/urllib3-2.7.0.dist-info/METADATA"
+ },
+ {
+ "Name": "uvicorn",
+ "Identifier": {
+ "PURL": "pkg:pypi/uvicorn@0.47.0",
+ "UID": "5e575d6807ee87fc"
+ },
+ "Version": "0.47.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/uvicorn-0.47.0.dist-info/METADATA"
+ }
+ ]
+ }
+ ]
+}
diff --git a/release/evidence/v2.0.0-review/manifest.json b/release/evidence/v2.0.0-review/manifest.json
new file mode 100644
index 0000000..eaf7c6f
--- /dev/null
+++ b/release/evidence/v2.0.0-review/manifest.json
@@ -0,0 +1,86 @@
+{
+ "schema": "openrath.review-evidence/1",
+ "generated_at": "2026-07-28T12:19:38+08:00",
+ "baseline_commit": "ec0ac921fe95de4d925113f63b4bda0934880f42",
+ "implementation_commit": "51a26c4a23850876548c61340da2d2da3bc834ce",
+ "branch": "codex/v2-review-remediation",
+ "intended_release": "2.0.0",
+ "package_version": "1.3.0",
+ "release_approved": false,
+ "source_tree_clean_at_implementation_commit": true,
+ "artifacts": {
+ "wheel": {
+ "path": "dist/openrath-1.3.0-py3-none-any.whl",
+ "sha256": "296705e4af199393ff81cfeab0034faa07c3366bb635bc25e8e2c1f19324f388"
+ },
+ "sdist": {
+ "path": "dist/openrath-1.3.0.tar.gz",
+ "sha256": "d34ca3adf76e5b3c99bde107a884189699c0d9de7df6da88d1b4a57217581016"
+ },
+ "openapi": {
+ "path": "deploy/docs/openapi-v2.json",
+ "sha256": "d2af9657b8c7346d1d8ef1097418af0548fc9ad6ca2817c82eb5895497c1d648"
+ },
+ "local_image": {
+ "reference": "openrath:review",
+ "local_image_id": "sha256:181247207c0f57e438c42676579a32d98cd7f9ea66c2c6b1bf2c233526723b14",
+ "registry_digest": null
+ },
+ "sbom": {
+ "path": "release/evidence/v2.0.0-review/openrath-v2-review.sbom.cdx.json",
+ "sha256": "cd38253ce326ee89c2e1075a2aa39aa7374cbdefe840c0e087527f198e9398ad"
+ },
+ "image_scan": {
+ "path": "release/evidence/v2.0.0-review/image-scan-high-critical.json",
+ "sha256": "824fd0f2b1eff05156c58ba16df4c08ca2eacb7635536291a37405e291c3afdb",
+ "fixed_high_or_critical_findings": 0
+ },
+ "repository_secret_scan": {
+ "path": "release/evidence/v2.0.0-review/repository-secret-scan.json",
+ "sha256": "8fc6fd9d2056aa23cc1d3e1719364096fccfae487164a990ea201df085df281d",
+ "findings": 0
+ }
+ },
+ "validation": {
+ "ruff": "passed",
+ "mypy_source_files": 166,
+ "offline_tests": {
+ "passed": 1043,
+ "skipped": 20,
+ "failed": 0
+ },
+ "openapi_contract_tests": {
+ "passed": 2,
+ "failed": 0
+ },
+ "opensandbox_real": {
+ "full_run_passed": 45,
+ "full_run_skipped": 3,
+ "environment_sensitive_timing_failures": 1,
+ "corrected_focused_rerun_passed": 1
+ },
+ "postgres_redis_s3_integration": {
+ "passed": 10,
+ "failed": 0
+ },
+ "dependency_audits": {
+ "production": "no known vulnerabilities",
+ "all_extras_and_groups": "no known vulnerabilities"
+ },
+ "review_soak": {
+ "duration_seconds": 10.032811900004162,
+ "completed_runs": 143,
+ "failed_runs": 0,
+ "profile": "sqlite-single-worker-one-step"
+ }
+ },
+ "blocking_gates": [
+ "approved live LLM/provider lifecycle",
+ "approved live OpenViking lifecycle",
+ "published immutable OpenRath registry image digest",
+ "eight-hour target-like soak",
+ "one-to-four worker scale test",
+ "target-cluster backup/restore and rollout/rollback drills",
+ "final CI and evidence regeneration on the frozen RC commit"
+ ]
+}
diff --git a/release/evidence/v2.0.0-review/openrath-v2-review.sbom.cdx.json b/release/evidence/v2.0.0-review/openrath-v2-review.sbom.cdx.json
new file mode 100644
index 0000000..96c1b38
--- /dev/null
+++ b/release/evidence/v2.0.0-review/openrath-v2-review.sbom.cdx.json
@@ -0,0 +1,9408 @@
+{
+ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.6",
+ "serialNumber": "urn:uuid:c25b7b2c-da51-49ea-b75a-85137e8113de",
+ "version": 1,
+ "metadata": {
+ "timestamp": "2026-07-28T04:18:22+00:00",
+ "tools": {
+ "components": [
+ {
+ "type": "application",
+ "manufacturer": {
+ "name": "Aqua Security Software Ltd."
+ },
+ "group": "aquasecurity",
+ "name": "trivy",
+ "version": "0.67.2"
+ }
+ ]
+ },
+ "component": {
+ "bom-ref": "f11d519f-8176-41a9-9ea2-c3f1841f1fa9",
+ "type": "container",
+ "name": "openrath:review",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:f2776a24e2368b14a6e05e79b2abd1f2b85fb5217de0b9b924fb2a926538d169"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:ImageID",
+ "value": "sha256:181247207c0f57e438c42676579a32d98cd7f9ea66c2c6b1bf2c233526723b14"
+ },
+ {
+ "name": "aquasecurity:trivy:RepoTag",
+ "value": "openrath:review"
+ },
+ {
+ "name": "aquasecurity:trivy:SchemaVersion",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:Size",
+ "value": "239066624"
+ }
+ ]
+ }
+ },
+ "components": [
+ {
+ "bom-ref": "f68ad4e5-afcc-4b65-9e7f-75fa6ce2c944",
+ "type": "operating-system",
+ "name": "debian",
+ "version": "13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:Class",
+ "value": "os-pkgs"
+ },
+ {
+ "name": "aquasecurity:trivy:Type",
+ "value": "debian"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Adduser Developers "
+ },
+ "name": "adduser",
+ "version": "3.152",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "adduser@3.152"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "adduser"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.152"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "APT Development Team "
+ },
+ "name": "apt",
+ "version": "3.0.3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "curl"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "apt@3.0.3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "apt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.0.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Santiago Vila "
+ },
+ "name": "base-files",
+ "version": "13.8+deb13u6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "verbatim"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "base-files@13.8+deb13u6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "base-files"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "13.8+deb13u6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "base-passwd",
+ "version": "3.6.7",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "base-passwd@3.6.7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "base-passwd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.6.7"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "bash",
+ "version": "5.2.37-2+b9",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "name": "Latex2e"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "permissive"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "bash@5.2.37-2+b9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "bash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.2.37"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "bsdutils",
+ "version": "1:2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "bsdutils@1:2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Julien Cristau "
+ },
+ "name": "ca-certificates",
+ "version": "20250419",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MPL-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ca-certificates@20250419"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ca-certificates"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "20250419"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Michael Stone "
+ },
+ "name": "coreutils",
+ "version": "9.7-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "coreutils@9.7-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "coreutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "9.7"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Andrej Shadura "
+ },
+ "name": "dash",
+ "version": "0.5.12-12",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "dash@0.5.12-12"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "dash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.5.12"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debconf Developers "
+ },
+ "name": "debconf",
+ "version": "1.5.91",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debconf@1.5.91"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debconf"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.91"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Release Team "
+ },
+ "name": "debian-archive-keyring",
+ "version": "2025.1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debian-archive-keyring@2025.1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debian-archive-keyring"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2025.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ileana Dumitrescu "
+ },
+ "name": "debianutils",
+ "version": "5.23.2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "SMAIL-GPL"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debianutils@5.23.2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debianutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.23.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Santiago Vila "
+ },
+ "name": "diffutils",
+ "version": "1:3.10-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH texinfo-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "diffutils@1:3.10-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "diffutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Dpkg Developers "
+ },
+ "name": "dpkg",
+ "version": "1.22.22",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-s-s-d"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "dpkg@1.22.22"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "dpkg"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.22.22"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Andreas Metzler "
+ },
+ "name": "findutils",
+ "version": "4.10.0-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH Autoconf-data-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Autoconf-data-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH automake-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-2.2-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "findutils@4.10.0-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "findutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.10.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "gcc-14-base",
+ "version": "14.2.0-19",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.2-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "gcc-14-base@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Anibal Monsalve Salazar "
+ },
+ "name": "grep",
+ "version": "3.11-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "grep@3.11-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "grep"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.11"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Milan Kupcevic "
+ },
+ "name": "gzip",
+ "version": "1.13-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GFDL-1.3--no-invariant"
+ }
+ },
+ {
+ "license": {
+ "name": "FSF-manpages"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GFDL-3"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "gzip@1.13-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gzip"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Michael Meskes "
+ },
+ "name": "hostname",
+ "version": "3.25",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "hostname@3.25"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "hostname"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.25"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "init-system-helpers",
+ "version": "1.69~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "init-system-helpers@1.69~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "init-system-helpers"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.69~deb13u1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libacl1",
+ "version": "2.3.2-2+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libacl1@2.3.2-2+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "acl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.3.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "APT Development Team "
+ },
+ "name": "libapt-pkg7.0",
+ "version": "3.0.3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "curl"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libapt-pkg7.0@3.0.3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "apt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.0.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libattr1",
+ "version": "1:2.5.2-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libattr1@1:2.5.2-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "attr"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.5.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Laurent Bigonville "
+ },
+ "name": "libaudit-common",
+ "version": "1:4.0.2-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libaudit-common@1:4.0.2-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "audit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.0.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Laurent Bigonville "
+ },
+ "name": "libaudit1",
+ "version": "1:4.0.2-2+b2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libaudit1@1:4.0.2-2+b2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "audit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.0.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libblkid1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libblkid1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libbsd0",
+ "version": "0.12.2-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Regents"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause-NetBSD"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-author"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-John-Birrell"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-5-clause-Peter-Wemm"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-2-clause-verbatim"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-2-clause-author"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-Original"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libbsd0@0.12.2-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libbsd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.12.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Anibal Monsalve Salazar "
+ },
+ "name": "libbz2-1.0",
+ "version": "1.0.8-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libbz2-1.0@1.0.8-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "bzip2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.0.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "libc-bin",
+ "version": "2.41-12+deb13u3",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "LGPL-2.1-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "Carnegie"
+ }
+ },
+ {
+ "license": {
+ "name": "Inner-Net"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-like-Lord"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-like-Spencer"
+ }
+ },
+ {
+ "license": {
+ "name": "PCRE"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Carnegie"
+ }
+ },
+ {
+ "license": {
+ "id": "Unicode-DFS-2016"
+ }
+ },
+ {
+ "license": {
+ "id": "BSL-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "SunPro"
+ }
+ },
+ {
+ "license": {
+ "name": "CORE-MATH"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Berkeley"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-WIDE"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Oracle"
+ }
+ },
+ {
+ "license": {
+ "name": "DEC"
+ }
+ },
+ {
+ "license": {
+ "name": "IBM"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Univ-Coimbra"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libc-bin@2.41-12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "glibc"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "libc6",
+ "version": "2.41-12+deb13u3",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "LGPL-2.1-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "Carnegie"
+ }
+ },
+ {
+ "license": {
+ "name": "Inner-Net"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-like-Lord"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-like-Spencer"
+ }
+ },
+ {
+ "license": {
+ "name": "PCRE"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Carnegie"
+ }
+ },
+ {
+ "license": {
+ "id": "Unicode-DFS-2016"
+ }
+ },
+ {
+ "license": {
+ "id": "BSL-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "SunPro"
+ }
+ },
+ {
+ "license": {
+ "name": "CORE-MATH"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Berkeley"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-WIDE"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Oracle"
+ }
+ },
+ {
+ "license": {
+ "name": "DEC"
+ }
+ },
+ {
+ "license": {
+ "name": "IBM"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Univ-Coimbra"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libc6@2.41-12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "glibc"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Håvard F. Aasen "
+ },
+ "name": "libcap-ng0",
+ "version": "0.8.5-4+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcap-ng0@0.8.5-4+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcap-ng"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.8.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Christian Kastner "
+ },
+ "name": "libcap2",
+ "version": "1:2.75-10+deb13u1+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcap2@1:2.75-10+deb13u1+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcap2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "10+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.75"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Marco d'Itri "
+ },
+ "name": "libcrypt1",
+ "version": "1:4.4.38-1",
+ "purl": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcrypt1@1:4.4.38-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libxcrypt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.4.38"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian QA Group "
+ },
+ "name": "libdb5.3t64",
+ "version": "5.3.28+dfsg2-9",
+ "licenses": [
+ {
+ "license": {
+ "id": "Sleepycat"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MS-PL"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-old"
+ }
+ },
+ {
+ "license": {
+ "name": "TCL-like"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-fjord"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libdb5.3t64@5.3.28+dfsg2-9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "db5.3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.3.28+dfsg2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Install System Team "
+ },
+ "name": "libdebconfclient0",
+ "version": "0.280",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libdebconfclient0@0.280"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "cdebconf"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.280"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libffi8",
+ "version": "3.4.8-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "MPL-1.1"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libffi8@3.4.8-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libffi"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.4.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libgcc-s1",
+ "version": "14.2.0-19",
+ "purl": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgcc-s1@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Nicolas Mora "
+ },
+ "name": "libgdbm6t64",
+ "version": "1.24-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgdbm6t64@1.24-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gdbm"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.24"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Science Maintainers "
+ },
+ "name": "libgmp10",
+ "version": "2:6.3.0+dfsg-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgmp10@2:6.3.0+dfsg-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gmp"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.3.0+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Magnus Holmgren "
+ },
+ "name": "libhogweed6t64",
+ "version": "3.10.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GAP"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libhogweed6t64@3.10.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "nettle"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "liblastlog2-2",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblastlog2-2@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Nobuhiro Iwamatsu "
+ },
+ "name": "liblz4-1",
+ "version": "1.10.0-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblz4-1@1.10.0-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "lz4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.10.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sebastian Andrzej Siewior "
+ },
+ "name": "liblzma5",
+ "version": "5.8.1-1+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "0BSD"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Autoconf-exception-macro"
+ }
+ },
+ {
+ "license": {
+ "name": "none"
+ }
+ },
+ {
+ "license": {
+ "name": "PD"
+ }
+ },
+ {
+ "license": {
+ "name": "permissive-nowarranty"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFUL"
+ }
+ },
+ {
+ "license": {
+ "name": "noderivs"
+ }
+ },
+ {
+ "license": {
+ "name": "PD-debian"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblzma5@5.8.1-1+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "xz-utils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libmd0",
+ "version": "1.1.0-2+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Aaron-D-Gifford"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause-NetBSD"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-md4"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-md5"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-sha1"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libmd0@1.1.0-2+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libmd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.1.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libmount1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libmount1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "libncursesw6",
+ "version": "6.5+20250216-2",
+ "purl": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libncursesw6@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Magnus Holmgren "
+ },
+ "name": "libnettle8t64",
+ "version": "3.10.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GAP"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libnettle8t64@3.10.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "nettle"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-modules-bin",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-modules-bin@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-modules",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-modules@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-runtime",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-runtime@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam0g",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam0g@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthew Vernon "
+ },
+ "name": "libpcre2-8-0",
+ "version": "10.46-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "BSD-3-clause-Cambridge WITH BINARY-LIBRARY-LIKE-PACKAGES-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpcre2-8-0@10.46-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pcre2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "10.46"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "libreadline8t64",
+ "version": "8.2-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-no-attribution"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libreadline8t64@8.2-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "readline"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Kees Cook "
+ },
+ "name": "libseccomp2",
+ "version": "2.6.0-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libseccomp2@2.6.0-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libseccomp"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.6.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libselinux1",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libselinux1@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libselinux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsemanage-common",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsemanage-common@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsemanage"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsemanage2",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsemanage2@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsemanage"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsepol2",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsepol2@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsepol"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libsmartcols1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsmartcols1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Laszlo Boszormenyi (GCS) "
+ },
+ "name": "libsqlite3-0",
+ "version": "3.46.1-7+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsqlite3-0@3.46.1-7+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sqlite3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "7+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.46.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "libssl3t64",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libssl3t64@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libstdc++6",
+ "version": "14.2.0-19",
+ "purl": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libstdc++6@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "libsystemd0",
+ "version": "257.13-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH Linux-syscall-note-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsystemd0@257.13-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "systemd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "257.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "libtinfo6",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libtinfo6@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "libudev1",
+ "version": "257.13-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH Linux-syscall-note-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libudev1@257.13-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "systemd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "257.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libuuid1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libuuid1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Josue Ortega "
+ },
+ "name": "libxxhash0",
+ "version": "0.8.3-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libxxhash0@0.8.3-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "xxhash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.8.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "RPM packaging team "
+ },
+ "name": "libzstd1",
+ "version": "1.5.7+dfsg-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libzstd1@1.5.7+dfsg-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libzstd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.7+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "login.defs",
+ "version": "1:4.17.4-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "login.defs@1:4.17.4-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "shadow"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.17.4"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "login",
+ "version": "1:4.16.0-2+really2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "login@1:4.16.0-2+really2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Boyuan Yang "
+ },
+ "name": "mawk",
+ "version": "1.3.4.20250131-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "CC-BY-3.0"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "mawk@1.3.4.20250131-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "mawk"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.4.20250131"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "mount",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "mount@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "ncurses-base",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ncurses-base@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "ncurses-bin",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ncurses-bin@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Marco d'Itri "
+ },
+ "name": "netbase",
+ "version": "6.5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "netbase@6.5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "netbase"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "openssl-provider-legacy",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "openssl-provider-legacy@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "openssl",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "openssl@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "passwd",
+ "version": "1:4.17.4-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "passwd@1:4.17.4-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "shadow"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.17.4"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Niko Tyni "
+ },
+ "name": "perl-base",
+ "version": "5.40.1-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "REGCOMP"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH bison-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "Unicode"
+ }
+ },
+ {
+ "license": {
+ "name": "BZIP"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-Clause WITH weird-numbering"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "TEXT-TABS"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-4-clause-POWERDOG"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-GENERIC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "SDBM-PUBLIC-DOMAIN"
+ }
+ },
+ {
+ "license": {
+ "name": "DONT-CHANGE-THE-GPL"
+ }
+ },
+ {
+ "license": {
+ "name": "Artistic-dist"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "Artistic-2"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "perl-base@5.40.1-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "perl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.40.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "readline-common",
+ "version": "8.2-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-no-attribution"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "readline-common@8.2-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "readline"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Clint Adams "
+ },
+ "name": "sed",
+ "version": "4.9-2+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "name": "BSL-1"
+ }
+ },
+ {
+ "license": {
+ "name": "pcre"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sed@4.9-2+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sed"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.9"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Rust Maintainers "
+ },
+ "name": "sqv",
+ "version": "1.3.0-3+b2",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sqv@1.3.0-3+b2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "rust-sequoia-sqv"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian sysvinit maintainers "
+ },
+ "name": "sysvinit-utils",
+ "version": "3.14-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sysvinit-utils@3.14-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sysvinit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.14"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Janos Lenart "
+ },
+ "name": "tar",
+ "version": "1.35+dfsg-3.1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "tar@1.35+dfsg-3.1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "tar"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3.1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.35+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "tzdata",
+ "version": "2026b-0+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "tzdata@2026b-0+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "tzdata"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "0+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2026b"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "util-linux",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "util-linux@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Mark Brown "
+ },
+ "name": "zlib1g",
+ "version": "1:1.3.dfsg+really1.3.1-1+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "zlib"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.dfsg+really1.3.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/annotated-types@0.7.0",
+ "type": "library",
+ "name": "annotated-types",
+ "version": "0.7.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "b11011181822ac765c9f66c8aa42c26952de6a96"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/annotated-types@0.7.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/anthropic@0.104.1",
+ "type": "library",
+ "name": "anthropic",
+ "version": "0.104.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "6a0fce5932599b482bf25ed3db3c06e9211f1358"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/anthropic@0.104.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/anthropic-0.104.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/anyio@4.13.0",
+ "type": "library",
+ "name": "anyio",
+ "version": "4.13.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5f30168435645daddf756ecef34992631c6e778b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/anyio@4.13.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/anyio-4.13.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/attrs@26.1.0",
+ "type": "library",
+ "name": "attrs",
+ "version": "26.1.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "89068272cc1dc340d8fd910a62be241c42414339"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/attrs@26.1.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/attrs-26.1.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/boto3@1.43.56",
+ "type": "library",
+ "name": "boto3",
+ "version": "1.43.56",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f5c7842f2414d0cd2cefdb918d07c52018450ff7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/boto3@1.43.56",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/boto3-1.43.56.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/botocore@1.43.56",
+ "type": "library",
+ "name": "botocore",
+ "version": "1.43.56",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "b8760d1db82eba72c06ec96252b62d541a21b09e"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/botocore@1.43.56",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/botocore-1.43.56.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/certifi@2026.5.20",
+ "type": "library",
+ "name": "certifi",
+ "version": "2026.5.20",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cb42a7b0ba6491d51e71ff594a39bfaf5b8f9d22"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MPL-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/certifi@2026.5.20",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/certifi-2026.5.20.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/cffi@2.0.0",
+ "type": "library",
+ "name": "cffi",
+ "version": "2.0.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "87e9c9d276c4f4c31f5a314d6a5472f45655674c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/cffi@2.0.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/cffi-2.0.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/click@8.4.1",
+ "type": "library",
+ "name": "click",
+ "version": "8.4.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "c486957c59cc28072021bdcfe6d681e9ddafc860"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/click@8.4.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/click-8.4.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/cryptography@49.0.0",
+ "type": "library",
+ "name": "cryptography",
+ "version": "49.0.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "739372eb2cc71602103a206e7a42a926930cecb6"
+ }
+ ],
+ "licenses": [
+ {
+ "expression": "Apache-2.0 OR BSD-3-Clause"
+ }
+ ],
+ "purl": "pkg:pypi/cryptography@49.0.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/cryptography-49.0.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/distro@1.9.0",
+ "type": "library",
+ "name": "distro",
+ "version": "1.9.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ce14620cf14e15a64d2ff574796543f99619e7f3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/distro@1.9.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/distro-1.9.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/docstring-parser@0.18.0",
+ "type": "library",
+ "name": "docstring_parser",
+ "version": "0.18.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cd475f73b404c399cf87b9fb990fc14669479d24"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/docstring-parser@0.18.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/docstring_parser-0.18.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/h11@0.16.0",
+ "type": "library",
+ "name": "h11",
+ "version": "0.16.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5d41eddffefef5f6e8ff383a2537e81a38a37807"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/h11@0.16.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/h11-0.16.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpcore@1.0.9",
+ "type": "library",
+ "name": "httpcore",
+ "version": "1.0.9",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "2981d359ae33f31d339189a9680db85785339a56"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpcore@1.0.9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpcore-1.0.9.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpx-sse@0.4.3",
+ "type": "library",
+ "name": "httpx-sse",
+ "version": "0.4.3",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "df05446be58f0a3a306e50c7ceebef24bb383a6d"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpx-sse@0.4.3",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpx_sse-0.4.3.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpx@0.28.1",
+ "type": "library",
+ "name": "httpx",
+ "version": "0.28.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "537da7e4f29438278e124e10e02d1a500fe33bcc"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpx@0.28.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/idna@3.16",
+ "type": "library",
+ "name": "idna",
+ "version": "3.16",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "191a7bf1dac83b0cc997024ebb4b8da5c962ae5b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/idna@3.16",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/idna-3.16.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jiter@0.15.0",
+ "type": "library",
+ "name": "jiter",
+ "version": "0.15.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9de68ecc913d85eafa70a1252b2f5b1b2d2829f5"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jiter@0.15.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jiter-0.15.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jmespath@1.1.0",
+ "type": "library",
+ "name": "jmespath",
+ "version": "1.1.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d3f297922cf04b0cc127a18994ad6e6b947f0cc7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jmespath@1.1.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jmespath-1.1.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "type": "library",
+ "name": "jsonschema-specifications",
+ "version": "2025.9.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ac33f477be9d3336ae67bc454f68a9ff39c91cf3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jsonschema@4.26.0",
+ "type": "library",
+ "name": "jsonschema",
+ "version": "4.26.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "94b3d1a46cf55d74e42c401eaf4a4b71c76cee31"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jsonschema@4.26.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jsonschema-4.26.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/mcp@1.28.1",
+ "type": "library",
+ "name": "mcp",
+ "version": "1.28.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "22fedbbf2f1d94917eba0c0c156781325bd3d786"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/mcp@1.28.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/mcp-1.28.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/openai@2.38.0",
+ "type": "library",
+ "name": "openai",
+ "version": "2.38.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ea17f685d13b1a896fb055b3bedbfcb5ed8da63a"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/openai@2.38.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/openai-2.38.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/openrath@1.3.0",
+ "type": "library",
+ "name": "openrath",
+ "version": "1.3.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "8009f0cff7caeee9b8be0fe36779e85219f6d112"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/openrath@1.3.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/openrath-1.3.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-api@1.42.1",
+ "type": "library",
+ "name": "opentelemetry-api",
+ "version": "1.42.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "a54ebbf560cfb13acfd3d7f7a5c385f03e36be08"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-api@1.42.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_api-1.42.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "type": "library",
+ "name": "opentelemetry-sdk",
+ "version": "1.42.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cdfb9c90d3e4765c62ffce81a835445a8efef7c4"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_sdk-1.42.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "type": "library",
+ "name": "opentelemetry-semantic-conventions",
+ "version": "0.63b1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5c7aaa298ae1ba489d7214ebec1427bd3f602556"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_semantic_conventions-0.63b1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pip@25.0.1",
+ "type": "library",
+ "name": "pip",
+ "version": "25.0.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "7e11d8be93f8cb02d43d078fc3a87cceb5b6cac9"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pip@25.0.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "usr/local/lib/python3.12/site-packages/pip-25.0.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg-binary@3.3.4",
+ "type": "library",
+ "name": "psycopg-binary",
+ "version": "3.3.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "e8c69d729c969a8a81834cce24f8947ad560813d"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg-binary@3.3.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg_binary-3.3.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg-pool@3.3.1",
+ "type": "library",
+ "name": "psycopg-pool",
+ "version": "3.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "60d07aa411067306f5244d0481227a78a5b11135"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg-pool@3.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg_pool-3.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg@3.3.4",
+ "type": "library",
+ "name": "psycopg",
+ "version": "3.3.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "dc38178dd59b090117f63d60bc627e6a168205c8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg@3.3.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg-3.3.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "type": "library",
+ "name": "psycopg_binary",
+ "version": "3.3.4",
+ "purl": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "psycopg_binary@3.3.4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "type": "library",
+ "name": "psycopg_binary",
+ "version": "3.3.4",
+ "purl": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "psycopg_binary@3.3.4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pycparser@3.0",
+ "type": "library",
+ "name": "pycparser",
+ "version": "3.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ec46323dcd4dd2f7742b74b09cc0b030e330e46f"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pycparser@3.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pycparser-3.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic-core@2.46.4",
+ "type": "library",
+ "name": "pydantic_core",
+ "version": "2.46.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f44318e9ae79f745f1f5a7a59b43044ab6fff485"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic-core@2.46.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic_core-2.46.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic-settings@2.14.2",
+ "type": "library",
+ "name": "pydantic-settings",
+ "version": "2.14.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cdbe89c33fcb95fd706f07af245dea549c06d52b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic-settings@2.14.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic_settings-2.14.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic@2.13.4",
+ "type": "library",
+ "name": "pydantic",
+ "version": "2.13.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "291e482df82749c7e52c21e8275551f04de3034b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic@2.13.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic-2.13.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pyjwt@2.13.0",
+ "type": "library",
+ "name": "PyJWT",
+ "version": "2.13.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "78125d2bb60e70bc168fd8787075ceb6a69d4f65"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pyjwt@2.13.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pyjwt-2.13.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "type": "library",
+ "name": "python-dateutil",
+ "version": "2.9.0.post0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "7a3c35abd86cd96034d5afb0d4b241dc9e13e6f8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-dotenv@1.2.2",
+ "type": "library",
+ "name": "python-dotenv",
+ "version": "1.2.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "a70b92340410dfaf8ce628e658f176278fa2e557"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-dotenv@1.2.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_dotenv-1.2.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-multipart@0.0.32",
+ "type": "library",
+ "name": "python-multipart",
+ "version": "0.0.32",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9f79572b3702bdac7487183b498470341276b17e"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-multipart@0.0.32",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_multipart-0.0.32.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/redis@6.4.0",
+ "type": "library",
+ "name": "redis",
+ "version": "6.4.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9a3de9ffc83addb0d845a4f16c6a415db91a3eda"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/redis@6.4.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/redis-6.4.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/referencing@0.37.0",
+ "type": "library",
+ "name": "referencing",
+ "version": "0.37.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f6fa004340bef5d23995b09dab75ce12e3f367a7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/referencing@0.37.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/referencing-0.37.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/rpds-py@0.30.0",
+ "type": "library",
+ "name": "rpds-py",
+ "version": "0.30.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9eef46c842a0ca6229680d7bfc1272958efdcc5a"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/rpds-py@0.30.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/rpds_py-0.30.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/s3transfer@0.19.2",
+ "type": "library",
+ "name": "s3transfer",
+ "version": "0.19.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "453d1af3240f56bb5d0bd093eb3d21a250cc5777"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/s3transfer@0.19.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/s3transfer-0.19.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/six@1.17.0",
+ "type": "library",
+ "name": "six",
+ "version": "1.17.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "483a26554261f6c839703c0e1183f3ef33ff97f1"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/six@1.17.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/sniffio@1.3.1",
+ "type": "library",
+ "name": "sniffio",
+ "version": "1.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "bc1d7aead770fe23c8d22666b84558edb3686da3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/sniffio@1.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/sse-starlette@3.4.4",
+ "type": "library",
+ "name": "sse-starlette",
+ "version": "3.4.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "58e4ad3946eafb572e0219f89bb599bee2b7cca2"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/sse-starlette@3.4.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/sse_starlette-3.4.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/starlette@1.3.1",
+ "type": "library",
+ "name": "starlette",
+ "version": "1.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9e43f99dc64bcf4498d65999f9cb36a40fa5e94c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/starlette@1.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/starlette-1.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/tqdm@4.67.3",
+ "type": "library",
+ "name": "tqdm",
+ "version": "4.67.3",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "0135af1981d2b0f1326020f991192d869693b873"
+ }
+ ],
+ "licenses": [
+ {
+ "expression": "MPL-2.0 AND MIT"
+ }
+ ],
+ "purl": "pkg:pypi/tqdm@4.67.3",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/tqdm-4.67.3.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/typing-extensions@4.15.0",
+ "type": "library",
+ "name": "typing_extensions",
+ "version": "4.15.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "c5c2ce18351f8f2ae0f4a6f7c84c523f342010ee"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "name": "PSF-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/typing-extensions@4.15.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/typing_extensions-4.15.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/typing-inspection@0.4.2",
+ "type": "library",
+ "name": "typing-inspection",
+ "version": "0.4.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "455fdb9c8e246ba02c2a28655287401b62028b60"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/typing-inspection@0.4.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/typing_inspection-0.4.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/urllib3@2.7.0",
+ "type": "library",
+ "name": "urllib3",
+ "version": "2.7.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d20520d0598c114ced8d55ed14209a2a3bbee22c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/urllib3@2.7.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/urllib3-2.7.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/uvicorn@0.47.0",
+ "type": "library",
+ "name": "uvicorn",
+ "version": "0.47.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f55652a6d9d6137b9be4cfc40b4c3d30b63717f8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/uvicorn@0.47.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/uvicorn-0.47.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "type": "library",
+ "name": "cyrus-sasl-lib",
+ "version": "2.1.26-24.el7_9",
+ "purl": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "cyrus-sasl-lib@2.1.26-24.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "cyrus-sasl-lib"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "24.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.1.26"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "type": "library",
+ "name": "keyutils-libs",
+ "version": "1.5.8-3.el7",
+ "purl": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "keyutils-libs@1.5.8-3.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "keyutils-libs"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#e140566d00db0f579c699b6d9e76106beaf31c2b7fb445a03fa070ecbba23222",
+ "type": "library",
+ "name": "krb5-libs",
+ "version": "1.15.1-55.el7_9",
+ "purl": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "krb5-libs@1.15.1-55.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "krb5-libs"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "55.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.15.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "type": "library",
+ "name": "libcom_err",
+ "version": "1.42.9-19.el7",
+ "purl": "pkg:rpm/centos/libcom_err@1.42.9-19.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcom_err@1.42.9-19.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcom_err"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.42.9"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "type": "library",
+ "name": "libselinux",
+ "version": "2.5-15.el7",
+ "purl": "pkg:rpm/centos/libselinux@2.5-15.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libselinux@2.5-15.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libselinux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "15.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72",
+ "type": "library",
+ "name": "pcre",
+ "version": "8.32-17.el7",
+ "purl": "pkg:rpm/centos/pcre@8.32-17.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:b8469e6975a0e7c33e72820e0400106aa5a6ac23f24fc64a3e3ab85b4713777f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "pcre@8.32-17.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pcre"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "17.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.32"
+ }
+ ]
+ }
+ ],
+ "dependencies": [
+ {
+ "ref": "f11d519f-8176-41a9-9ea2-c3f1841f1fa9",
+ "dependsOn": [
+ "f68ad4e5-afcc-4b65-9e7f-75fa6ce2c944",
+ "pkg:pypi/annotated-types@0.7.0",
+ "pkg:pypi/anthropic@0.104.1",
+ "pkg:pypi/anyio@4.13.0",
+ "pkg:pypi/attrs@26.1.0",
+ "pkg:pypi/boto3@1.43.56",
+ "pkg:pypi/botocore@1.43.56",
+ "pkg:pypi/certifi@2026.5.20",
+ "pkg:pypi/cffi@2.0.0",
+ "pkg:pypi/click@8.4.1",
+ "pkg:pypi/cryptography@49.0.0",
+ "pkg:pypi/distro@1.9.0",
+ "pkg:pypi/docstring-parser@0.18.0",
+ "pkg:pypi/h11@0.16.0",
+ "pkg:pypi/httpcore@1.0.9",
+ "pkg:pypi/httpx-sse@0.4.3",
+ "pkg:pypi/httpx@0.28.1",
+ "pkg:pypi/idna@3.16",
+ "pkg:pypi/jiter@0.15.0",
+ "pkg:pypi/jmespath@1.1.0",
+ "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "pkg:pypi/jsonschema@4.26.0",
+ "pkg:pypi/mcp@1.28.1",
+ "pkg:pypi/openai@2.38.0",
+ "pkg:pypi/openrath@1.3.0",
+ "pkg:pypi/opentelemetry-api@1.42.1",
+ "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "pkg:pypi/pip@25.0.1",
+ "pkg:pypi/psycopg-binary@3.3.4",
+ "pkg:pypi/psycopg-pool@3.3.1",
+ "pkg:pypi/psycopg@3.3.4",
+ "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "pkg:pypi/pycparser@3.0",
+ "pkg:pypi/pydantic-core@2.46.4",
+ "pkg:pypi/pydantic-settings@2.14.2",
+ "pkg:pypi/pydantic@2.13.4",
+ "pkg:pypi/pyjwt@2.13.0",
+ "pkg:pypi/python-dateutil@2.9.0.post0",
+ "pkg:pypi/python-dotenv@1.2.2",
+ "pkg:pypi/python-multipart@0.0.32",
+ "pkg:pypi/redis@6.4.0",
+ "pkg:pypi/referencing@0.37.0",
+ "pkg:pypi/rpds-py@0.30.0",
+ "pkg:pypi/s3transfer@0.19.2",
+ "pkg:pypi/six@1.17.0",
+ "pkg:pypi/sniffio@1.3.1",
+ "pkg:pypi/sse-starlette@3.4.4",
+ "pkg:pypi/starlette@1.3.1",
+ "pkg:pypi/tqdm@4.67.3",
+ "pkg:pypi/typing-extensions@4.15.0",
+ "pkg:pypi/typing-inspection@0.4.2",
+ "pkg:pypi/urllib3@2.7.0",
+ "pkg:pypi/uvicorn@0.47.0"
+ ]
+ },
+ {
+ "ref": "f68ad4e5-afcc-4b65-9e7f-75fa6ce2c944",
+ "dependsOn": [
+ "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#e140566d00db0f579c699b6d9e76106beaf31c2b7fb445a03fa070ecbba23222",
+ "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:pypi/annotated-types@0.7.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/anthropic@0.104.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/anyio@4.13.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/attrs@26.1.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/boto3@1.43.56",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/botocore@1.43.56",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/certifi@2026.5.20",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/cffi@2.0.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/click@8.4.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/cryptography@49.0.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/distro@1.9.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/docstring-parser@0.18.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/h11@0.16.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpcore@1.0.9",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpx-sse@0.4.3",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpx@0.28.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/idna@3.16",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jiter@0.15.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jmespath@1.1.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jsonschema@4.26.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/mcp@1.28.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/openai@2.38.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/openrath@1.3.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-api@1.42.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pip@25.0.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg-binary@3.3.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg-pool@3.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg@3.3.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pycparser@3.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic-core@2.46.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic-settings@2.14.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic@2.13.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pyjwt@2.13.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-dotenv@1.2.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-multipart@0.0.32",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/redis@6.4.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/referencing@0.37.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/rpds-py@0.30.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/s3transfer@0.19.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/six@1.17.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/sniffio@1.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/sse-starlette@3.4.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/starlette@1.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/tqdm@4.67.3",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/typing-extensions@4.15.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/typing-inspection@0.4.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/urllib3@2.7.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/uvicorn@0.47.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#e140566d00db0f579c699b6d9e76106beaf31c2b7fb445a03fa070ecbba23222",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72",
+ "dependsOn": []
+ }
+ ],
+ "vulnerabilities": []
+}
diff --git a/release/evidence/v2.0.0-review/repository-secret-scan.json b/release/evidence/v2.0.0-review/repository-secret-scan.json
new file mode 100644
index 0000000..af2ad48
--- /dev/null
+++ b/release/evidence/v2.0.0-review/repository-secret-scan.json
@@ -0,0 +1,2733 @@
+{
+ "SchemaVersion": 2,
+ "CreatedAt": "2026-07-28T04:19:38.200413949Z",
+ "ArtifactName": "/workspace",
+ "ArtifactType": "filesystem",
+ "Results": [
+ {
+ "Target": "uv.lock",
+ "Class": "lang-pkgs",
+ "Type": "uv",
+ "Packages": [
+ {
+ "ID": "openrath@1.3.0",
+ "Name": "openrath",
+ "Identifier": {
+ "PURL": "pkg:pypi/openrath@1.3.0",
+ "UID": "21a32c273ff0fe1a"
+ },
+ "Version": "1.3.0",
+ "Relationship": "root",
+ "DependsOn": [
+ "aiohttp@3.14.3",
+ "anthropic@0.104.1",
+ "boto3@1.43.56",
+ "httpx@0.28.1",
+ "json-repair@0.61.7",
+ "litellm@1.85.1",
+ "mcp@1.28.1",
+ "openai@2.38.0",
+ "opensandbox-code-interpreter@0.1.2",
+ "opensandbox-server@0.2.2",
+ "opensandbox@0.1.15",
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-sdk@1.42.1",
+ "openviking@0.4.11",
+ "pillow@12.3.0",
+ "psycopg@3.3.4",
+ "pydantic@2.13.4",
+ "redis@6.4.0",
+ "soupsieve@2.9.1",
+ "starlette@1.3.1",
+ "uvicorn@0.47.0"
+ ]
+ },
+ {
+ "ID": "aiohttp@3.14.3",
+ "Name": "aiohttp",
+ "Identifier": {
+ "PURL": "pkg:pypi/aiohttp@3.14.3",
+ "UID": "4464ad9667e0cd52"
+ },
+ "Version": "3.14.3",
+ "Relationship": "direct",
+ "DependsOn": [
+ "aiohappyeyeballs@2.6.2",
+ "aiosignal@1.4.0",
+ "async-timeout@5.0.1",
+ "attrs@26.1.0",
+ "frozenlist@1.8.0",
+ "multidict@6.7.1",
+ "propcache@0.5.2",
+ "typing-extensions@4.15.0",
+ "yarl@1.24.2"
+ ]
+ },
+ {
+ "ID": "anthropic@0.104.1",
+ "Name": "anthropic",
+ "Identifier": {
+ "PURL": "pkg:pypi/anthropic@0.104.1",
+ "UID": "c5caf0507f8b092"
+ },
+ "Version": "0.104.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "distro@1.9.0",
+ "docstring-parser@0.18.0",
+ "httpx@0.28.1",
+ "jiter@0.15.0",
+ "pydantic@2.13.4",
+ "sniffio@1.3.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "boto3@1.43.56",
+ "Name": "boto3",
+ "Identifier": {
+ "PURL": "pkg:pypi/boto3@1.43.56",
+ "UID": "60cfd1667c43e1ea"
+ },
+ "Version": "1.43.56",
+ "Relationship": "direct",
+ "DependsOn": [
+ "botocore@1.43.56",
+ "jmespath@1.1.0",
+ "s3transfer@0.19.2"
+ ]
+ },
+ {
+ "ID": "httpx@0.28.1",
+ "Name": "httpx",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx@0.28.1",
+ "UID": "c2cb02c3c7a09654"
+ },
+ "Version": "0.28.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "certifi@2026.5.20",
+ "httpcore@1.0.9",
+ "idna@3.16",
+ "socksio@1.0.0"
+ ]
+ },
+ {
+ "ID": "json-repair@0.61.7",
+ "Name": "json-repair",
+ "Identifier": {
+ "PURL": "pkg:pypi/json-repair@0.61.7",
+ "UID": "45c719c89f96c8d6"
+ },
+ "Version": "0.61.7",
+ "Relationship": "direct"
+ },
+ {
+ "ID": "litellm@1.85.1",
+ "Name": "litellm",
+ "Identifier": {
+ "PURL": "pkg:pypi/litellm@1.85.1",
+ "UID": "d3fe251d8a6dd307"
+ },
+ "Version": "1.85.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "aiohttp@3.14.3",
+ "click@8.4.1",
+ "fastuuid@0.14.0",
+ "httpx@0.28.1",
+ "importlib-metadata@8.9.0",
+ "jinja2@3.1.6",
+ "jsonschema@4.26.0",
+ "openai@2.38.0",
+ "pydantic@2.13.4",
+ "python-dotenv@1.2.2",
+ "tiktoken@0.13.0",
+ "tokenizers@0.23.1"
+ ]
+ },
+ {
+ "ID": "mcp@1.28.1",
+ "Name": "mcp",
+ "Identifier": {
+ "PURL": "pkg:pypi/mcp@1.28.1",
+ "UID": "ffa4e48e15c9ecad"
+ },
+ "Version": "1.28.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "httpx-sse@0.4.3",
+ "httpx@0.28.1",
+ "jsonschema@4.26.0",
+ "pydantic-settings@2.14.2",
+ "pydantic@2.13.4",
+ "pyjwt@2.13.0",
+ "python-multipart@0.0.32",
+ "pywin32@311",
+ "sse-starlette@3.4.4",
+ "starlette@1.3.1",
+ "typing-extensions@4.15.0",
+ "typing-inspection@0.4.2",
+ "uvicorn@0.47.0"
+ ]
+ },
+ {
+ "ID": "openai@2.38.0",
+ "Name": "openai",
+ "Identifier": {
+ "PURL": "pkg:pypi/openai@2.38.0",
+ "UID": "a31f95dee98c2929"
+ },
+ "Version": "2.38.0",
+ "Relationship": "direct",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "distro@1.9.0",
+ "httpx@0.28.1",
+ "jiter@0.15.0",
+ "pydantic@2.13.4",
+ "sniffio@1.3.1",
+ "tqdm@4.67.3",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "opensandbox@0.1.15",
+ "Name": "opensandbox",
+ "Identifier": {
+ "PURL": "pkg:pypi/opensandbox@0.1.15",
+ "UID": "14d373b6037593d6"
+ },
+ "Version": "0.1.15",
+ "Relationship": "direct",
+ "DependsOn": [
+ "attrs@26.1.0",
+ "httpx@0.28.1",
+ "pydantic@2.13.4",
+ "python-dateutil@2.9.0.post0"
+ ]
+ },
+ {
+ "ID": "opensandbox-code-interpreter@0.1.2",
+ "Name": "opensandbox-code-interpreter",
+ "Identifier": {
+ "PURL": "pkg:pypi/opensandbox-code-interpreter@0.1.2",
+ "UID": "a384211ffdbd1ed3"
+ },
+ "Version": "0.1.2",
+ "Relationship": "direct",
+ "DependsOn": [
+ "opensandbox@0.1.15",
+ "pydantic@2.13.4"
+ ]
+ },
+ {
+ "ID": "opensandbox-server@0.2.2",
+ "Name": "opensandbox-server",
+ "Identifier": {
+ "PURL": "pkg:pypi/opensandbox-server@0.2.2",
+ "UID": "399d8dc3b4929198"
+ },
+ "Version": "0.2.2",
+ "Relationship": "direct",
+ "DependsOn": [
+ "docker@7.1.0",
+ "fastapi@0.139.0",
+ "httpx@0.28.1",
+ "kubernetes@36.0.0",
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-exporter-otlp-proto-http@1.42.1",
+ "opentelemetry-sdk@1.42.1",
+ "pydantic-settings@2.14.2",
+ "pydantic@2.13.4",
+ "python-multipart@0.0.32",
+ "pyyaml@6.0.3",
+ "redis@6.4.0",
+ "starlette@1.3.1",
+ "tomli@2.4.1",
+ "uvicorn@0.47.0",
+ "websockets@16.0"
+ ]
+ },
+ {
+ "ID": "opentelemetry-api@1.42.1",
+ "Name": "opentelemetry-api",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-api@1.42.1",
+ "UID": "f7c8ca6452999cc2"
+ },
+ "Version": "1.42.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "opentelemetry-sdk@1.42.1",
+ "Name": "opentelemetry-sdk",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "UID": "cbf596f7e9ece60"
+ },
+ "Version": "1.42.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-semantic-conventions@0.63b1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "openviking@0.4.11",
+ "Name": "openviking",
+ "Identifier": {
+ "PURL": "pkg:pypi/openviking@0.4.11",
+ "UID": "fbe7652768e34e80"
+ },
+ "Version": "0.4.11",
+ "Relationship": "direct",
+ "DependsOn": [
+ "apscheduler@3.11.2",
+ "argon2-cffi@25.1.0",
+ "charset-normalizer@3.4.7",
+ "cryptography@49.0.0",
+ "defusedxml@0.7.1",
+ "ebooklib@0.20",
+ "fastapi@0.139.0",
+ "feedparser@6.0.12",
+ "httpx@0.28.1",
+ "jinja2@3.1.6",
+ "json-repair@0.61.7",
+ "lark-oapi@1.5.5",
+ "litellm@1.85.1",
+ "loguru@0.7.3",
+ "mcp@1.28.1",
+ "olefile@0.47",
+ "openai@2.38.0",
+ "openpyxl@3.1.5",
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-exporter-otlp-proto-grpc@1.42.1",
+ "opentelemetry-exporter-otlp-proto-http@1.42.1",
+ "opentelemetry-instrumentation-asyncio@0.63b1",
+ "opentelemetry-sdk@1.42.1",
+ "openviking-sdk@0.1.5",
+ "pathspec@1.1.1",
+ "pdfminer-six@20251230",
+ "pdfplumber@0.11.9",
+ "protobuf@6.33.6",
+ "pydantic@2.13.4",
+ "python-docx@1.2.0",
+ "python-multipart@0.0.32",
+ "python-pptx@1.0.2",
+ "pyyaml@6.0.3",
+ "requests@2.34.2",
+ "scrapy@2.17.0",
+ "tabulate@0.10.0",
+ "trafilatura@2.1.0",
+ "tree-sitter-c-sharp@0.23.5",
+ "tree-sitter-cpp@0.23.4",
+ "tree-sitter-go@0.25.0",
+ "tree-sitter-java@0.23.5",
+ "tree-sitter-javascript@0.25.0",
+ "tree-sitter-lua@0.5.0",
+ "tree-sitter-php@0.24.1",
+ "tree-sitter-python@0.25.0",
+ "tree-sitter-rust@0.24.2",
+ "tree-sitter-typescript@0.23.2",
+ "tree-sitter@0.25.2",
+ "typer@0.25.1",
+ "typing-extensions@4.15.0",
+ "urllib3@2.7.0",
+ "uvicorn@0.47.0",
+ "volcengine-python-sdk@5.0.28",
+ "volcengine@1.0.222",
+ "xlrd@2.0.2",
+ "xxhash@3.7.0"
+ ]
+ },
+ {
+ "ID": "pillow@12.3.0",
+ "Name": "pillow",
+ "Identifier": {
+ "PURL": "pkg:pypi/pillow@12.3.0",
+ "UID": "ca54c7626e3d7537"
+ },
+ "Version": "12.3.0",
+ "Relationship": "direct"
+ },
+ {
+ "ID": "psycopg@3.3.4",
+ "Name": "psycopg",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg@3.3.4",
+ "UID": "a7fcc28e4c71e88b"
+ },
+ "Version": "3.3.4",
+ "Relationship": "direct",
+ "DependsOn": [
+ "psycopg-binary@3.3.4",
+ "psycopg-pool@3.3.1",
+ "typing-extensions@4.15.0",
+ "tzdata@2026.2"
+ ]
+ },
+ {
+ "ID": "pydantic@2.13.4",
+ "Name": "pydantic",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic@2.13.4",
+ "UID": "1143b24984ee2cd6"
+ },
+ "Version": "2.13.4",
+ "Relationship": "direct",
+ "DependsOn": [
+ "annotated-types@0.7.0",
+ "pydantic-core@2.46.4",
+ "typing-extensions@4.15.0",
+ "typing-inspection@0.4.2"
+ ]
+ },
+ {
+ "ID": "redis@6.4.0",
+ "Name": "redis",
+ "Identifier": {
+ "PURL": "pkg:pypi/redis@6.4.0",
+ "UID": "11fbd3b587a47e23"
+ },
+ "Version": "6.4.0",
+ "Relationship": "direct",
+ "DependsOn": [
+ "async-timeout@5.0.1"
+ ]
+ },
+ {
+ "ID": "soupsieve@2.9.1",
+ "Name": "soupsieve",
+ "Identifier": {
+ "PURL": "pkg:pypi/soupsieve@2.9.1",
+ "UID": "eb32fb90af49d2f3"
+ },
+ "Version": "2.9.1",
+ "Relationship": "direct"
+ },
+ {
+ "ID": "starlette@1.3.1",
+ "Name": "starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/starlette@1.3.1",
+ "UID": "24c1e0349df55f94"
+ },
+ "Version": "1.3.1",
+ "Relationship": "direct",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "uvicorn@0.47.0",
+ "Name": "uvicorn",
+ "Identifier": {
+ "PURL": "pkg:pypi/uvicorn@0.47.0",
+ "UID": "17cbb6ef525da623"
+ },
+ "Version": "0.47.0",
+ "Relationship": "direct",
+ "DependsOn": [
+ "click@8.4.1",
+ "colorama@0.4.6",
+ "h11@0.16.0",
+ "httptools@0.7.1",
+ "python-dotenv@1.2.2",
+ "pyyaml@6.0.3",
+ "typing-extensions@4.15.0",
+ "uvloop@0.22.1",
+ "watchfiles@1.2.0",
+ "websockets@16.0"
+ ]
+ },
+ {
+ "ID": "aiohappyeyeballs@2.6.2",
+ "Name": "aiohappyeyeballs",
+ "Identifier": {
+ "PURL": "pkg:pypi/aiohappyeyeballs@2.6.2",
+ "UID": "3138cd82fb6bf479"
+ },
+ "Version": "2.6.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "aiosignal@1.4.0",
+ "Name": "aiosignal",
+ "Identifier": {
+ "PURL": "pkg:pypi/aiosignal@1.4.0",
+ "UID": "f44b45e60a76e658"
+ },
+ "Version": "1.4.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "frozenlist@1.8.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "annotated-doc@0.0.4",
+ "Name": "annotated-doc",
+ "Identifier": {
+ "PURL": "pkg:pypi/annotated-doc@0.0.4",
+ "UID": "b22c8e29cb6dcb45"
+ },
+ "Version": "0.0.4",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "annotated-types@0.7.0",
+ "Name": "annotated-types",
+ "Identifier": {
+ "PURL": "pkg:pypi/annotated-types@0.7.0",
+ "UID": "11cf816d4baeb496"
+ },
+ "Version": "0.7.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "anyio@4.13.0",
+ "Name": "anyio",
+ "Identifier": {
+ "PURL": "pkg:pypi/anyio@4.13.0",
+ "UID": "51357db313006c72"
+ },
+ "Version": "4.13.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "exceptiongroup@1.3.1",
+ "idna@3.16",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "apscheduler@3.11.2",
+ "Name": "apscheduler",
+ "Identifier": {
+ "PURL": "pkg:pypi/apscheduler@3.11.2",
+ "UID": "874346a401c38a88"
+ },
+ "Version": "3.11.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "tzlocal@5.3.1"
+ ]
+ },
+ {
+ "ID": "argon2-cffi@25.1.0",
+ "Name": "argon2-cffi",
+ "Identifier": {
+ "PURL": "pkg:pypi/argon2-cffi@25.1.0",
+ "UID": "b19c636eb5c69eb7"
+ },
+ "Version": "25.1.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "argon2-cffi-bindings@25.1.0"
+ ]
+ },
+ {
+ "ID": "argon2-cffi-bindings@25.1.0",
+ "Name": "argon2-cffi-bindings",
+ "Identifier": {
+ "PURL": "pkg:pypi/argon2-cffi-bindings@25.1.0",
+ "UID": "6fd05fced56d1f87"
+ },
+ "Version": "25.1.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cffi@2.0.0"
+ ]
+ },
+ {
+ "ID": "async-timeout@5.0.1",
+ "Name": "async-timeout",
+ "Identifier": {
+ "PURL": "pkg:pypi/async-timeout@5.0.1",
+ "UID": "d96510162b86cfa"
+ },
+ "Version": "5.0.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "attrs@26.1.0",
+ "Name": "attrs",
+ "Identifier": {
+ "PURL": "pkg:pypi/attrs@26.1.0",
+ "UID": "e79bb2f7c1ab75e6"
+ },
+ "Version": "26.1.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "automat@25.4.16",
+ "Name": "automat",
+ "Identifier": {
+ "PURL": "pkg:pypi/automat@25.4.16",
+ "UID": "f7a0cdce26c33e15"
+ },
+ "Version": "25.4.16",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "babel@2.18.0",
+ "Name": "babel",
+ "Identifier": {
+ "PURL": "pkg:pypi/babel@2.18.0",
+ "UID": "63b032d4c841398"
+ },
+ "Version": "2.18.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "beautifulsoup4@4.14.3",
+ "Name": "beautifulsoup4",
+ "Identifier": {
+ "PURL": "pkg:pypi/beautifulsoup4@4.14.3",
+ "UID": "c258519877024c2b"
+ },
+ "Version": "4.14.3",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "soupsieve@2.9.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "botocore@1.43.56",
+ "Name": "botocore",
+ "Identifier": {
+ "PURL": "pkg:pypi/botocore@1.43.56",
+ "UID": "2ebc9c1eb8303c4"
+ },
+ "Version": "1.43.56",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "jmespath@1.1.0",
+ "python-dateutil@2.9.0.post0",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "certifi@2026.5.20",
+ "Name": "certifi",
+ "Identifier": {
+ "PURL": "pkg:pypi/certifi@2026.5.20",
+ "UID": "a1f3abeb0afcd7a0"
+ },
+ "Version": "2026.5.20",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "cffi@2.0.0",
+ "Name": "cffi",
+ "Identifier": {
+ "PURL": "pkg:pypi/cffi@2.0.0",
+ "UID": "17b62359c3dde9fe"
+ },
+ "Version": "2.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "pycparser@3.0"
+ ]
+ },
+ {
+ "ID": "charset-normalizer@3.4.7",
+ "Name": "charset-normalizer",
+ "Identifier": {
+ "PURL": "pkg:pypi/charset-normalizer@3.4.7",
+ "UID": "86b1f758bd996aaa"
+ },
+ "Version": "3.4.7",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "click@8.4.1",
+ "Name": "click",
+ "Identifier": {
+ "PURL": "pkg:pypi/click@8.4.1",
+ "UID": "1bfc14795c497ded"
+ },
+ "Version": "8.4.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "colorama@0.4.6"
+ ]
+ },
+ {
+ "ID": "colorama@0.4.6",
+ "Name": "colorama",
+ "Identifier": {
+ "PURL": "pkg:pypi/colorama@0.4.6",
+ "UID": "49acc401742db23d"
+ },
+ "Version": "0.4.6",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "constantly@23.10.4",
+ "Name": "constantly",
+ "Identifier": {
+ "PURL": "pkg:pypi/constantly@23.10.4",
+ "UID": "646532fbe0743280"
+ },
+ "Version": "23.10.4",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "courlan@1.4.0",
+ "Name": "courlan",
+ "Identifier": {
+ "PURL": "pkg:pypi/courlan@1.4.0",
+ "UID": "f529508ae553eb4"
+ },
+ "Version": "1.4.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "babel@2.18.0",
+ "tld@0.13.2",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "cryptography@49.0.0",
+ "Name": "cryptography",
+ "Identifier": {
+ "PURL": "pkg:pypi/cryptography@49.0.0",
+ "UID": "3155e393a29b8cf"
+ },
+ "Version": "49.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cffi@2.0.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "cssselect@1.5.0",
+ "Name": "cssselect",
+ "Identifier": {
+ "PURL": "pkg:pypi/cssselect@1.5.0",
+ "UID": "ee20042c34045be4"
+ },
+ "Version": "1.5.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "dateparser@1.4.1",
+ "Name": "dateparser",
+ "Identifier": {
+ "PURL": "pkg:pypi/dateparser@1.4.1",
+ "UID": "6323da64da6c74ab"
+ },
+ "Version": "1.4.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "python-dateutil@2.9.0.post0",
+ "pytz@2026.2",
+ "regex@2026.5.9",
+ "tzlocal@5.3.1"
+ ]
+ },
+ {
+ "ID": "decorator@5.3.1",
+ "Name": "decorator",
+ "Identifier": {
+ "PURL": "pkg:pypi/decorator@5.3.1",
+ "UID": "b4b00eb3b1242618"
+ },
+ "Version": "5.3.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "defusedxml@0.7.1",
+ "Name": "defusedxml",
+ "Identifier": {
+ "PURL": "pkg:pypi/defusedxml@0.7.1",
+ "UID": "7ee6826d9010842f"
+ },
+ "Version": "0.7.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "distro@1.9.0",
+ "Name": "distro",
+ "Identifier": {
+ "PURL": "pkg:pypi/distro@1.9.0",
+ "UID": "8e2597fd6ac81338"
+ },
+ "Version": "1.9.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "docker@7.1.0",
+ "Name": "docker",
+ "Identifier": {
+ "PURL": "pkg:pypi/docker@7.1.0",
+ "UID": "2bd3c21667ff80f0"
+ },
+ "Version": "7.1.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "pywin32@311",
+ "requests@2.34.2",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "docstring-parser@0.18.0",
+ "Name": "docstring-parser",
+ "Identifier": {
+ "PURL": "pkg:pypi/docstring-parser@0.18.0",
+ "UID": "e88afd9925d31571"
+ },
+ "Version": "0.18.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "durationpy@0.10",
+ "Name": "durationpy",
+ "Identifier": {
+ "PURL": "pkg:pypi/durationpy@0.10",
+ "UID": "96b0639e4e6a2fb5"
+ },
+ "Version": "0.10",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "ebooklib@0.20",
+ "Name": "ebooklib",
+ "Identifier": {
+ "PURL": "pkg:pypi/ebooklib@0.20",
+ "UID": "4f383fac356d0fb1"
+ },
+ "Version": "0.20",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml@6.1.1",
+ "six@1.17.0"
+ ]
+ },
+ {
+ "ID": "et-xmlfile@2.0.0",
+ "Name": "et-xmlfile",
+ "Identifier": {
+ "PURL": "pkg:pypi/et-xmlfile@2.0.0",
+ "UID": "bba70b2b7d16f35"
+ },
+ "Version": "2.0.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "exceptiongroup@1.3.1",
+ "Name": "exceptiongroup",
+ "Identifier": {
+ "PURL": "pkg:pypi/exceptiongroup@1.3.1",
+ "UID": "409f1274ee18054c"
+ },
+ "Version": "1.3.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "fastapi@0.139.0",
+ "Name": "fastapi",
+ "Identifier": {
+ "PURL": "pkg:pypi/fastapi@0.139.0",
+ "UID": "6caf70d612778d61"
+ },
+ "Version": "0.139.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "annotated-doc@0.0.4",
+ "pydantic@2.13.4",
+ "starlette@1.3.1",
+ "typing-extensions@4.15.0",
+ "typing-inspection@0.4.2"
+ ]
+ },
+ {
+ "ID": "fastuuid@0.14.0",
+ "Name": "fastuuid",
+ "Identifier": {
+ "PURL": "pkg:pypi/fastuuid@0.14.0",
+ "UID": "eeeb8ee5daaa04fa"
+ },
+ "Version": "0.14.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "feedparser@6.0.12",
+ "Name": "feedparser",
+ "Identifier": {
+ "PURL": "pkg:pypi/feedparser@6.0.12",
+ "UID": "158e6c8d5cbd238f"
+ },
+ "Version": "6.0.12",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "sgmllib3k@1.0.0"
+ ]
+ },
+ {
+ "ID": "filelock@3.29.0",
+ "Name": "filelock",
+ "Identifier": {
+ "PURL": "pkg:pypi/filelock@3.29.0",
+ "UID": "7828d67563657a86"
+ },
+ "Version": "3.29.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "frozenlist@1.8.0",
+ "Name": "frozenlist",
+ "Identifier": {
+ "PURL": "pkg:pypi/frozenlist@1.8.0",
+ "UID": "ceb29e6f4c30b4f4"
+ },
+ "Version": "1.8.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "fsspec@2026.4.0",
+ "Name": "fsspec",
+ "Identifier": {
+ "PURL": "pkg:pypi/fsspec@2026.4.0",
+ "UID": "3ff12fc77e668ef6"
+ },
+ "Version": "2026.4.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "google@3.0.0",
+ "Name": "google",
+ "Identifier": {
+ "PURL": "pkg:pypi/google@3.0.0",
+ "UID": "796c803dde2dd11a"
+ },
+ "Version": "3.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "beautifulsoup4@4.14.3"
+ ]
+ },
+ {
+ "ID": "googleapis-common-protos@1.75.0",
+ "Name": "googleapis-common-protos",
+ "Identifier": {
+ "PURL": "pkg:pypi/googleapis-common-protos@1.75.0",
+ "UID": "7e29147907b8f5b0"
+ },
+ "Version": "1.75.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "protobuf@6.33.6"
+ ]
+ },
+ {
+ "ID": "grpcio@1.80.0",
+ "Name": "grpcio",
+ "Identifier": {
+ "PURL": "pkg:pypi/grpcio@1.80.0",
+ "UID": "eea11b30053eb26"
+ },
+ "Version": "1.80.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "h11@0.16.0",
+ "Name": "h11",
+ "Identifier": {
+ "PURL": "pkg:pypi/h11@0.16.0",
+ "UID": "f98d44af252a461e"
+ },
+ "Version": "0.16.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "hf-xet@1.5.0",
+ "Name": "hf-xet",
+ "Identifier": {
+ "PURL": "pkg:pypi/hf-xet@1.5.0",
+ "UID": "c5bbf1acd9dd4de8"
+ },
+ "Version": "1.5.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "htmldate@1.10.0",
+ "Name": "htmldate",
+ "Identifier": {
+ "PURL": "pkg:pypi/htmldate@1.10.0",
+ "UID": "c7a7d9da06bbfe15"
+ },
+ "Version": "1.10.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "charset-normalizer@3.4.7",
+ "dateparser@1.4.1",
+ "lxml@6.1.1",
+ "python-dateutil@2.9.0.post0",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "httpcore@1.0.9",
+ "Name": "httpcore",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpcore@1.0.9",
+ "UID": "8a4f5f5c03660848"
+ },
+ "Version": "1.0.9",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "certifi@2026.5.20",
+ "h11@0.16.0"
+ ]
+ },
+ {
+ "ID": "httptools@0.7.1",
+ "Name": "httptools",
+ "Identifier": {
+ "PURL": "pkg:pypi/httptools@0.7.1",
+ "UID": "935b13449a70e6a8"
+ },
+ "Version": "0.7.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "httpx-sse@0.4.3",
+ "Name": "httpx-sse",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx-sse@0.4.3",
+ "UID": "87c1f59b65c4e08e"
+ },
+ "Version": "0.4.3",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "huggingface-hub@1.16.1",
+ "Name": "huggingface-hub",
+ "Identifier": {
+ "PURL": "pkg:pypi/huggingface-hub@1.16.1",
+ "UID": "d187308b5c4de4c1"
+ },
+ "Version": "1.16.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "filelock@3.29.0",
+ "fsspec@2026.4.0",
+ "hf-xet@1.5.0",
+ "httpx@0.28.1",
+ "packaging@26.2",
+ "pyyaml@6.0.3",
+ "tqdm@4.67.3",
+ "typer@0.25.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "hyperlink@21.0.0",
+ "Name": "hyperlink",
+ "Identifier": {
+ "PURL": "pkg:pypi/hyperlink@21.0.0",
+ "UID": "9a8716f7de74750b"
+ },
+ "Version": "21.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "idna@3.16"
+ ]
+ },
+ {
+ "ID": "idna@3.16",
+ "Name": "idna",
+ "Identifier": {
+ "PURL": "pkg:pypi/idna@3.16",
+ "UID": "5bca8aece3b138ad"
+ },
+ "Version": "3.16",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "importlib-metadata@8.9.0",
+ "Name": "importlib-metadata",
+ "Identifier": {
+ "PURL": "pkg:pypi/importlib-metadata@8.9.0",
+ "UID": "3596d46d555ede11"
+ },
+ "Version": "8.9.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "zipp@4.1.0"
+ ]
+ },
+ {
+ "ID": "incremental@24.11.0",
+ "Name": "incremental",
+ "Identifier": {
+ "PURL": "pkg:pypi/incremental@24.11.0",
+ "UID": "81ec074f91c1b630"
+ },
+ "Version": "24.11.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "packaging@26.2",
+ "tomli@2.4.1"
+ ]
+ },
+ {
+ "ID": "itemadapter@0.13.1",
+ "Name": "itemadapter",
+ "Identifier": {
+ "PURL": "pkg:pypi/itemadapter@0.13.1",
+ "UID": "48b35965ca4ba913"
+ },
+ "Version": "0.13.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "itemloaders@1.4.0",
+ "Name": "itemloaders",
+ "Identifier": {
+ "PURL": "pkg:pypi/itemloaders@1.4.0",
+ "UID": "bb3d98f1a645722a"
+ },
+ "Version": "1.4.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "itemadapter@0.13.1",
+ "jmespath@1.1.0",
+ "parsel@1.11.0"
+ ]
+ },
+ {
+ "ID": "jinja2@3.1.6",
+ "Name": "jinja2",
+ "Identifier": {
+ "PURL": "pkg:pypi/jinja2@3.1.6",
+ "UID": "7665ffa0d224a020"
+ },
+ "Version": "3.1.6",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "markupsafe@3.0.3"
+ ]
+ },
+ {
+ "ID": "jiter@0.15.0",
+ "Name": "jiter",
+ "Identifier": {
+ "PURL": "pkg:pypi/jiter@0.15.0",
+ "UID": "8b9915803c7cc55a"
+ },
+ "Version": "0.15.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "jmespath@1.1.0",
+ "Name": "jmespath",
+ "Identifier": {
+ "PURL": "pkg:pypi/jmespath@1.1.0",
+ "UID": "a7947903a898d0ac"
+ },
+ "Version": "1.1.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "jsonschema@4.26.0",
+ "Name": "jsonschema",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema@4.26.0",
+ "UID": "6cde932ef1ea2a36"
+ },
+ "Version": "4.26.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "attrs@26.1.0",
+ "jsonschema-specifications@2025.9.1",
+ "referencing@0.37.0",
+ "rpds-py@0.30.0"
+ ]
+ },
+ {
+ "ID": "jsonschema-specifications@2025.9.1",
+ "Name": "jsonschema-specifications",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "UID": "867f65dbe20d7caf"
+ },
+ "Version": "2025.9.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "referencing@0.37.0"
+ ]
+ },
+ {
+ "ID": "justext@3.0.2",
+ "Name": "justext",
+ "Identifier": {
+ "PURL": "pkg:pypi/justext@3.0.2",
+ "UID": "79912f2980a181fc"
+ },
+ "Version": "3.0.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml@6.1.1"
+ ]
+ },
+ {
+ "ID": "kubernetes@36.0.0",
+ "Name": "kubernetes",
+ "Identifier": {
+ "PURL": "pkg:pypi/kubernetes@36.0.0",
+ "UID": "223729affe6a5cfc"
+ },
+ "Version": "36.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "aiohttp@3.14.3",
+ "certifi@2026.5.20",
+ "durationpy@0.10",
+ "python-dateutil@2.9.0.post0",
+ "pyyaml@6.0.3",
+ "requests-oauthlib@2.0.0",
+ "requests@2.34.2",
+ "six@1.17.0",
+ "urllib3@2.7.0",
+ "websocket-client@1.9.0"
+ ]
+ },
+ {
+ "ID": "lark-oapi@1.5.5",
+ "Name": "lark-oapi",
+ "Identifier": {
+ "PURL": "pkg:pypi/lark-oapi@1.5.5",
+ "UID": "4913f86a0bc67ce4"
+ },
+ "Version": "1.5.5",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "httpx@0.28.1",
+ "pycryptodome@3.23.0",
+ "requests-toolbelt@1.0.0",
+ "requests@2.34.2",
+ "websockets@16.0"
+ ]
+ },
+ {
+ "ID": "loguru@0.7.3",
+ "Name": "loguru",
+ "Identifier": {
+ "PURL": "pkg:pypi/loguru@0.7.3",
+ "UID": "1a048f1512302e8b"
+ },
+ "Version": "0.7.3",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "colorama@0.4.6",
+ "win32-setctime@1.2.0"
+ ]
+ },
+ {
+ "ID": "lxml@6.1.1",
+ "Name": "lxml",
+ "Identifier": {
+ "PURL": "pkg:pypi/lxml@6.1.1",
+ "UID": "ed7e75bfa63b559b"
+ },
+ "Version": "6.1.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml-html-clean@0.4.5"
+ ]
+ },
+ {
+ "ID": "lxml-html-clean@0.4.5",
+ "Name": "lxml-html-clean",
+ "Identifier": {
+ "PURL": "pkg:pypi/lxml-html-clean@0.4.5",
+ "UID": "e298af70adf97e61"
+ },
+ "Version": "0.4.5",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml@6.1.1"
+ ]
+ },
+ {
+ "ID": "markdown-it-py@3.0.0",
+ "Name": "markdown-it-py",
+ "Identifier": {
+ "PURL": "pkg:pypi/markdown-it-py@3.0.0",
+ "UID": "215996bc09c94a4f"
+ },
+ "Version": "3.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "mdurl@0.1.2"
+ ]
+ },
+ {
+ "ID": "markdown-it-py@4.2.0",
+ "Name": "markdown-it-py",
+ "Identifier": {
+ "PURL": "pkg:pypi/markdown-it-py@4.2.0",
+ "UID": "aac12c738988211a"
+ },
+ "Version": "4.2.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "mdurl@0.1.2"
+ ]
+ },
+ {
+ "ID": "markupsafe@3.0.3",
+ "Name": "markupsafe",
+ "Identifier": {
+ "PURL": "pkg:pypi/markupsafe@3.0.3",
+ "UID": "6e3d7916e912131a"
+ },
+ "Version": "3.0.3",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "mdurl@0.1.2",
+ "Name": "mdurl",
+ "Identifier": {
+ "PURL": "pkg:pypi/mdurl@0.1.2",
+ "UID": "d262cfb9f949997f"
+ },
+ "Version": "0.1.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "multidict@6.7.1",
+ "Name": "multidict",
+ "Identifier": {
+ "PURL": "pkg:pypi/multidict@6.7.1",
+ "UID": "529d708d203464c"
+ },
+ "Version": "6.7.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "oauthlib@3.3.1",
+ "Name": "oauthlib",
+ "Identifier": {
+ "PURL": "pkg:pypi/oauthlib@3.3.1",
+ "UID": "8a4916a10042a47f"
+ },
+ "Version": "3.3.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "olefile@0.47",
+ "Name": "olefile",
+ "Identifier": {
+ "PURL": "pkg:pypi/olefile@0.47",
+ "UID": "70a33159957baaf9"
+ },
+ "Version": "0.47",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "openpyxl@3.1.5",
+ "Name": "openpyxl",
+ "Identifier": {
+ "PURL": "pkg:pypi/openpyxl@3.1.5",
+ "UID": "7b09753dc900e457"
+ },
+ "Version": "3.1.5",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "et-xmlfile@2.0.0"
+ ]
+ },
+ {
+ "ID": "opentelemetry-exporter-otlp-proto-common@1.42.1",
+ "Name": "opentelemetry-exporter-otlp-proto-common",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-exporter-otlp-proto-common@1.42.1",
+ "UID": "87322e48d562e1"
+ },
+ "Version": "1.42.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "opentelemetry-proto@1.42.1"
+ ]
+ },
+ {
+ "ID": "opentelemetry-exporter-otlp-proto-grpc@1.42.1",
+ "Name": "opentelemetry-exporter-otlp-proto-grpc",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-exporter-otlp-proto-grpc@1.42.1",
+ "UID": "5d1152f1911a8444"
+ },
+ "Version": "1.42.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "googleapis-common-protos@1.75.0",
+ "grpcio@1.80.0",
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-exporter-otlp-proto-common@1.42.1",
+ "opentelemetry-proto@1.42.1",
+ "opentelemetry-sdk@1.42.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "opentelemetry-exporter-otlp-proto-http@1.42.1",
+ "Name": "opentelemetry-exporter-otlp-proto-http",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-exporter-otlp-proto-http@1.42.1",
+ "UID": "75787693aca0dae6"
+ },
+ "Version": "1.42.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "googleapis-common-protos@1.75.0",
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-exporter-otlp-proto-common@1.42.1",
+ "opentelemetry-proto@1.42.1",
+ "opentelemetry-sdk@1.42.1",
+ "requests@2.34.2",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "opentelemetry-instrumentation@0.63b1",
+ "Name": "opentelemetry-instrumentation",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-instrumentation@0.63b1",
+ "UID": "4fa0f62795b46fbc"
+ },
+ "Version": "0.63b1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-semantic-conventions@0.63b1",
+ "packaging@26.2",
+ "wrapt@2.2.1"
+ ]
+ },
+ {
+ "ID": "opentelemetry-instrumentation-asyncio@0.63b1",
+ "Name": "opentelemetry-instrumentation-asyncio",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-instrumentation-asyncio@0.63b1",
+ "UID": "6b2615e3539d8be1"
+ },
+ "Version": "0.63b1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "opentelemetry-api@1.42.1",
+ "opentelemetry-instrumentation@0.63b1",
+ "opentelemetry-semantic-conventions@0.63b1",
+ "wrapt@2.2.1"
+ ]
+ },
+ {
+ "ID": "opentelemetry-proto@1.42.1",
+ "Name": "opentelemetry-proto",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-proto@1.42.1",
+ "UID": "90d02bc53514c0a6"
+ },
+ "Version": "1.42.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "protobuf@6.33.6"
+ ]
+ },
+ {
+ "ID": "opentelemetry-semantic-conventions@0.63b1",
+ "Name": "opentelemetry-semantic-conventions",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "UID": "361682bb3ff3a740"
+ },
+ "Version": "0.63b1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "opentelemetry-api@1.42.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "openviking-sdk@0.1.5",
+ "Name": "openviking-sdk",
+ "Identifier": {
+ "PURL": "pkg:pypi/openviking-sdk@0.1.5",
+ "UID": "5fbf4f602388cac8"
+ },
+ "Version": "0.1.5",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "httpx@0.28.1"
+ ]
+ },
+ {
+ "ID": "packaging@26.2",
+ "Name": "packaging",
+ "Identifier": {
+ "PURL": "pkg:pypi/packaging@26.2",
+ "UID": "78ec05430e68bf11"
+ },
+ "Version": "26.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "parsel@1.11.0",
+ "Name": "parsel",
+ "Identifier": {
+ "PURL": "pkg:pypi/parsel@1.11.0",
+ "UID": "b5b1b1edbf84974c"
+ },
+ "Version": "1.11.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cssselect@1.5.0",
+ "jmespath@1.1.0",
+ "lxml@6.1.1",
+ "packaging@26.2",
+ "w3lib@2.4.1"
+ ]
+ },
+ {
+ "ID": "pathspec@1.1.1",
+ "Name": "pathspec",
+ "Identifier": {
+ "PURL": "pkg:pypi/pathspec@1.1.1",
+ "UID": "f417e9bd635ac2ff"
+ },
+ "Version": "1.1.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pdfminer-six@20251230",
+ "Name": "pdfminer-six",
+ "Identifier": {
+ "PURL": "pkg:pypi/pdfminer-six@20251230",
+ "UID": "7c6ab0beb183d479"
+ },
+ "Version": "20251230",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "charset-normalizer@3.4.7",
+ "cryptography@49.0.0"
+ ]
+ },
+ {
+ "ID": "pdfplumber@0.11.9",
+ "Name": "pdfplumber",
+ "Identifier": {
+ "PURL": "pkg:pypi/pdfplumber@0.11.9",
+ "UID": "36bd3356488181b0"
+ },
+ "Version": "0.11.9",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "pdfminer-six@20251230",
+ "pillow@12.3.0",
+ "pypdfium2@5.8.0"
+ ]
+ },
+ {
+ "ID": "propcache@0.5.2",
+ "Name": "propcache",
+ "Identifier": {
+ "PURL": "pkg:pypi/propcache@0.5.2",
+ "UID": "f9ffe97c9009ad1c"
+ },
+ "Version": "0.5.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "protego@0.6.2",
+ "Name": "protego",
+ "Identifier": {
+ "PURL": "pkg:pypi/protego@0.6.2",
+ "UID": "a42402938b1817fe"
+ },
+ "Version": "0.6.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "protobuf@6.33.6",
+ "Name": "protobuf",
+ "Identifier": {
+ "PURL": "pkg:pypi/protobuf@6.33.6",
+ "UID": "3dc30339a9cf63dd"
+ },
+ "Version": "6.33.6",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "psycopg-binary@3.3.4",
+ "Name": "psycopg-binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4",
+ "UID": "57eaf6cb0321067a"
+ },
+ "Version": "3.3.4",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "psycopg-pool@3.3.1",
+ "Name": "psycopg-pool",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-pool@3.3.1",
+ "UID": "72a99c34cd88e626"
+ },
+ "Version": "3.3.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "py@1.11.0",
+ "Name": "py",
+ "Identifier": {
+ "PURL": "pkg:pypi/py@1.11.0",
+ "UID": "54a331165a4640d2"
+ },
+ "Version": "1.11.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pycparser@3.0",
+ "Name": "pycparser",
+ "Identifier": {
+ "PURL": "pkg:pypi/pycparser@3.0",
+ "UID": "a030070ae7a187b2"
+ },
+ "Version": "3.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pycryptodome@3.23.0",
+ "Name": "pycryptodome",
+ "Identifier": {
+ "PURL": "pkg:pypi/pycryptodome@3.23.0",
+ "UID": "9d1c5c172635c793"
+ },
+ "Version": "3.23.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pydantic-core@2.46.4",
+ "Name": "pydantic-core",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-core@2.46.4",
+ "UID": "979f2e0bdfa56772"
+ },
+ "Version": "2.46.4",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "pydantic-settings@2.14.2",
+ "Name": "pydantic-settings",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-settings@2.14.2",
+ "UID": "9c593c1e826a3acc"
+ },
+ "Version": "2.14.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "pydantic@2.13.4",
+ "python-dotenv@1.2.2",
+ "typing-inspection@0.4.2"
+ ]
+ },
+ {
+ "ID": "pydispatcher@2.0.7",
+ "Name": "pydispatcher",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydispatcher@2.0.7",
+ "UID": "a84eb20b6c22d2dd"
+ },
+ "Version": "2.0.7",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pygments@2.20.0",
+ "Name": "pygments",
+ "Identifier": {
+ "PURL": "pkg:pypi/pygments@2.20.0",
+ "UID": "412fcfe0e35c3c57"
+ },
+ "Version": "2.20.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pyjwt@2.13.0",
+ "Name": "pyjwt",
+ "Identifier": {
+ "PURL": "pkg:pypi/pyjwt@2.13.0",
+ "UID": "3171e9daeb0b9d05"
+ },
+ "Version": "2.13.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cryptography@49.0.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "pyopenssl@26.3.0",
+ "Name": "pyopenssl",
+ "Identifier": {
+ "PURL": "pkg:pypi/pyopenssl@26.3.0",
+ "UID": "c2dbce487c92169"
+ },
+ "Version": "26.3.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cryptography@49.0.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "pypdfium2@5.8.0",
+ "Name": "pypdfium2",
+ "Identifier": {
+ "PURL": "pkg:pypi/pypdfium2@5.8.0",
+ "UID": "cb12848faa434a66"
+ },
+ "Version": "5.8.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pypydispatcher@2.1.2",
+ "Name": "pypydispatcher",
+ "Identifier": {
+ "PURL": "pkg:pypi/pypydispatcher@2.1.2",
+ "UID": "65bcfe1679f61073"
+ },
+ "Version": "2.1.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "python-dateutil@2.9.0.post0",
+ "Name": "python-dateutil",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "UID": "f076f675da73225b"
+ },
+ "Version": "2.9.0.post0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "six@1.17.0"
+ ]
+ },
+ {
+ "ID": "python-docx@1.2.0",
+ "Name": "python-docx",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-docx@1.2.0",
+ "UID": "e78a7343a4694472"
+ },
+ "Version": "1.2.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml@6.1.1",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "python-dotenv@1.2.2",
+ "Name": "python-dotenv",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dotenv@1.2.2",
+ "UID": "14d8dd609e7b32bb"
+ },
+ "Version": "1.2.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "python-multipart@0.0.32",
+ "Name": "python-multipart",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-multipart@0.0.32",
+ "UID": "eadf759a4737b46b"
+ },
+ "Version": "0.0.32",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "python-pptx@1.0.2",
+ "Name": "python-pptx",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-pptx@1.0.2",
+ "UID": "769c0b09031f42bb"
+ },
+ "Version": "1.0.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "lxml@6.1.1",
+ "pillow@12.3.0",
+ "typing-extensions@4.15.0",
+ "xlsxwriter@3.2.9"
+ ]
+ },
+ {
+ "ID": "pytz@2026.2",
+ "Name": "pytz",
+ "Identifier": {
+ "PURL": "pkg:pypi/pytz@2026.2",
+ "UID": "433c0d251b5b021c"
+ },
+ "Version": "2026.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pywin32@311",
+ "Name": "pywin32",
+ "Identifier": {
+ "PURL": "pkg:pypi/pywin32@311",
+ "UID": "b301115ac354b51d"
+ },
+ "Version": "311",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "pyyaml@6.0.3",
+ "Name": "pyyaml",
+ "Identifier": {
+ "PURL": "pkg:pypi/pyyaml@6.0.3",
+ "UID": "107b31a534619272"
+ },
+ "Version": "6.0.3",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "queuelib@1.9.0",
+ "Name": "queuelib",
+ "Identifier": {
+ "PURL": "pkg:pypi/queuelib@1.9.0",
+ "UID": "5c8692655e664f79"
+ },
+ "Version": "1.9.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "referencing@0.37.0",
+ "Name": "referencing",
+ "Identifier": {
+ "PURL": "pkg:pypi/referencing@0.37.0",
+ "UID": "df12688160a5997"
+ },
+ "Version": "0.37.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "attrs@26.1.0",
+ "rpds-py@0.30.0",
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "regex@2026.5.9",
+ "Name": "regex",
+ "Identifier": {
+ "PURL": "pkg:pypi/regex@2026.5.9",
+ "UID": "668888c9689a83e6"
+ },
+ "Version": "2026.5.9",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "requests@2.34.2",
+ "Name": "requests",
+ "Identifier": {
+ "PURL": "pkg:pypi/requests@2.34.2",
+ "UID": "ea0a1eef368ee39b"
+ },
+ "Version": "2.34.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "certifi@2026.5.20",
+ "charset-normalizer@3.4.7",
+ "idna@3.16",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "requests-file@3.0.1",
+ "Name": "requests-file",
+ "Identifier": {
+ "PURL": "pkg:pypi/requests-file@3.0.1",
+ "UID": "3475fa97fb85873d"
+ },
+ "Version": "3.0.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "requests@2.34.2"
+ ]
+ },
+ {
+ "ID": "requests-oauthlib@2.0.0",
+ "Name": "requests-oauthlib",
+ "Identifier": {
+ "PURL": "pkg:pypi/requests-oauthlib@2.0.0",
+ "UID": "b26b8619f6db397b"
+ },
+ "Version": "2.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "oauthlib@3.3.1",
+ "requests@2.34.2"
+ ]
+ },
+ {
+ "ID": "requests-toolbelt@1.0.0",
+ "Name": "requests-toolbelt",
+ "Identifier": {
+ "PURL": "pkg:pypi/requests-toolbelt@1.0.0",
+ "UID": "d73d767e21e45a30"
+ },
+ "Version": "1.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "requests@2.34.2"
+ ]
+ },
+ {
+ "ID": "retry@0.9.2",
+ "Name": "retry",
+ "Identifier": {
+ "PURL": "pkg:pypi/retry@0.9.2",
+ "UID": "5547c39c7c3cf0d9"
+ },
+ "Version": "0.9.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "decorator@5.3.1",
+ "py@1.11.0"
+ ]
+ },
+ {
+ "ID": "rich@15.0.0",
+ "Name": "rich",
+ "Identifier": {
+ "PURL": "pkg:pypi/rich@15.0.0",
+ "UID": "9a38a0981856043e"
+ },
+ "Version": "15.0.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "markdown-it-py@4.2.0",
+ "pygments@2.20.0"
+ ]
+ },
+ {
+ "ID": "rpds-py@0.30.0",
+ "Name": "rpds-py",
+ "Identifier": {
+ "PURL": "pkg:pypi/rpds-py@0.30.0",
+ "UID": "6772cf180012274b"
+ },
+ "Version": "0.30.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "s3transfer@0.19.2",
+ "Name": "s3transfer",
+ "Identifier": {
+ "PURL": "pkg:pypi/s3transfer@0.19.2",
+ "UID": "12120efcef72eedc"
+ },
+ "Version": "0.19.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "botocore@1.43.56"
+ ]
+ },
+ {
+ "ID": "scrapy@2.17.0",
+ "Name": "scrapy",
+ "Identifier": {
+ "PURL": "pkg:pypi/scrapy@2.17.0",
+ "UID": "e74369fc0946fa09"
+ },
+ "Version": "2.17.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "cryptography@49.0.0",
+ "cssselect@1.5.0",
+ "defusedxml@0.7.1",
+ "itemadapter@0.13.1",
+ "itemloaders@1.4.0",
+ "lxml@6.1.1",
+ "packaging@26.2",
+ "parsel@1.11.0",
+ "protego@0.6.2",
+ "pydispatcher@2.0.7",
+ "pyopenssl@26.3.0",
+ "pypydispatcher@2.1.2",
+ "queuelib@1.9.0",
+ "service-identity@26.1.0",
+ "tldextract@5.3.1",
+ "twisted@26.4.0",
+ "w3lib@2.4.1",
+ "zope-interface@8.5"
+ ]
+ },
+ {
+ "ID": "service-identity@26.1.0",
+ "Name": "service-identity",
+ "Identifier": {
+ "PURL": "pkg:pypi/service-identity@26.1.0",
+ "UID": "eb6e07fabc9f8a8b"
+ },
+ "Version": "26.1.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "attrs@26.1.0",
+ "cryptography@49.0.0"
+ ]
+ },
+ {
+ "ID": "sgmllib3k@1.0.0",
+ "Name": "sgmllib3k",
+ "Identifier": {
+ "PURL": "pkg:pypi/sgmllib3k@1.0.0",
+ "UID": "a6388df1b2bc901"
+ },
+ "Version": "1.0.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "shellingham@1.5.4",
+ "Name": "shellingham",
+ "Identifier": {
+ "PURL": "pkg:pypi/shellingham@1.5.4",
+ "UID": "d506ce660d05c75a"
+ },
+ "Version": "1.5.4",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "six@1.17.0",
+ "Name": "six",
+ "Identifier": {
+ "PURL": "pkg:pypi/six@1.17.0",
+ "UID": "6d52467f91fbb7a1"
+ },
+ "Version": "1.17.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "sniffio@1.3.1",
+ "Name": "sniffio",
+ "Identifier": {
+ "PURL": "pkg:pypi/sniffio@1.3.1",
+ "UID": "1ce19e35a8ce5758"
+ },
+ "Version": "1.3.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "socksio@1.0.0",
+ "Name": "socksio",
+ "Identifier": {
+ "PURL": "pkg:pypi/socksio@1.0.0",
+ "UID": "7919f9e91eb10079"
+ },
+ "Version": "1.0.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "sse-starlette@3.4.4",
+ "Name": "sse-starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/sse-starlette@3.4.4",
+ "UID": "dd13553280d62c81"
+ },
+ "Version": "3.4.4",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "starlette@1.3.1"
+ ]
+ },
+ {
+ "ID": "tabulate@0.10.0",
+ "Name": "tabulate",
+ "Identifier": {
+ "PURL": "pkg:pypi/tabulate@0.10.0",
+ "UID": "70c5c9cf3c6ed8fc"
+ },
+ "Version": "0.10.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tiktoken@0.13.0",
+ "Name": "tiktoken",
+ "Identifier": {
+ "PURL": "pkg:pypi/tiktoken@0.13.0",
+ "UID": "3cd41aa3722452a5"
+ },
+ "Version": "0.13.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "regex@2026.5.9",
+ "requests@2.34.2"
+ ]
+ },
+ {
+ "ID": "tld@0.13.2",
+ "Name": "tld",
+ "Identifier": {
+ "PURL": "pkg:pypi/tld@0.13.2",
+ "UID": "788e2916ab5041aa"
+ },
+ "Version": "0.13.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tldextract@5.3.1",
+ "Name": "tldextract",
+ "Identifier": {
+ "PURL": "pkg:pypi/tldextract@5.3.1",
+ "UID": "a4231d7e253d955"
+ },
+ "Version": "5.3.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "filelock@3.29.0",
+ "idna@3.16",
+ "requests-file@3.0.1",
+ "requests@2.34.2"
+ ]
+ },
+ {
+ "ID": "tokenizers@0.23.1",
+ "Name": "tokenizers",
+ "Identifier": {
+ "PURL": "pkg:pypi/tokenizers@0.23.1",
+ "UID": "f4ee0223d5f4cdb0"
+ },
+ "Version": "0.23.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "huggingface-hub@1.16.1"
+ ]
+ },
+ {
+ "ID": "tomli@2.4.1",
+ "Name": "tomli",
+ "Identifier": {
+ "PURL": "pkg:pypi/tomli@2.4.1",
+ "UID": "20bcead7b0d200b5"
+ },
+ "Version": "2.4.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tqdm@4.67.3",
+ "Name": "tqdm",
+ "Identifier": {
+ "PURL": "pkg:pypi/tqdm@4.67.3",
+ "UID": "301669619356c4c0"
+ },
+ "Version": "4.67.3",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "colorama@0.4.6"
+ ]
+ },
+ {
+ "ID": "trafilatura@2.1.0",
+ "Name": "trafilatura",
+ "Identifier": {
+ "PURL": "pkg:pypi/trafilatura@2.1.0",
+ "UID": "146facb70391d0fd"
+ },
+ "Version": "2.1.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "certifi@2026.5.20",
+ "charset-normalizer@3.4.7",
+ "courlan@1.4.0",
+ "htmldate@1.10.0",
+ "justext@3.0.2",
+ "lxml@6.1.1",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "tree-sitter@0.25.2",
+ "Name": "tree-sitter",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter@0.25.2",
+ "UID": "9a6268b2b51b6303"
+ },
+ "Version": "0.25.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-c-sharp@0.23.5",
+ "Name": "tree-sitter-c-sharp",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-c-sharp@0.23.5",
+ "UID": "95210b17917f7e7f"
+ },
+ "Version": "0.23.5",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-cpp@0.23.4",
+ "Name": "tree-sitter-cpp",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-cpp@0.23.4",
+ "UID": "219b1d75e5d65d2e"
+ },
+ "Version": "0.23.4",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-go@0.25.0",
+ "Name": "tree-sitter-go",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-go@0.25.0",
+ "UID": "595881d5dc7a0628"
+ },
+ "Version": "0.25.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-java@0.23.5",
+ "Name": "tree-sitter-java",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-java@0.23.5",
+ "UID": "838315b64575b259"
+ },
+ "Version": "0.23.5",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-javascript@0.25.0",
+ "Name": "tree-sitter-javascript",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-javascript@0.25.0",
+ "UID": "ae8fce409d8eeecf"
+ },
+ "Version": "0.25.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-lua@0.5.0",
+ "Name": "tree-sitter-lua",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-lua@0.5.0",
+ "UID": "c6af3b893a75d12b"
+ },
+ "Version": "0.5.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-php@0.24.1",
+ "Name": "tree-sitter-php",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-php@0.24.1",
+ "UID": "d1c6c35197eda7fe"
+ },
+ "Version": "0.24.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-python@0.25.0",
+ "Name": "tree-sitter-python",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-python@0.25.0",
+ "UID": "7a7715b1e43a4360"
+ },
+ "Version": "0.25.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-rust@0.24.2",
+ "Name": "tree-sitter-rust",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-rust@0.24.2",
+ "UID": "53d892c5390466c4"
+ },
+ "Version": "0.24.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tree-sitter-typescript@0.23.2",
+ "Name": "tree-sitter-typescript",
+ "Identifier": {
+ "PURL": "pkg:pypi/tree-sitter-typescript@0.23.2",
+ "UID": "3495385b51052032"
+ },
+ "Version": "0.23.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "twisted@26.4.0",
+ "Name": "twisted",
+ "Identifier": {
+ "PURL": "pkg:pypi/twisted@26.4.0",
+ "UID": "9604f6909ee425f1"
+ },
+ "Version": "26.4.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "attrs@26.1.0",
+ "automat@25.4.16",
+ "constantly@23.10.4",
+ "hyperlink@21.0.0",
+ "incremental@24.11.0",
+ "typing-extensions@4.15.0",
+ "zope-interface@8.5"
+ ]
+ },
+ {
+ "ID": "typer@0.25.1",
+ "Name": "typer",
+ "Identifier": {
+ "PURL": "pkg:pypi/typer@0.25.1",
+ "UID": "2e29dfd7124201ba"
+ },
+ "Version": "0.25.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "annotated-doc@0.0.4",
+ "click@8.4.1",
+ "rich@15.0.0",
+ "shellingham@1.5.4"
+ ]
+ },
+ {
+ "ID": "typing-extensions@4.15.0",
+ "Name": "typing-extensions",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-extensions@4.15.0",
+ "UID": "88de06ebf9f410bf"
+ },
+ "Version": "4.15.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "typing-inspection@0.4.2",
+ "Name": "typing-inspection",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-inspection@0.4.2",
+ "UID": "284668b5aaa0b762"
+ },
+ "Version": "0.4.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "typing-extensions@4.15.0"
+ ]
+ },
+ {
+ "ID": "tzdata@2026.2",
+ "Name": "tzdata",
+ "Identifier": {
+ "PURL": "pkg:pypi/tzdata@2026.2",
+ "UID": "ceecdf3721c83e67"
+ },
+ "Version": "2026.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "tzlocal@5.3.1",
+ "Name": "tzlocal",
+ "Identifier": {
+ "PURL": "pkg:pypi/tzlocal@5.3.1",
+ "UID": "c4b82592ea529dcb"
+ },
+ "Version": "5.3.1",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "tzdata@2026.2"
+ ]
+ },
+ {
+ "ID": "urllib3@2.7.0",
+ "Name": "urllib3",
+ "Identifier": {
+ "PURL": "pkg:pypi/urllib3@2.7.0",
+ "UID": "e5d000df273620a4"
+ },
+ "Version": "2.7.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "uvloop@0.22.1",
+ "Name": "uvloop",
+ "Identifier": {
+ "PURL": "pkg:pypi/uvloop@0.22.1",
+ "UID": "c014f41e768af26b"
+ },
+ "Version": "0.22.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "volcengine@1.0.222",
+ "Name": "volcengine",
+ "Identifier": {
+ "PURL": "pkg:pypi/volcengine@1.0.222",
+ "UID": "ff9e95b01340c9fb"
+ },
+ "Version": "1.0.222",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "google@3.0.0",
+ "protobuf@6.33.6",
+ "pycryptodome@3.23.0",
+ "pytz@2026.2",
+ "requests@2.34.2",
+ "retry@0.9.2",
+ "six@1.17.0"
+ ]
+ },
+ {
+ "ID": "volcengine-python-sdk@5.0.28",
+ "Name": "volcengine-python-sdk",
+ "Identifier": {
+ "PURL": "pkg:pypi/volcengine-python-sdk@5.0.28",
+ "UID": "550367d680327ee2"
+ },
+ "Version": "5.0.28",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "anyio@4.13.0",
+ "certifi@2026.5.20",
+ "cryptography@49.0.0",
+ "httpx@0.28.1",
+ "pydantic@2.13.4",
+ "python-dateutil@2.9.0.post0",
+ "six@1.17.0",
+ "urllib3@2.7.0"
+ ]
+ },
+ {
+ "ID": "w3lib@2.4.1",
+ "Name": "w3lib",
+ "Identifier": {
+ "PURL": "pkg:pypi/w3lib@2.4.1",
+ "UID": "bd5ce8fa2da24e38"
+ },
+ "Version": "2.4.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "watchfiles@1.2.0",
+ "Name": "watchfiles",
+ "Identifier": {
+ "PURL": "pkg:pypi/watchfiles@1.2.0",
+ "UID": "151b6d1df9cd1dc6"
+ },
+ "Version": "1.2.0",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "anyio@4.13.0"
+ ]
+ },
+ {
+ "ID": "websocket-client@1.9.0",
+ "Name": "websocket-client",
+ "Identifier": {
+ "PURL": "pkg:pypi/websocket-client@1.9.0",
+ "UID": "c1424d85000fd7be"
+ },
+ "Version": "1.9.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "websockets@16.0",
+ "Name": "websockets",
+ "Identifier": {
+ "PURL": "pkg:pypi/websockets@16.0",
+ "UID": "d430ebe985e5c420"
+ },
+ "Version": "16.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "win32-setctime@1.2.0",
+ "Name": "win32-setctime",
+ "Identifier": {
+ "PURL": "pkg:pypi/win32-setctime@1.2.0",
+ "UID": "754e6d984a7107db"
+ },
+ "Version": "1.2.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "wrapt@2.2.1",
+ "Name": "wrapt",
+ "Identifier": {
+ "PURL": "pkg:pypi/wrapt@2.2.1",
+ "UID": "9123195fab1fb9d2"
+ },
+ "Version": "2.2.1",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "xlrd@2.0.2",
+ "Name": "xlrd",
+ "Identifier": {
+ "PURL": "pkg:pypi/xlrd@2.0.2",
+ "UID": "537a3d0858a38313"
+ },
+ "Version": "2.0.2",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "xlsxwriter@3.2.9",
+ "Name": "xlsxwriter",
+ "Identifier": {
+ "PURL": "pkg:pypi/xlsxwriter@3.2.9",
+ "UID": "540aa0252a1a5a29"
+ },
+ "Version": "3.2.9",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "xxhash@3.7.0",
+ "Name": "xxhash",
+ "Identifier": {
+ "PURL": "pkg:pypi/xxhash@3.7.0",
+ "UID": "820b78187c88065a"
+ },
+ "Version": "3.7.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "yarl@1.24.2",
+ "Name": "yarl",
+ "Identifier": {
+ "PURL": "pkg:pypi/yarl@1.24.2",
+ "UID": "699a7c7261334735"
+ },
+ "Version": "1.24.2",
+ "Indirect": true,
+ "Relationship": "indirect",
+ "DependsOn": [
+ "idna@3.16",
+ "multidict@6.7.1",
+ "propcache@0.5.2"
+ ]
+ },
+ {
+ "ID": "zipp@4.1.0",
+ "Name": "zipp",
+ "Identifier": {
+ "PURL": "pkg:pypi/zipp@4.1.0",
+ "UID": "f8320f81fe4db0c3"
+ },
+ "Version": "4.1.0",
+ "Indirect": true,
+ "Relationship": "indirect"
+ },
+ {
+ "ID": "zope-interface@8.5",
+ "Name": "zope-interface",
+ "Identifier": {
+ "PURL": "pkg:pypi/zope-interface@8.5",
+ "UID": "e30e2fa360db3c49"
+ },
+ "Version": "8.5",
+ "Indirect": true,
+ "Relationship": "indirect"
+ }
+ ]
+ }
+ ]
+}
diff --git a/release/manual-pypi-v2.0.0.md b/release/manual-pypi-v2.0.0.md
new file mode 100644
index 0000000..79dce7e
--- /dev/null
+++ b/release/manual-pypi-v2.0.0.md
@@ -0,0 +1,52 @@
+# Manual PyPI publication for OpenRath 2.0.0
+
+This procedure uploads only the immutable distributions produced by the
+protected `Prepare v2.0.0 GA bundle` workflow. Never rebuild the wheel or sdist
+locally and never place a PyPI token in this repository, a command-line
+argument, an environment variable, or a GitHub secret.
+
+## One-time PyPI setup
+
+1. Sign in to PyPI with an owner of the `openrath` project.
+2. Open .
+3. Create an API token scoped only to the existing `openrath` project.
+4. Copy it to a password manager. The value starts with `pypi-`.
+
+## Prepare the local handoff
+
+After the GA preparation workflow succeeds, check out the exact annotated tag
+and download its artifact:
+
+```powershell
+git fetch origin --tags
+git switch --detach v2.0.0
+gh run download `
+ --repo Rath-Team/OpenRath `
+ --name openrath-2.0.0-ga-candidate `
+ --dir release-bundle
+```
+
+The helper verifies the SHA-bound manifest, every artifact hash, the current
+PyPI state, and Twine metadata before it offers to upload:
+
+```powershell
+uv run python scripts/release/publish_pypi_manual.py `
+ --bundle-dir release-bundle
+```
+
+Type the exact confirmation displayed by the helper. Twine then prompts for
+the API token without echoing it. Use the complete value including its
+`pypi-` prefix. In Windows Terminal, paste with `Ctrl+Shift+V` if `Ctrl+V`
+does not work inside the hidden prompt. The helper performs a second hash
+comparison against PyPI after the upload.
+
+Do not use `dist/` from another checkout and do not run `uv build` during this
+handoff.
+
+## Finalize the release
+
+Dispatch `Finalize v2.0.0 GA` from `main` with the same annotated tag and the
+preparation workflow run ID. Its protected job refuses to continue unless
+PyPI exposes exactly the wheel and sdist from the candidate bundle. It then
+promotes the already-attested OCI digest to `2.0.0`, creates or verifies the
+GitHub Release, and performs fresh public installation and provenance checks.
diff --git a/release/notes/v2.0.0.md b/release/notes/v2.0.0.md
new file mode 100644
index 0000000..5847b2b
--- /dev/null
+++ b/release/notes/v2.0.0.md
@@ -0,0 +1,47 @@
+# OpenRath v2.0.0
+
+OpenRath 2.0.0 introduces a durable multi-agent Runtime and Agent Server while
+preserving the supported Python v1 facade for the documented maintenance
+window.
+
+## Highlights
+
+- Explicit `@step` and `@router` compilation with canonical plans and immutable
+ revision identity.
+- Durable Runs, Events, Checkpoints, Interrupts, cancellation, deadlines,
+ retries, lease fencing, and effect reconciliation.
+- PostgreSQL production state, optional Redis signaling, and S3-compatible
+ artifact storage.
+- Tenant/project-scoped HTTP and SSE APIs with explicit grants, bounded
+ resources, security headers, and redacted structured audit events.
+- Governed Provider, Tool/MCP, Sandbox, and Memory adapter boundaries.
+- OpenTelemetry integration, evaluation resources, migration tooling, and
+ split API/worker deployment references.
+
+## Compatibility and migration
+
+- Existing v1 JSONL Sessions import as non-resumable historical Runs.
+- Database migrations are additive during the rollback window.
+- Operators should inventory v1 data, back up PostgreSQL and artifacts, run the
+ migration dry-run, and restore-test backups before switching traffic.
+- See `deploy/docs/migration-v2.md`, `deploy/docs/operations-v2.md`, and
+ `deploy/docs/api-governance-v2.md`.
+
+## Security and operational boundary
+
+- Authentication never grants access by itself; deployments must provide
+ explicit action grants and tenant/project scope.
+- Embedded mode trusts the local process and is not a multi-tenant isolation
+ boundary.
+- Exactly-once execution is not promised for arbitrary external side effects;
+ ambiguous non-idempotent outcomes stop in `NEEDS_REVIEW`.
+- Production operators must supply their identity provider, TLS ingress,
+ secret manager, audit collector, retention controls, and restricted egress.
+- See `deploy/docs/threat-model-v2.md` and
+ `deploy/docs/known-limitations-v2.md`.
+
+## Distribution and provenance
+
+The release publishes wheel and source distributions to PyPI, an immutable OCI
+image to GHCR, and a GitHub Release containing the SBOM, scans, rendered
+Kubernetes manifest, Gate C summaries, and SHA-bound evidence manifest.
diff --git a/release/notes/v2.0.0rc1.md b/release/notes/v2.0.0rc1.md
new file mode 100644
index 0000000..8990094
--- /dev/null
+++ b/release/notes/v2.0.0rc1.md
@@ -0,0 +1,51 @@
+# OpenRath v2.0.0rc1
+
+`v2.0.0rc1` is the first installable release candidate for OpenRath's durable
+Runtime and Agent Server. It is published for integration, compatibility, and
+operator validation. It is **not GA approval** and is not deployed by this
+release.
+
+## Highlights
+
+- Explicit `@step` / `@router` compilation with canonical plans and revision
+ identity.
+- Durable Run, Event, Checkpoint, Interrupt, lease/fencing, cancellation,
+ deadline, retry, and effect-reconciliation semantics.
+- PostgreSQL production storage, optional Redis signaling, and
+ S3-compatible artifact storage.
+- Tenant/project-scoped Agent Server HTTP/SSE APIs with explicit action grants,
+ bounded queues/pages/bodies, security headers, and redacted structured audit.
+- Governed Provider, Tool/MCP, Sandbox, and Memory adapter boundaries.
+- OpenTelemetry integration, datasets/experiments/feedback, migration tooling,
+ Compose/Kubernetes references, SBOM, and security gates.
+
+## Stability
+
+- The v1 Python façade remains supported during the RC.
+- The Agent Server `/v1` HTTP surface remains **Beta**.
+- v1 JSONL imports are historical and cannot resume active Runs.
+- See `deploy/docs/known-limitations-v2.md`,
+ `deploy/docs/threat-model-v2.md`, and `deploy/docs/migration-v2.md`.
+
+## RC evidence boundary
+
+This prerelease includes source/package/container CI and local/available
+backend evidence. The following remain blocking before final `v2.0.0` GA:
+
+1. Approved live LLM/provider lifecycle.
+2. Approved live OpenViking lifecycle.
+3. Target-like single-host and split-profile capacity results.
+4. One-to-four worker scaling efficiency validation.
+5. Eight-hour target-like soak.
+6. Target-cluster backup/restore, dependency-failure, rollout, and rollback
+ drills.
+7. Final API stability, v1 maintenance-window, and GA owner approval.
+
+Do not represent this RC as production certification.
+
+## Distribution
+
+- Wheel and source distribution are attached to this GitHub prerelease.
+- The OCI image is published to GHCR and identified by the digest in the
+ attached evidence manifest.
+- This RC does not publish to PyPI and does not deploy to a shared environment.
diff --git a/review/v2.0.0/README.md b/review/v2.0.0/README.md
new file mode 100644
index 0000000..479d799
--- /dev/null
+++ b/review/v2.0.0/README.md
@@ -0,0 +1,95 @@
+# OpenRath v2.0.0 review candidate
+
+Status: **historical pre-RC evidence; superseded for release decisions**
+
+This directory preserves the local implementation-review snapshot created
+before `v2.0.0rc1`. Its `1.3.0` package metadata, local image, test totals, and
+`publication=false` fields describe that snapshot only. Do not use them as the
+current release status.
+
+The authoritative RC evidence is the
+[`v2.0.0rc1` release manifest](https://github.com/Rath-Team/OpenRath/releases/download/v2.0.0rc1/manifest.json),
+bound to commit `feedcaadb79a349aa60c034618610231d83fb131` and the immutable
+OCI digest recorded in [release-approval.md](release-approval.md). The GA
+decision remains on hold until the unchecked owner and target-environment
+gates are complete.
+
+## Implemented production surface
+
+- Immutable events, explicit `@step`/`@router` compilation, canonical plans,
+ revision identity, and compatibility reporting.
+- Durable Run state machine, transactional events/checkpoints, CAS updates,
+ retries, deadlines, cancellation, priority, per-session serialization, and
+ queue backpressure.
+- SQLite local storage and PostgreSQL production storage with pooled
+ connections, `SKIP LOCKED` claims, leases, heartbeats, fencing, and orphan
+ recovery.
+- Durable human-in-the-loop interrupts with inbox, approve/edit/reject/respond,
+ actor/reason audit data, timeout expiry, and same-step resume.
+- Effect ledger for read-only, idempotent, and non-idempotent operations;
+ ambiguous outcomes enter review instead of unsafe replay.
+- Tenant-scoped local/S3 artifacts and governed Provider, Tool, Sandbox, and
+ Memory boundaries with explicit context, policy, timeout, trust, and
+ credential references.
+- Agent Server resources for Assistants, Sessions, Runs, Events/SSE,
+ Interrupts, Store, and Feedback; sync/async remote clients; authentication,
+ tenant isolation, correlation IDs, pagination, body limits, and security
+ headers.
+- OpenTelemetry trace/metric bridge, redacted structured JSON logs, durable
+ feedback, datasets, experiments, and regression gates.
+- Immutable deployment revisions, migration CLI, v1 history importer,
+ non-root/read-only OCI image, split API/worker Compose and Kubernetes
+ references, runbooks, capacity calculator, backup/restore procedure, CI,
+ SBOM, and vulnerability gate.
+
+## Evidence summary
+
+| Gate | Result |
+|---|---|
+| Ruff | passed |
+| mypy | passed, 164 source files |
+| Test suite | 1024 passed, 14 conditional skips, 1 third-party deprecation warning |
+| Real backends | PostgreSQL 17, Redis 8, and MinIO lifecycle tests passed |
+| Worker crash recovery | succeeded; 2 claims, 1 lease-expiry recovery event |
+| Backup/restore | restored isolated database; 1 Run and 6 RunEvents verified |
+| Container lifecycle | ready, Run succeeded, UID 10001, read-only root filesystem |
+| Kubernetes | kubeconform strict: 10 valid, 0 invalid |
+| Vulnerability scan | Trivy 0.67.2: 0 HIGH/CRITICAL after upgrading MCP to 1.28.1 |
+| SBOM | CycloneDX 1.6 generated |
+| Benchmark | 500 Runs; see [benchmark.json](benchmark.json) |
+| Review soak | 1050 Runs/30 s, 0 failures, 0 thread delta; see [soak.json](soak.json) |
+| Wheel smoke | isolated install, package migration resource, and server CLI passed |
+
+The local review image is
+`sha256:92fa787d8b2be51b2248c13628765ad630f0820b757f74d46514ab94f332c7f6`.
+It is intentionally not pushed.
+
+## Evidence files
+
+- [benchmark.json](benchmark.json): hardware-bound latency/throughput profile.
+- [soak.json](soak.json): bounded resource-leak review profile.
+- [sbom.cdx.json](sbom.cdx.json): CycloneDX software bill of materials.
+- [vulnerability-report.json](vulnerability-report.json): machine-readable
+ HIGH/CRITICAL scan result.
+- [release-approval.md](release-approval.md): explicit owner review and release
+ authorization gate.
+- [API governance and maintenance policy](../../deploy/docs/api-governance-v2.md):
+ stability labels, SemVer, deprecation, v1 compatibility, and private
+ vulnerability reporting.
+
+## Scope boundaries and remaining operator acceptance
+
+The following are not unreported implementation gaps:
+
+- Webhooks and cron triggers remain P2 and are deferred; Runs can be submitted
+ through the stable API or an external scheduler.
+- Exactly-once execution for arbitrary third-party side effects is not
+ promised; the supported contract is ledger + idempotency + `NEEDS_REVIEW`.
+- Enterprise UI, SAML/SCIM, billing, and cross-region active-active are outside
+ v2.0.0 scope.
+
+Before production rollout, the operator must repeat the supplied soak tool for
+the approved 8h/24h duration on target hardware, exercise the chosen live LLM,
+OpenSandbox, and OpenViking credentials if those optional adapters are enabled,
+and perform a target-cluster rollout/rollback drill. These environment-specific
+checks do not authorize a release and must be attached to the approval record.
diff --git a/review/v2.0.0/benchmark.json b/review/v2.0.0/benchmark.json
new file mode 100644
index 0000000..86ce2b0
--- /dev/null
+++ b/review/v2.0.0/benchmark.json
@@ -0,0 +1,17 @@
+{
+ "schema": "openrath.v2.benchmark/1",
+ "profile": "sqlite-single-worker-one-step",
+ "runs": 500,
+ "throughput_runs_per_second": 38.318744250606294,
+ "latency_ms": {
+ "mean": 26.053890199998932,
+ "p50": 24.10760000020673,
+ "p95": 27.95830000013666,
+ "p99": 103.07360000024346
+ },
+ "environment": {
+ "python": "3.10.18",
+ "platform": "Windows-10-10.0.26200-SP0",
+ "processor": "Intel64 Family 6 Model 183 Stepping 1, GenuineIntel"
+ }
+}
\ No newline at end of file
diff --git a/review/v2.0.0/evidence.json b/review/v2.0.0/evidence.json
new file mode 100644
index 0000000..4ec37d0
--- /dev/null
+++ b/review/v2.0.0/evidence.json
@@ -0,0 +1,66 @@
+{
+ "schema": "openrath.v2.review-evidence/1",
+ "release_state": "superseded_pre_rc_snapshot",
+ "original_release_state": "hold_for_owner_review",
+ "evidence_scope": "local implementation review before v2.0.0rc1",
+ "package_version": "1.3.0",
+ "review_target": "2.0.0",
+ "superseded_by": {
+ "candidate": "v2.0.0rc1",
+ "source_commit": "feedcaadb79a349aa60c034618610231d83fb131",
+ "release_url": "https://github.com/Rath-Team/OpenRath/releases/tag/v2.0.0rc1",
+ "manifest_url": "https://github.com/Rath-Team/OpenRath/releases/download/v2.0.0rc1/manifest.json",
+ "image": "ghcr.io/rath-team/openrath@sha256:d66a1c7933e410d290528ba5091f73a9f4e94566e1bd9d917f7fd7937c6b9be2",
+ "anonymous_manifest_verified": "2026-07-30",
+ "attestation_verified": "2026-07-30"
+ },
+ "tests": {
+ "passed": 1024,
+ "skipped": 14,
+ "warnings": 1,
+ "real_backends": [
+ "postgresql-17",
+ "redis-8",
+ "minio-s3-compatible"
+ ]
+ },
+ "static_checks": {
+ "ruff": "passed",
+ "mypy_source_files": 164,
+ "uv_lock": "passed"
+ },
+ "container": {
+ "image": "openrath:2.0.0-review",
+ "image_id": "sha256:92fa787d8b2be51b2248c13628765ad630f0820b757f74d46514ab94f332c7f6",
+ "uid": 10001,
+ "read_only_root": true,
+ "lifecycle": "passed"
+ },
+ "security": {
+ "scanner": "trivy-0.67.2",
+ "high_critical": 0,
+ "sbom": "cyclonedx-1.6",
+ "mcp_minimum_version": "1.28.1"
+ },
+ "chaos": {
+ "worker_kill_recovered": true,
+ "claim_events": 2,
+ "lease_expired_events": 1
+ },
+ "backup_restore": {
+ "restored_runs": 1,
+ "restored_run_events": 6
+ },
+ "kubernetes": {
+ "validator": "kubeconform-0.7.0-strict",
+ "valid_resources": 10,
+ "invalid_resources": 0
+ },
+ "publication": {
+ "scope": "this historical pre-RC evidence bundle",
+ "pushed": false,
+ "tagged": false,
+ "released": false,
+ "deployed": false
+ }
+}
diff --git a/review/v2.0.0/release-approval.md b/review/v2.0.0/release-approval.md
new file mode 100644
index 0000000..be96590
--- /dev/null
+++ b/review/v2.0.0/release-approval.md
@@ -0,0 +1,58 @@
+# OpenRath v2 release approval
+
+Current decision: **v2.0.0rc1 PUBLICATION AUTHORIZED; v2.0.0 GA HOLD**
+
+The repository owner explicitly requested publication of an RC on 2026-07-29.
+That authorizes the following RC-only actions:
+
+- changing package metadata to `2.0.0rc1`;
+- pushing the `codex/v2-review-remediation` branch;
+- creating and pushing the `v2.0.0rc1` tag;
+- publishing wheel/sdist as GitHub prerelease assets;
+- publishing the RC image to GHCR by immutable digest;
+- creating a GitHub prerelease.
+
+The following remain prohibited until separately approved:
+
+- changing package metadata to final `2.0.0`;
+- creating or pushing the final `v2.0.0` tag;
+- publishing the final PyPI/GHCR/GitHub release;
+- deploying to any shared, staging, or production environment.
+
+## RC publication record
+
+The authorized RC publication completed from source commit
+`feedcaadb79a349aa60c034618610231d83fb131`:
+
+- release workflow:
+ ;
+- GitHub prerelease:
+ ;
+- OCI artifact:
+ `ghcr.io/rath-team/openrath@sha256:d66a1c7933e410d290528ba5091f73a9f4e94566e1bd9d917f7fd7937c6b9be2`.
+
+Anonymous OCI manifest retrieval and GitHub attestation verification passed on
+2026-07-30. This record closes RC artifact publication only; it does not change
+the GA hold or approve a shared deployment.
+
+## Owner review checklist
+
+- [ ] Review public SDK/API compatibility and the stable error model.
+- [ ] Review SecurityContext, tenant, policy, trust, secret, Tool, Memory, and
+ Sandbox boundaries.
+- [ ] Review durable Run/checkpoint/interrupt/effect recovery semantics.
+- [ ] Review PostgreSQL migrations, v1 import, backup/restore, and rollback.
+- [ ] Review Agent Server authentication, resource isolation, SSE, limits, and
+ split API/worker deployment.
+- [ ] Review SBOM, zero-HIGH/CRITICAL scan, benchmark, soak, and chaos evidence.
+- [ ] Approve the v1 maintenance window and v2 support/security policy.
+- [ ] Attach target-environment extended soak, optional live-adapter, and
+ rollout/rollback evidence when applicable.
+- [ ] Explicitly authorize version bump, tag, push, image publication, and
+ release.
+
+Approval must be explicit. Silence, code review completion, or a passing CI
+run does not authorize publication.
+
+RC publication is not evidence that the unchecked GA items passed. The
+prerelease must link the unresolved Gate C items and remain marked prerelease.
diff --git a/review/v2.0.0/sbom.cdx.json b/review/v2.0.0/sbom.cdx.json
new file mode 100644
index 0000000..6d3d3e8
--- /dev/null
+++ b/review/v2.0.0/sbom.cdx.json
@@ -0,0 +1,9402 @@
+{
+ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.6",
+ "serialNumber": "urn:uuid:a6e9217d-ff2d-4aa5-ad9a-e9dae394259a",
+ "version": 1,
+ "metadata": {
+ "timestamp": "2026-07-27T11:32:21+00:00",
+ "tools": {
+ "components": [
+ {
+ "type": "application",
+ "manufacturer": {
+ "name": "Aqua Security Software Ltd."
+ },
+ "group": "aquasecurity",
+ "name": "trivy",
+ "version": "0.67.2"
+ }
+ ]
+ },
+ "component": {
+ "bom-ref": "a8a162b2-37e7-4097-9741-311f48a2e27a",
+ "type": "container",
+ "name": "openrath:2.0.0-review",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:82d0cec9fb0c30115a70fe1863820ee9af9f2b16e211e6e5233beb4aa7c9386a"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:DiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:ImageID",
+ "value": "sha256:92fa787d8b2be51b2248c13628765ad630f0820b757f74d46514ab94f332c7f6"
+ },
+ {
+ "name": "aquasecurity:trivy:RepoTag",
+ "value": "openrath:2.0.0-review"
+ },
+ {
+ "name": "aquasecurity:trivy:SchemaVersion",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:Size",
+ "value": "238930944"
+ }
+ ]
+ }
+ },
+ "components": [
+ {
+ "bom-ref": "3f6f6949-37ac-4670-9c65-1265e18f14ff",
+ "type": "operating-system",
+ "name": "debian",
+ "version": "13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:Class",
+ "value": "os-pkgs"
+ },
+ {
+ "name": "aquasecurity:trivy:Type",
+ "value": "debian"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Adduser Developers "
+ },
+ "name": "adduser",
+ "version": "3.152",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "adduser@3.152"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "adduser"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.152"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "APT Development Team "
+ },
+ "name": "apt",
+ "version": "3.0.3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "curl"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "apt@3.0.3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "apt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.0.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Santiago Vila "
+ },
+ "name": "base-files",
+ "version": "13.8+deb13u6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "verbatim"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "base-files@13.8+deb13u6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "base-files"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "13.8+deb13u6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "base-passwd",
+ "version": "3.6.7",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "base-passwd@3.6.7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "base-passwd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.6.7"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "bash",
+ "version": "5.2.37-2+b9",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "name": "Latex2e"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "permissive"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "bash@5.2.37-2+b9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "bash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.2.37"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "bsdutils",
+ "version": "1:2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "bsdutils@1:2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Julien Cristau "
+ },
+ "name": "ca-certificates",
+ "version": "20250419",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MPL-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ca-certificates@20250419"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ca-certificates"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "20250419"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Michael Stone "
+ },
+ "name": "coreutils",
+ "version": "9.7-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "coreutils@9.7-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "coreutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "9.7"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Andrej Shadura "
+ },
+ "name": "dash",
+ "version": "0.5.12-12",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "dash@0.5.12-12"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "dash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.5.12"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debconf Developers "
+ },
+ "name": "debconf",
+ "version": "1.5.91",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debconf@1.5.91"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debconf"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.91"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Release Team "
+ },
+ "name": "debian-archive-keyring",
+ "version": "2025.1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debian-archive-keyring@2025.1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debian-archive-keyring"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2025.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ileana Dumitrescu "
+ },
+ "name": "debianutils",
+ "version": "5.23.2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "SMAIL-GPL"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "debianutils@5.23.2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "debianutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.23.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Santiago Vila "
+ },
+ "name": "diffutils",
+ "version": "1:3.10-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH texinfo-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "diffutils@1:3.10-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "diffutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Dpkg Developers "
+ },
+ "name": "dpkg",
+ "version": "1.22.22",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-s-s-d"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "dpkg@1.22.22"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "dpkg"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.22.22"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Andreas Metzler "
+ },
+ "name": "findutils",
+ "version": "4.10.0-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH Autoconf-data-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Autoconf-data-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH automake-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-2.2-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "findutils@4.10.0-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "findutils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.10.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "gcc-14-base",
+ "version": "14.2.0-19",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.2-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "gcc-14-base@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Anibal Monsalve Salazar "
+ },
+ "name": "grep",
+ "version": "3.11-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "grep@3.11-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "grep"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.11"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Milan Kupcevic "
+ },
+ "name": "gzip",
+ "version": "1.13-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GFDL-1.3--no-invariant"
+ }
+ },
+ {
+ "license": {
+ "name": "FSF-manpages"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GFDL-3"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "gzip@1.13-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gzip"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Michael Meskes "
+ },
+ "name": "hostname",
+ "version": "3.25",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "hostname@3.25"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "hostname"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.25"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "init-system-helpers",
+ "version": "1.69~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "init-system-helpers@1.69~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "init-system-helpers"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.69~deb13u1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libacl1",
+ "version": "2.3.2-2+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libacl1@2.3.2-2+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "acl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.3.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "APT Development Team "
+ },
+ "name": "libapt-pkg7.0",
+ "version": "3.0.3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "curl"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libapt-pkg7.0@3.0.3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "apt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.0.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libattr1",
+ "version": "1:2.5.2-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libattr1@1:2.5.2-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "attr"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.5.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Laurent Bigonville "
+ },
+ "name": "libaudit-common",
+ "version": "1:4.0.2-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libaudit-common@1:4.0.2-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "audit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.0.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Laurent Bigonville "
+ },
+ "name": "libaudit1",
+ "version": "1:4.0.2-2+b2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libaudit1@1:4.0.2-2+b2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "audit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.0.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libblkid1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libblkid1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libbsd0",
+ "version": "0.12.2-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Regents"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause-NetBSD"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-author"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-John-Birrell"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-5-clause-Peter-Wemm"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-2-clause-verbatim"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-2-clause-author"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-Original"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libbsd0@0.12.2-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libbsd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.12.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Anibal Monsalve Salazar "
+ },
+ "name": "libbz2-1.0",
+ "version": "1.0.8-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libbz2-1.0@1.0.8-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "bzip2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.0.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "libc-bin",
+ "version": "2.41-12+deb13u3",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "LGPL-2.1-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "Carnegie"
+ }
+ },
+ {
+ "license": {
+ "name": "Inner-Net"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-like-Lord"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-like-Spencer"
+ }
+ },
+ {
+ "license": {
+ "name": "PCRE"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Carnegie"
+ }
+ },
+ {
+ "license": {
+ "id": "Unicode-DFS-2016"
+ }
+ },
+ {
+ "license": {
+ "id": "BSL-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "SunPro"
+ }
+ },
+ {
+ "license": {
+ "name": "CORE-MATH"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Berkeley"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-WIDE"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Oracle"
+ }
+ },
+ {
+ "license": {
+ "name": "DEC"
+ }
+ },
+ {
+ "license": {
+ "name": "IBM"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Univ-Coimbra"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libc-bin@2.41-12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "glibc"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "libc6",
+ "version": "2.41-12+deb13u3",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "LGPL-2.1-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-or-later WITH link-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "Carnegie"
+ }
+ },
+ {
+ "license": {
+ "name": "Inner-Net"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-like-Lord"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-like-Spencer"
+ }
+ },
+ {
+ "license": {
+ "name": "PCRE"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Carnegie"
+ }
+ },
+ {
+ "license": {
+ "id": "Unicode-DFS-2016"
+ }
+ },
+ {
+ "license": {
+ "id": "BSL-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "SunPro"
+ }
+ },
+ {
+ "license": {
+ "name": "CORE-MATH"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Berkeley"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-WIDE"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Oracle"
+ }
+ },
+ {
+ "license": {
+ "name": "DEC"
+ }
+ },
+ {
+ "license": {
+ "name": "IBM"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Univ-Coimbra"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libc6@2.41-12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "glibc"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "12+deb13u3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Håvard F. Aasen "
+ },
+ "name": "libcap-ng0",
+ "version": "0.8.5-4+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcap-ng0@0.8.5-4+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcap-ng"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.8.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Christian Kastner "
+ },
+ "name": "libcap2",
+ "version": "1:2.75-10+deb13u1+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcap2@1:2.75-10+deb13u1+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcap2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "10+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.75"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Marco d'Itri "
+ },
+ "name": "libcrypt1",
+ "version": "1:4.4.38-1",
+ "purl": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcrypt1@1:4.4.38-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libxcrypt"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.4.38"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian QA Group "
+ },
+ "name": "libdb5.3t64",
+ "version": "5.3.28+dfsg2-9",
+ "licenses": [
+ {
+ "license": {
+ "id": "Sleepycat"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MS-PL"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "name": "MIT-old"
+ }
+ },
+ {
+ "license": {
+ "name": "TCL-like"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-fjord"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libdb5.3t64@5.3.28+dfsg2-9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "db5.3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.3.28+dfsg2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Install System Team "
+ },
+ "name": "libdebconfclient0",
+ "version": "0.280",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libdebconfclient0@0.280"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "cdebconf"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.280"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libffi8",
+ "version": "3.4.8-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "MPL-1.1"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libffi8@3.4.8-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libffi"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.4.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libgcc-s1",
+ "version": "14.2.0-19",
+ "purl": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgcc-s1@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Nicolas Mora "
+ },
+ "name": "libgdbm6t64",
+ "version": "1.24-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgdbm6t64@1.24-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gdbm"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.24"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Science Maintainers "
+ },
+ "name": "libgmp10",
+ "version": "2:6.3.0+dfsg-3",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libgmp10@2:6.3.0+dfsg-3"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gmp"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.3.0+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Magnus Holmgren "
+ },
+ "name": "libhogweed6t64",
+ "version": "3.10.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GAP"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libhogweed6t64@3.10.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "nettle"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "liblastlog2-2",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblastlog2-2@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Nobuhiro Iwamatsu "
+ },
+ "name": "liblz4-1",
+ "version": "1.10.0-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblz4-1@1.10.0-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "lz4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.10.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sebastian Andrzej Siewior "
+ },
+ "name": "liblzma5",
+ "version": "5.8.1-1+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "0BSD"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFULLR"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Autoconf-exception-macro"
+ }
+ },
+ {
+ "license": {
+ "name": "none"
+ }
+ },
+ {
+ "license": {
+ "name": "PD"
+ }
+ },
+ {
+ "license": {
+ "name": "permissive-nowarranty"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFUL"
+ }
+ },
+ {
+ "license": {
+ "name": "noderivs"
+ }
+ },
+ {
+ "license": {
+ "name": "PD-debian"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "liblzma5@5.8.1-1+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "xz-utils"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Guillem Jover "
+ },
+ "name": "libmd0",
+ "version": "1.1.0-2+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-Aaron-D-Gifford"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause-NetBSD"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-md4"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-md5"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain-sha1"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libmd0@1.1.0-2+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libmd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.1.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libmount1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libmount1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "libncursesw6",
+ "version": "6.5+20250216-2",
+ "purl": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libncursesw6@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Magnus Holmgren "
+ },
+ "name": "libnettle8t64",
+ "version": "3.10.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-only WITH autoconf-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GAP"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libnettle8t64@3.10.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "nettle"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.10.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-modules-bin",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-modules-bin@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-modules",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-modules@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam-runtime",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam-runtime@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Sam Hartman "
+ },
+ "name": "libpam0g",
+ "version": "1.7.0-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-tcp-wrappers"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "name": "Beerware"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpam0g@1.7.0-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pam"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.7.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthew Vernon "
+ },
+ "name": "libpcre2-8-0",
+ "version": "10.46-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "BSD-3-clause-Cambridge WITH BINARY-LIBRARY-LIKE-PACKAGES-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libpcre2-8-0@10.46-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pcre2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "10.46"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "libreadline8t64",
+ "version": "8.2-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-no-attribution"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libreadline8t64@8.2-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "readline"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Kees Cook "
+ },
+ "name": "libseccomp2",
+ "version": "2.6.0-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libseccomp2@2.6.0-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libseccomp"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.6.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libselinux1",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libselinux1@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libselinux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsemanage-common",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsemanage-common@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsemanage"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsemanage2",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsemanage2@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsemanage"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian SELinux maintainers "
+ },
+ "name": "libsepol2",
+ "version": "3.8.1-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsepol2@3.8.1-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libsepol"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.8.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libsmartcols1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsmartcols1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Laszlo Boszormenyi (GCS) "
+ },
+ "name": "libsqlite3-0",
+ "version": "3.46.1-7+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsqlite3-0@3.46.1-7+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sqlite3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "7+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.46.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "libssl3t64",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libssl3t64@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian GCC Maintainers "
+ },
+ "name": "libstdc++6",
+ "version": "14.2.0-19",
+ "purl": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libstdc++6@14.2.0-19"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "gcc-14"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "14.2.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "libsystemd0",
+ "version": "257.13-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH Linux-syscall-note-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libsystemd0@257.13-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "systemd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "257.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "libtinfo6",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libtinfo6@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian systemd Maintainers "
+ },
+ "name": "libudev1",
+ "version": "257.13-1~deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH Linux-syscall-note-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libudev1@257.13-1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "systemd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "257.13"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "libuuid1",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libuuid1@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Josue Ortega "
+ },
+ "name": "libxxhash0",
+ "version": "0.8.3-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libxxhash0@0.8.3-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "xxhash"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "0.8.3"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "RPM packaging team "
+ },
+ "name": "libzstd1",
+ "version": "1.5.7+dfsg-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libzstd1@1.5.7+dfsg-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libzstd"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.7+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "login.defs",
+ "version": "1:4.17.4-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "login.defs@1:4.17.4-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "shadow"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.17.4"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "login",
+ "version": "1:4.16.0-2+really2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "login@1:4.16.0-2+really2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Boyuan Yang "
+ },
+ "name": "mawk",
+ "version": "1.3.4.20250131-1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "CC-BY-3.0"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "mawk@1.3.4.20250131-1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "mawk"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.4.20250131"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "mount",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "mount@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "ncurses-base",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ncurses-base@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Ncurses Maintainers "
+ },
+ "name": "ncurses-bin",
+ "version": "6.5+20250216-2",
+ "licenses": [
+ {
+ "license": {
+ "name": "MIT-X11"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "ncurses-bin@6.5+20250216-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "ncurses"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5+20250216"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Marco d'Itri "
+ },
+ "name": "netbase",
+ "version": "6.5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "netbase@6.5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "netbase"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "6.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "openssl-provider-legacy",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "openssl-provider-legacy@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian OpenSSL Team "
+ },
+ "name": "openssl",
+ "version": "3.5.6-1~deb13u2",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "openssl@3.5.6-1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "openssl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1~deb13u2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.5.6"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Shadow package maintainers "
+ },
+ "name": "passwd",
+ "version": "1:4.17.4-2",
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "passwd@1:4.17.4-2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "shadow"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.17.4"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Niko Tyni "
+ },
+ "name": "perl-base",
+ "version": "5.40.1-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-1.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "Artistic-2.0"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "name": "REGCOMP"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-2.0-only WITH bison-exception+"
+ }
+ },
+ {
+ "license": {
+ "name": "Unicode"
+ }
+ },
+ {
+ "license": {
+ "name": "BZIP"
+ }
+ },
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "FSFAP"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-Clause WITH weird-numbering"
+ }
+ },
+ {
+ "license": {
+ "id": "CC0-1.0"
+ }
+ },
+ {
+ "license": {
+ "name": "TEXT-TABS"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-4-clause-POWERDOG"
+ }
+ },
+ {
+ "license": {
+ "name": "BSD-3-clause-GENERIC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "SDBM-PUBLIC-DOMAIN"
+ }
+ },
+ {
+ "license": {
+ "name": "DONT-CHANGE-THE-GPL"
+ }
+ },
+ {
+ "license": {
+ "name": "Artistic-dist"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-1.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "Artistic-2"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "perl-base@5.40.1-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "perl"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "5.40.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Matthias Klose "
+ },
+ "name": "readline-common",
+ "version": "8.2-6",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "ISC-no-attribution"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "readline-common@8.2-6"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "readline"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "6"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.2"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Clint Adams "
+ },
+ "name": "sed",
+ "version": "4.9-2+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "X11"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-no-invariants-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GFDL-1.3-only"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause-UC"
+ }
+ },
+ {
+ "license": {
+ "name": "BSL-1"
+ }
+ },
+ {
+ "license": {
+ "name": "pcre"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sed@4.9-2+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sed"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "2+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "4.9"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian Rust Maintainers "
+ },
+ "name": "sqv",
+ "version": "1.3.0-3+b2",
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sqv@1.3.0-3+b2"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "rust-sequoia-sqv"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.0"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Debian sysvinit maintainers "
+ },
+ "name": "sysvinit-utils",
+ "version": "3.14-4",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "sysvinit-utils@3.14-4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "sysvinit"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "4"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "3.14"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Janos Lenart "
+ },
+ "name": "tar",
+ "version": "1.35+dfsg-3.1",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "name": "GPL-3.0-or-later WITH Bison-exception"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "tar@1.35+dfsg-3.1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "tar"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3.1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.35+dfsg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "GNU Libc Maintainers "
+ },
+ "name": "tzdata",
+ "version": "2026b-0+deb13u1",
+ "licenses": [
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "tzdata@2026b-0+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "tzdata"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "0+deb13u1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2026b"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "type": "library",
+ "supplier": {
+ "name": "Chris Hofstaedtler "
+ },
+ "name": "util-linux",
+ "version": "2.41-5",
+ "licenses": [
+ {
+ "license": {
+ "id": "GPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-or-later"
+ }
+ },
+ {
+ "license": {
+ "name": "public-domain"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-4-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "ISC"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "name": "BSLA"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "BSD-2-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-or-later"
+ }
+ },
+ {
+ "license": {
+ "id": "GPL-3.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.0-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-2.1-only"
+ }
+ },
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "util-linux@2.41-5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "util-linux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "5"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.41"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "type": "library",
+ "supplier": {
+ "name": "Mark Brown "
+ },
+ "name": "zlib1g",
+ "version": "1:1.3.dfsg+really1.3.1-1+b1",
+ "licenses": [
+ {
+ "license": {
+ "id": "Zlib"
+ }
+ }
+ ],
+ "purl": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcEpoch",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "zlib"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "1"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.3.dfsg+really1.3.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/annotated-types@0.7.0",
+ "type": "library",
+ "name": "annotated-types",
+ "version": "0.7.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "b11011181822ac765c9f66c8aa42c26952de6a96"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/annotated-types@0.7.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/anthropic@0.104.1",
+ "type": "library",
+ "name": "anthropic",
+ "version": "0.104.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "6a0fce5932599b482bf25ed3db3c06e9211f1358"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/anthropic@0.104.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/anthropic-0.104.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/anyio@4.13.0",
+ "type": "library",
+ "name": "anyio",
+ "version": "4.13.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5f30168435645daddf756ecef34992631c6e778b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/anyio@4.13.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/anyio-4.13.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/attrs@26.1.0",
+ "type": "library",
+ "name": "attrs",
+ "version": "26.1.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "89068272cc1dc340d8fd910a62be241c42414339"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/attrs@26.1.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/attrs-26.1.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/boto3@1.43.56",
+ "type": "library",
+ "name": "boto3",
+ "version": "1.43.56",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f5c7842f2414d0cd2cefdb918d07c52018450ff7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/boto3@1.43.56",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/boto3-1.43.56.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/botocore@1.43.56",
+ "type": "library",
+ "name": "botocore",
+ "version": "1.43.56",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "b8760d1db82eba72c06ec96252b62d541a21b09e"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/botocore@1.43.56",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/botocore-1.43.56.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/certifi@2026.5.20",
+ "type": "library",
+ "name": "certifi",
+ "version": "2026.5.20",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cb42a7b0ba6491d51e71ff594a39bfaf5b8f9d22"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MPL-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/certifi@2026.5.20",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/certifi-2026.5.20.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/cffi@2.0.0",
+ "type": "library",
+ "name": "cffi",
+ "version": "2.0.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "87e9c9d276c4f4c31f5a314d6a5472f45655674c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/cffi@2.0.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/cffi-2.0.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/click@8.4.1",
+ "type": "library",
+ "name": "click",
+ "version": "8.4.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "c486957c59cc28072021bdcfe6d681e9ddafc860"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/click@8.4.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/click-8.4.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/cryptography@49.0.0",
+ "type": "library",
+ "name": "cryptography",
+ "version": "49.0.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "739372eb2cc71602103a206e7a42a926930cecb6"
+ }
+ ],
+ "licenses": [
+ {
+ "expression": "Apache-2.0 OR BSD-3-Clause"
+ }
+ ],
+ "purl": "pkg:pypi/cryptography@49.0.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/cryptography-49.0.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/distro@1.9.0",
+ "type": "library",
+ "name": "distro",
+ "version": "1.9.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ce14620cf14e15a64d2ff574796543f99619e7f3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/distro@1.9.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/distro-1.9.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/docstring-parser@0.18.0",
+ "type": "library",
+ "name": "docstring_parser",
+ "version": "0.18.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cd475f73b404c399cf87b9fb990fc14669479d24"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/docstring-parser@0.18.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/docstring_parser-0.18.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/h11@0.16.0",
+ "type": "library",
+ "name": "h11",
+ "version": "0.16.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5d41eddffefef5f6e8ff383a2537e81a38a37807"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/h11@0.16.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/h11-0.16.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpcore@1.0.9",
+ "type": "library",
+ "name": "httpcore",
+ "version": "1.0.9",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "2981d359ae33f31d339189a9680db85785339a56"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpcore@1.0.9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpcore-1.0.9.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpx-sse@0.4.3",
+ "type": "library",
+ "name": "httpx-sse",
+ "version": "0.4.3",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "df05446be58f0a3a306e50c7ceebef24bb383a6d"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpx-sse@0.4.3",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpx_sse-0.4.3.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/httpx@0.28.1",
+ "type": "library",
+ "name": "httpx",
+ "version": "0.28.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "537da7e4f29438278e124e10e02d1a500fe33bcc"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/httpx@0.28.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/idna@3.16",
+ "type": "library",
+ "name": "idna",
+ "version": "3.16",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "191a7bf1dac83b0cc997024ebb4b8da5c962ae5b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/idna@3.16",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/idna-3.16.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jiter@0.15.0",
+ "type": "library",
+ "name": "jiter",
+ "version": "0.15.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9de68ecc913d85eafa70a1252b2f5b1b2d2829f5"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jiter@0.15.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jiter-0.15.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jmespath@1.1.0",
+ "type": "library",
+ "name": "jmespath",
+ "version": "1.1.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d3f297922cf04b0cc127a18994ad6e6b947f0cc7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jmespath@1.1.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jmespath-1.1.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "type": "library",
+ "name": "jsonschema-specifications",
+ "version": "2025.9.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ac33f477be9d3336ae67bc454f68a9ff39c91cf3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/jsonschema@4.26.0",
+ "type": "library",
+ "name": "jsonschema",
+ "version": "4.26.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "94b3d1a46cf55d74e42c401eaf4a4b71c76cee31"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/jsonschema@4.26.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/jsonschema-4.26.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/mcp@1.28.1",
+ "type": "library",
+ "name": "mcp",
+ "version": "1.28.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "22fedbbf2f1d94917eba0c0c156781325bd3d786"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/mcp@1.28.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/mcp-1.28.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/openai@2.38.0",
+ "type": "library",
+ "name": "openai",
+ "version": "2.38.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ea17f685d13b1a896fb055b3bedbfcb5ed8da63a"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/openai@2.38.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/openai-2.38.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/openrath@1.3.0",
+ "type": "library",
+ "name": "openrath",
+ "version": "1.3.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d04d62d29a60270300a6eefa18f542d44f8d14fc"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/openrath@1.3.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/openrath-1.3.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-api@1.42.1",
+ "type": "library",
+ "name": "opentelemetry-api",
+ "version": "1.42.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "a54ebbf560cfb13acfd3d7f7a5c385f03e36be08"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-api@1.42.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_api-1.42.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "type": "library",
+ "name": "opentelemetry-sdk",
+ "version": "1.42.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "cdfb9c90d3e4765c62ffce81a835445a8efef7c4"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_sdk-1.42.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "type": "library",
+ "name": "opentelemetry-semantic-conventions",
+ "version": "0.63b1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "5c7aaa298ae1ba489d7214ebec1427bd3f602556"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/opentelemetry_semantic_conventions-0.63b1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pip@25.0.1",
+ "type": "library",
+ "name": "pip",
+ "version": "25.0.1",
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pip@25.0.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "usr/local/lib/python3.12/site-packages/pip-25.0.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg-binary@3.3.4",
+ "type": "library",
+ "name": "psycopg-binary",
+ "version": "3.3.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "e8c69d729c969a8a81834cce24f8947ad560813d"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg-binary@3.3.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg_binary-3.3.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg-pool@3.3.1",
+ "type": "library",
+ "name": "psycopg-pool",
+ "version": "3.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "60d07aa411067306f5244d0481227a78a5b11135"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg-pool@3.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg_pool-3.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg@3.3.4",
+ "type": "library",
+ "name": "psycopg",
+ "version": "3.3.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "dc38178dd59b090117f63d60bc627e6a168205c8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "LGPL-3.0-only"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/psycopg@3.3.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/psycopg-3.3.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "type": "library",
+ "name": "psycopg_binary",
+ "version": "3.3.4",
+ "purl": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "psycopg_binary@3.3.4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "type": "library",
+ "name": "psycopg_binary",
+ "version": "3.3.4",
+ "purl": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "psycopg_binary@3.3.4"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pycparser@3.0",
+ "type": "library",
+ "name": "pycparser",
+ "version": "3.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "ec46323dcd4dd2f7742b74b09cc0b030e330e46f"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pycparser@3.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pycparser-3.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic-core@2.46.4",
+ "type": "library",
+ "name": "pydantic_core",
+ "version": "2.46.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f44318e9ae79f745f1f5a7a59b43044ab6fff485"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic-core@2.46.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic_core-2.46.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic-settings@2.14.1",
+ "type": "library",
+ "name": "pydantic-settings",
+ "version": "2.14.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "b9246a1f2d8974cb71bb7ec65fb8a9f45710d89a"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic-settings@2.14.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic_settings-2.14.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pydantic@2.13.4",
+ "type": "library",
+ "name": "pydantic",
+ "version": "2.13.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "291e482df82749c7e52c21e8275551f04de3034b"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pydantic@2.13.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pydantic-2.13.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/pyjwt@2.13.0",
+ "type": "library",
+ "name": "PyJWT",
+ "version": "2.13.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "78125d2bb60e70bc168fd8787075ceb6a69d4f65"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/pyjwt@2.13.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/pyjwt-2.13.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "type": "library",
+ "name": "python-dateutil",
+ "version": "2.9.0.post0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "7a3c35abd86cd96034d5afb0d4b241dc9e13e6f8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ },
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-dotenv@1.2.2",
+ "type": "library",
+ "name": "python-dotenv",
+ "version": "1.2.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "a70b92340410dfaf8ce628e658f176278fa2e557"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-dotenv@1.2.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_dotenv-1.2.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/python-multipart@0.0.32",
+ "type": "library",
+ "name": "python-multipart",
+ "version": "0.0.32",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9f79572b3702bdac7487183b498470341276b17e"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/python-multipart@0.0.32",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/python_multipart-0.0.32.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/redis@6.4.0",
+ "type": "library",
+ "name": "redis",
+ "version": "6.4.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9a3de9ffc83addb0d845a4f16c6a415db91a3eda"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/redis@6.4.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/redis-6.4.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/referencing@0.37.0",
+ "type": "library",
+ "name": "referencing",
+ "version": "0.37.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f6fa004340bef5d23995b09dab75ce12e3f367a7"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/referencing@0.37.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/referencing-0.37.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/rpds-py@0.30.0",
+ "type": "library",
+ "name": "rpds-py",
+ "version": "0.30.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9eef46c842a0ca6229680d7bfc1272958efdcc5a"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/rpds-py@0.30.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/rpds_py-0.30.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/s3transfer@0.19.2",
+ "type": "library",
+ "name": "s3transfer",
+ "version": "0.19.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "453d1af3240f56bb5d0bd093eb3d21a250cc5777"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/s3transfer@0.19.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/s3transfer-0.19.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/six@1.17.0",
+ "type": "library",
+ "name": "six",
+ "version": "1.17.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "483a26554261f6c839703c0e1183f3ef33ff97f1"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/six@1.17.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/sniffio@1.3.1",
+ "type": "library",
+ "name": "sniffio",
+ "version": "1.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "bc1d7aead770fe23c8d22666b84558edb3686da3"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ },
+ {
+ "license": {
+ "id": "Apache-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/sniffio@1.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/sse-starlette@3.4.4",
+ "type": "library",
+ "name": "sse-starlette",
+ "version": "3.4.4",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "58e4ad3946eafb572e0219f89bb599bee2b7cca2"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/sse-starlette@3.4.4",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/sse_starlette-3.4.4.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/starlette@1.3.1",
+ "type": "library",
+ "name": "starlette",
+ "version": "1.3.1",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "9e43f99dc64bcf4498d65999f9cb36a40fa5e94c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/starlette@1.3.1",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/starlette-1.3.1.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/tqdm@4.67.3",
+ "type": "library",
+ "name": "tqdm",
+ "version": "4.67.3",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "0135af1981d2b0f1326020f991192d869693b873"
+ }
+ ],
+ "licenses": [
+ {
+ "expression": "MPL-2.0 AND MIT"
+ }
+ ],
+ "purl": "pkg:pypi/tqdm@4.67.3",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/tqdm-4.67.3.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/typing-extensions@4.15.0",
+ "type": "library",
+ "name": "typing_extensions",
+ "version": "4.15.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "c5c2ce18351f8f2ae0f4a6f7c84c523f342010ee"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "name": "PSF-2.0"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/typing-extensions@4.15.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/typing_extensions-4.15.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/typing-inspection@0.4.2",
+ "type": "library",
+ "name": "typing-inspection",
+ "version": "0.4.2",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "455fdb9c8e246ba02c2a28655287401b62028b60"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/typing-inspection@0.4.2",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/typing_inspection-0.4.2.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/urllib3@2.7.0",
+ "type": "library",
+ "name": "urllib3",
+ "version": "2.7.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d20520d0598c114ced8d55ed14209a2a3bbee22c"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/urllib3@2.7.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/urllib3-2.7.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:pypi/uvicorn@0.47.0",
+ "type": "library",
+ "name": "uvicorn",
+ "version": "0.47.0",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "f55652a6d9d6137b9be4cfc40b4c3d30b63717f8"
+ }
+ ],
+ "licenses": [
+ {
+ "license": {
+ "id": "BSD-3-Clause"
+ }
+ }
+ ],
+ "purl": "pkg:pypi/uvicorn@0.47.0",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:FilePath",
+ "value": "opt/venv/lib/python3.12/site-packages/uvicorn-0.47.0.dist-info/METADATA"
+ },
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "python-pkg"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "type": "library",
+ "name": "cyrus-sasl-lib",
+ "version": "2.1.26-24.el7_9",
+ "purl": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "cyrus-sasl-lib@2.1.26-24.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "cyrus-sasl-lib"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "24.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.1.26"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "type": "library",
+ "name": "keyutils-libs",
+ "version": "1.5.8-3.el7",
+ "purl": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "keyutils-libs@1.5.8-3.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "keyutils-libs"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "3.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.5.8"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#5b1da461e2c57feebadb3f96f47736f4b17ad56a83895f95d60a166ced6472b0",
+ "type": "library",
+ "name": "krb5-libs",
+ "version": "1.15.1-55.el7_9",
+ "purl": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "krb5-libs@1.15.1-55.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "krb5-libs"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "55.el7_9"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.15.1"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "type": "library",
+ "name": "libcom_err",
+ "version": "1.42.9-19.el7",
+ "purl": "pkg:rpm/centos/libcom_err@1.42.9-19.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libcom_err@1.42.9-19.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libcom_err"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "19.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "1.42.9"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "type": "library",
+ "name": "libselinux",
+ "version": "2.5-15.el7",
+ "purl": "pkg:rpm/centos/libselinux@2.5-15.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "libselinux@2.5-15.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "libselinux"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "15.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "2.5"
+ }
+ ]
+ },
+ {
+ "bom-ref": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72",
+ "type": "library",
+ "name": "pcre",
+ "version": "8.32-17.el7",
+ "purl": "pkg:rpm/centos/pcre@8.32-17.el7",
+ "properties": [
+ {
+ "name": "aquasecurity:trivy:LayerDiffID",
+ "value": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgID",
+ "value": "pcre@8.32-17.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:PkgType",
+ "value": "debian"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcName",
+ "value": "pcre"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcRelease",
+ "value": "17.el7"
+ },
+ {
+ "name": "aquasecurity:trivy:SrcVersion",
+ "value": "8.32"
+ }
+ ]
+ }
+ ],
+ "dependencies": [
+ {
+ "ref": "3f6f6949-37ac-4670-9c65-1265e18f14ff",
+ "dependsOn": [
+ "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#5b1da461e2c57feebadb3f96f47736f4b17ad56a83895f95d60a166ced6472b0",
+ "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72"
+ ]
+ },
+ {
+ "ref": "a8a162b2-37e7-4097-9741-311f48a2e27a",
+ "dependsOn": [
+ "3f6f6949-37ac-4670-9c65-1265e18f14ff",
+ "pkg:pypi/annotated-types@0.7.0",
+ "pkg:pypi/anthropic@0.104.1",
+ "pkg:pypi/anyio@4.13.0",
+ "pkg:pypi/attrs@26.1.0",
+ "pkg:pypi/boto3@1.43.56",
+ "pkg:pypi/botocore@1.43.56",
+ "pkg:pypi/certifi@2026.5.20",
+ "pkg:pypi/cffi@2.0.0",
+ "pkg:pypi/click@8.4.1",
+ "pkg:pypi/cryptography@49.0.0",
+ "pkg:pypi/distro@1.9.0",
+ "pkg:pypi/docstring-parser@0.18.0",
+ "pkg:pypi/h11@0.16.0",
+ "pkg:pypi/httpcore@1.0.9",
+ "pkg:pypi/httpx-sse@0.4.3",
+ "pkg:pypi/httpx@0.28.1",
+ "pkg:pypi/idna@3.16",
+ "pkg:pypi/jiter@0.15.0",
+ "pkg:pypi/jmespath@1.1.0",
+ "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "pkg:pypi/jsonschema@4.26.0",
+ "pkg:pypi/mcp@1.28.1",
+ "pkg:pypi/openai@2.38.0",
+ "pkg:pypi/openrath@1.3.0",
+ "pkg:pypi/opentelemetry-api@1.42.1",
+ "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "pkg:pypi/pip@25.0.1",
+ "pkg:pypi/psycopg-binary@3.3.4",
+ "pkg:pypi/psycopg-pool@3.3.1",
+ "pkg:pypi/psycopg@3.3.4",
+ "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "pkg:pypi/pycparser@3.0",
+ "pkg:pypi/pydantic-core@2.46.4",
+ "pkg:pypi/pydantic-settings@2.14.1",
+ "pkg:pypi/pydantic@2.13.4",
+ "pkg:pypi/pyjwt@2.13.0",
+ "pkg:pypi/python-dateutil@2.9.0.post0",
+ "pkg:pypi/python-dotenv@1.2.2",
+ "pkg:pypi/python-multipart@0.0.32",
+ "pkg:pypi/redis@6.4.0",
+ "pkg:pypi/referencing@0.37.0",
+ "pkg:pypi/rpds-py@0.30.0",
+ "pkg:pypi/s3transfer@0.19.2",
+ "pkg:pypi/six@1.17.0",
+ "pkg:pypi/sniffio@1.3.1",
+ "pkg:pypi/sse-starlette@3.4.4",
+ "pkg:pypi/starlette@1.3.1",
+ "pkg:pypi/tqdm@4.67.3",
+ "pkg:pypi/typing-extensions@4.15.0",
+ "pkg:pypi/typing-inspection@0.4.2",
+ "pkg:pypi/urllib3@2.7.0",
+ "pkg:pypi/uvicorn@0.47.0"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/apt@3.0.3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/adduser@3.152?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ca-certificates@20250419?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/coreutils@9.7-3?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/dash@0.5.12-12?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/debianutils@5.23.2?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/diffutils@3.10-4?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/dpkg@1.22.22?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/grep@3.11-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/gzip@1.13-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/hostname@3.25?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libmount1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libblkid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all&distro=debian-13.6",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/mount@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/netbase@6.5?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/base-passwd@3.6.7?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64&distro=debian-13.6&epoch=1",
+ "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/login.defs@4.17.4-2?arch=all&distro=debian-13.6&epoch=1"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/readline-common@8.2-6?arch=all&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64&distro=debian-13.6&epoch=2",
+ "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64&distro=debian-13.6",
+ "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all&distro=debian-13.6",
+ "dependsOn": [
+ "pkg:deb/debian/debconf@1.5.91?arch=all&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:deb/debian/util-linux@2.41-5?arch=amd64&distro=debian-13.6",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64&distro=debian-13.6&epoch=1",
+ "dependsOn": [
+ "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64&distro=debian-13.6"
+ ]
+ },
+ {
+ "ref": "pkg:pypi/annotated-types@0.7.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/anthropic@0.104.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/anyio@4.13.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/attrs@26.1.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/boto3@1.43.56",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/botocore@1.43.56",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/certifi@2026.5.20",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/cffi@2.0.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/click@8.4.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/cryptography@49.0.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/distro@1.9.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/docstring-parser@0.18.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/h11@0.16.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpcore@1.0.9",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpx-sse@0.4.3",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/httpx@0.28.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/idna@3.16",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jiter@0.15.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jmespath@1.1.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/jsonschema@4.26.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/mcp@1.28.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/openai@2.38.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/openrath@1.3.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-api@1.42.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pip@25.0.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg-binary@3.3.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg-pool@3.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg@3.3.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pycparser@3.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic-core@2.46.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic-settings@2.14.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pydantic@2.13.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/pyjwt@2.13.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-dotenv@1.2.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/python-multipart@0.0.32",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/redis@6.4.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/referencing@0.37.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/rpds-py@0.30.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/s3transfer@0.19.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/six@1.17.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/sniffio@1.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/sse-starlette@3.4.4",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/starlette@1.3.1",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/tqdm@4.67.3",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/typing-extensions@4.15.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/typing-inspection@0.4.2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/urllib3@2.7.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:pypi/uvicorn@0.47.0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#5b1da461e2c57feebadb3f96f47736f4b17ad56a83895f95d60a166ced6472b0",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed",
+ "dependsOn": []
+ },
+ {
+ "ref": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72",
+ "dependsOn": []
+ }
+ ],
+ "vulnerabilities": []
+}
diff --git a/review/v2.0.0/soak.json b/review/v2.0.0/soak.json
new file mode 100644
index 0000000..96b6af3
--- /dev/null
+++ b/review/v2.0.0/soak.json
@@ -0,0 +1,19 @@
+{
+ "schema": "openrath.v2.soak/1",
+ "profile": "sqlite-single-worker-one-step",
+ "duration_seconds": 30.003353699999934,
+ "completed_runs": 1050,
+ "failed_runs": 0,
+ "throughput_runs_per_second": 34.996087787346326,
+ "resource_delta": {
+ "threads": 0,
+ "traced_memory_bytes": 312383,
+ "peak_traced_memory_bytes": 337934
+ },
+ "environment": {
+ "python": "3.10.18",
+ "platform": "Windows-10-10.0.26200-SP0",
+ "processor": "Intel64 Family 6 Model 183 Stepping 1, GenuineIntel"
+ },
+ "scope": "Review profile only; repeat for the approved 8h/24h duration on target hardware before production rollout."
+}
\ No newline at end of file
diff --git a/review/v2.0.0/vulnerability-report.json b/review/v2.0.0/vulnerability-report.json
new file mode 100644
index 0000000..eb7756e
--- /dev/null
+++ b/review/v2.0.0/vulnerability-report.json
@@ -0,0 +1,8360 @@
+{
+ "SchemaVersion": 2,
+ "CreatedAt": "2026-07-27T11:32:22.346970079Z",
+ "ArtifactName": "openrath:2.0.0-review",
+ "ArtifactType": "container_image",
+ "Metadata": {
+ "Size": 238930944,
+ "OS": {
+ "Family": "debian",
+ "Name": "13.6"
+ },
+ "ImageID": "sha256:92fa787d8b2be51b2248c13628765ad630f0820b757f74d46514ab94f332c7f6",
+ "DiffIDs": [
+ "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f",
+ "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167",
+ "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd",
+ "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f",
+ "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8",
+ "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1",
+ "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5",
+ "sha256:82d0cec9fb0c30115a70fe1863820ee9af9f2b16e211e6e5233beb4aa7c9386a"
+ ],
+ "RepoTags": [
+ "openrath:2.0.0-review"
+ ],
+ "ImageConfig": {
+ "architecture": "amd64",
+ "created": "2026-07-27T11:32:09.941712925Z",
+ "history": [
+ {
+ "created": "2026-07-13T00:00:00Z",
+ "created_by": "# debian.sh --arch 'amd64' out/ 'trixie' '@1783900800'",
+ "comment": "debuerreotype 0.17"
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV LANG=C.UTF-8",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "RUN /bin/sh -c set -eux; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tca-certificates \t\tnetbase \t\ttzdata \t; \tapt-get dist-clean # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV GPG_KEY=7169605F62C751356D054A26A821E680E5FA6305",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PYTHON_VERSION=3.12.13",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:02:10Z",
+ "created_by": "ENV PYTHON_SHA256=c08bc65a81971c1dd5783182826503369466c7e67374d1646519adf05207b684",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "RUN /bin/sh -c set -eux; \t\tsavedAptMark=\"$(apt-mark showmanual)\"; \tapt-get update; \tapt-get install -y --no-install-recommends \t\tdpkg-dev \t\tgcc \t\tgnupg \t\tlibbluetooth-dev \t\tlibbz2-dev \t\tlibc6-dev \t\tlibdb-dev \t\tlibffi-dev \t\tlibgdbm-dev \t\tliblzma-dev \t\tlibncursesw5-dev \t\tlibreadline-dev \t\tlibsqlite3-dev \t\tlibssl-dev \t\tmake \t\ttk-dev \t\tuuid-dev \t\twget \t\txz-utils \t\tzlib1g-dev \t; \t\twget -O python.tar.xz \"https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz\"; \techo \"$PYTHON_SHA256 *python.tar.xz\" | sha256sum -c -; \twget -O python.tar.xz.asc \"https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc\"; \tGNUPGHOME=\"$(mktemp -d)\"; export GNUPGHOME; \tgpg --batch --keyserver hkps://keys.openpgp.org --recv-keys \"$GPG_KEY\"; \tgpg --batch --verify python.tar.xz.asc python.tar.xz; \tgpgconf --kill all; \trm -rf \"$GNUPGHOME\" python.tar.xz.asc; \tmkdir -p /usr/src/python; \ttar --extract --directory /usr/src/python --strip-components=1 --file python.tar.xz; \trm python.tar.xz; \t\tcd /usr/src/python; \tgnuArch=\"$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)\"; \t./configure \t\t--build=\"$gnuArch\" \t\t--enable-loadable-sqlite-extensions \t\t--enable-optimizations \t\t--enable-option-checking=fatal \t\t--enable-shared \t\t$(test \"${gnuArch%%-*}\" != 'riscv64' \u0026\u0026 echo '--with-lto') \t\t--with-ensurepip \t; \tnproc=\"$(nproc)\"; \tEXTRA_CFLAGS=\"$(dpkg-buildflags --get CFLAGS)\"; \tLDFLAGS=\"$(dpkg-buildflags --get LDFLAGS)\"; \tLDFLAGS=\"${LDFLAGS:-} -Wl,--strip-all\"; \tarch=\"$(dpkg --print-architecture)\"; arch=\"${arch##*-}\"; \tcase \"$arch\" in \t\tamd64|arm64) \t\t\tEXTRA_CFLAGS=\"${EXTRA_CFLAGS:-} -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer\"; \t\t\t;; \t\ti386) \t\t\t;; \t\t*) \t\t\tEXTRA_CFLAGS=\"${EXTRA_CFLAGS:-} -fno-omit-frame-pointer\"; \t\t\t;; \tesac; \tmake -j \"$nproc\" \t\t\"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}\" \t\t\"LDFLAGS=${LDFLAGS:-}\" \t; \trm python; \tmake -j \"$nproc\" \t\t\"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}\" \t\t\"LDFLAGS=${LDFLAGS:-} -Wl,-rpath='\\$\\$ORIGIN/../lib'\" \t\tpython \t; \tmake install; \t\tcd /; \trm -rf /usr/src/python; \t\tfind /usr/local -depth \t\t\\( \t\t\t\\( -type d -a \\( -name test -o -name tests -o -name idle_test \\) \\) \t\t\t-o \\( -type f -a \\( -name '*.pyc' -o -name '*.pyo' -o -name 'libpython*.a' \\) \\) \t\t\\) -exec rm -rf '{}' + \t; \t\tldconfig; \t\tapt-mark auto '.*' \u003e /dev/null; \tapt-mark manual $savedAptMark; \tfind /usr/local -type f -executable -not \\( -name '*tkinter*' \\) -exec ldd '{}' ';' \t\t| awk '/=\u003e/ { so = $(NF-1); if (index(so, \"/usr/local/\") == 1) { next }; gsub(\"^/(usr/)?\", \"\", so); printf \"*%s\\n\", so }' \t\t| sort -u \t\t| xargs -rt dpkg-query --search \t\t| awk 'sub(\":$\", \"\", $1) { print $1 }' \t\t| sort -u \t\t| xargs -r apt-mark manual \t; \tapt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \tapt-get dist-clean; \t\texport PYTHONDONTWRITEBYTECODE=1; \tpython3 --version; \tpip3 --version # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "RUN /bin/sh -c set -eux; \tfor src in idle3 pip3 pydoc3 python3 python3-config; do \t\tdst=\"$(echo \"$src\" | tr -d 3)\"; \t\t[ -s \"/usr/local/bin/$src\" ]; \t\t[ ! -e \"/usr/local/bin/$dst\" ]; \t\tln -svT \"$src\" \"/usr/local/bin/$dst\"; \tdone # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-14T02:11:29Z",
+ "created_by": "CMD [\"python3\"]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "ENV PATH=/opt/venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PYTHONPATH=/app PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 OPENRATH_HOST=0.0.0.0 OPENRATH_PORT=8000",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "RUN /bin/sh -c groupadd --system --gid 10001 openrath \u0026\u0026 useradd --system --uid 10001 --gid openrath --home /app openrath # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-27T10:45:44Z",
+ "created_by": "WORKDIR /app",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-27T11:32:09Z",
+ "created_by": "COPY /opt/venv /opt/venv # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-27T11:32:09Z",
+ "created_by": "COPY examples ./examples # buildkit",
+ "comment": "buildkit.dockerfile.v0"
+ },
+ {
+ "created": "2026-07-27T11:32:09Z",
+ "created_by": "USER 10001:10001",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T11:32:09Z",
+ "created_by": "EXPOSE map[8000/tcp:{}]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ },
+ {
+ "created": "2026-07-27T11:32:09Z",
+ "created_by": "ENTRYPOINT [\"openrath-server\"]",
+ "comment": "buildkit.dockerfile.v0",
+ "empty_layer": true
+ }
+ ],
+ "os": "linux",
+ "rootfs": {
+ "type": "layers",
+ "diff_ids": [
+ "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f",
+ "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167",
+ "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd",
+ "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f",
+ "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8",
+ "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1",
+ "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5",
+ "sha256:82d0cec9fb0c30115a70fe1863820ee9af9f2b16e211e6e5233beb4aa7c9386a"
+ ]
+ },
+ "config": {
+ "Entrypoint": [
+ "openrath-server"
+ ],
+ "Env": [
+ "PATH=/opt/venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "LANG=C.UTF-8",
+ "GPG_KEY=7169605F62C751356D054A26A821E680E5FA6305",
+ "PYTHON_VERSION=3.12.13",
+ "PYTHON_SHA256=c08bc65a81971c1dd5783182826503369466c7e67374d1646519adf05207b684",
+ "PYTHONPATH=/app",
+ "PYTHONDONTWRITEBYTECODE=1",
+ "PYTHONUNBUFFERED=1",
+ "OPENRATH_HOST=0.0.0.0",
+ "OPENRATH_PORT=8000"
+ ],
+ "User": "10001:10001",
+ "WorkingDir": "/app",
+ "ExposedPorts": {
+ "8000/tcp": {}
+ }
+ }
+ },
+ "Layers": [
+ {
+ "Size": 81049600,
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ {
+ "Size": 4127232,
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ {
+ "Size": 38094848,
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ {
+ "Size": 5120,
+ "DiffID": "sha256:b80f3ed1ee6de85c788d9ae7203207c44724eab4baac8697390ca1412954ad2f"
+ },
+ {
+ "Size": 11264,
+ "DiffID": "sha256:705f755ad342993f1a9bbe9922cbab983321521117c79d796018013fab05e4d8"
+ },
+ {
+ "Size": 1536,
+ "DiffID": "sha256:b456d050d640df9ffbe456b81bbf11ed446fb23372063f6ce701e29fe74eb1a1"
+ },
+ {
+ "Size": 115636224,
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ {
+ "Size": 5120,
+ "DiffID": "sha256:82d0cec9fb0c30115a70fe1863820ee9af9f2b16e211e6e5233beb4aa7c9386a"
+ }
+ ]
+ },
+ "Results": [
+ {
+ "Target": "openrath:2.0.0-review (debian 13.6)",
+ "Class": "os-pkgs",
+ "Type": "debian",
+ "Packages": [
+ {
+ "ID": "adduser@3.152",
+ "Name": "adduser",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/adduser@3.152?arch=all\u0026distro=debian-13.6",
+ "UID": "a26e3466c18314ad"
+ },
+ "Version": "3.152",
+ "Arch": "all",
+ "SrcName": "adduser",
+ "SrcVersion": "3.152",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian Adduser Developers \u003cadduser@packages.debian.org\u003e",
+ "DependsOn": [
+ "passwd@1:4.17.4-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/adduser",
+ "/usr/sbin/deluser",
+ "/usr/share/doc/adduser/NEWS.Debian.gz",
+ "/usr/share/doc/adduser/README.gz",
+ "/usr/share/doc/adduser/TODO",
+ "/usr/share/doc/adduser/changelog.gz",
+ "/usr/share/doc/adduser/copyright",
+ "/usr/share/doc/adduser/examples/INSTALL",
+ "/usr/share/doc/adduser/examples/README",
+ "/usr/share/doc/adduser/examples/adduser.conf",
+ "/usr/share/doc/adduser/examples/adduser.local",
+ "/usr/share/doc/adduser/examples/adduser.local.conf",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/bash.bashrc",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/profile",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel.other/index.html",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bash_logout",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bash_profile",
+ "/usr/share/doc/adduser/examples/adduser.local.conf.examples/skel/dot.bashrc",
+ "/usr/share/doc/adduser/examples/deluser.conf",
+ "/usr/share/man/da/man5/deluser.conf.5.gz",
+ "/usr/share/man/de/man5/adduser.conf.5.gz",
+ "/usr/share/man/de/man5/deluser.conf.5.gz",
+ "/usr/share/man/de/man8/adduser.8.gz",
+ "/usr/share/man/de/man8/adduser.local.8.gz",
+ "/usr/share/man/de/man8/deluser.8.gz",
+ "/usr/share/man/es/man5/deluser.conf.5.gz",
+ "/usr/share/man/fr/man5/adduser.conf.5.gz",
+ "/usr/share/man/fr/man5/deluser.conf.5.gz",
+ "/usr/share/man/fr/man8/adduser.8.gz",
+ "/usr/share/man/fr/man8/deluser.8.gz",
+ "/usr/share/man/it/man5/deluser.conf.5.gz",
+ "/usr/share/man/man5/adduser.conf.5.gz",
+ "/usr/share/man/man5/deluser.conf.5.gz",
+ "/usr/share/man/man8/adduser.8.gz",
+ "/usr/share/man/man8/adduser.local.8.gz",
+ "/usr/share/man/man8/deluser.8.gz",
+ "/usr/share/man/nl/man5/adduser.conf.5.gz",
+ "/usr/share/man/nl/man5/deluser.conf.5.gz",
+ "/usr/share/man/nl/man8/adduser.8.gz",
+ "/usr/share/man/nl/man8/adduser.local.8.gz",
+ "/usr/share/man/nl/man8/deluser.8.gz",
+ "/usr/share/man/pl/man5/deluser.conf.5.gz",
+ "/usr/share/man/pt/man5/adduser.conf.5.gz",
+ "/usr/share/man/pt/man5/deluser.conf.5.gz",
+ "/usr/share/man/pt/man8/adduser.8.gz",
+ "/usr/share/man/pt/man8/adduser.local.8.gz",
+ "/usr/share/man/pt/man8/deluser.8.gz",
+ "/usr/share/man/ro/man5/adduser.conf.5.gz",
+ "/usr/share/man/ro/man5/deluser.conf.5.gz",
+ "/usr/share/man/ro/man8/adduser.8.gz",
+ "/usr/share/man/ro/man8/adduser.local.8.gz",
+ "/usr/share/man/ro/man8/deluser.8.gz",
+ "/usr/share/man/ru/man5/deluser.conf.5.gz",
+ "/usr/share/man/sv/man5/deluser.conf.5.gz",
+ "/usr/share/perl5/Debian/AdduserCommon.pm",
+ "/usr/share/perl5/Debian/AdduserLogging.pm",
+ "/usr/share/perl5/Debian/AdduserRetvalues.pm"
+ ]
+ },
+ {
+ "ID": "apt@3.0.3",
+ "Name": "apt",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/apt@3.0.3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3c1822d549195c1f"
+ },
+ "Version": "3.0.3",
+ "Arch": "amd64",
+ "SrcName": "apt",
+ "SrcVersion": "3.0.3",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "curl",
+ "BSD-3-Clause",
+ "MIT",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "APT Development Team \u003cdeity@lists.debian.org\u003e",
+ "DependsOn": [
+ "adduser@3.152",
+ "base-passwd@3.6.7",
+ "debian-archive-keyring@2025.1",
+ "libapt-pkg7.0@3.0.3",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "libseccomp2@2.6.0-2",
+ "libssl3t64@3.5.6-1~deb13u2",
+ "libstdc++6@14.2.0-19",
+ "libsystemd0@257.13-1~deb13u1",
+ "sqv@1.3.0-3+b2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/apt",
+ "/usr/bin/apt-cache",
+ "/usr/bin/apt-cdrom",
+ "/usr/bin/apt-config",
+ "/usr/bin/apt-get",
+ "/usr/bin/apt-mark",
+ "/usr/lib/apt/apt-extracttemplates",
+ "/usr/lib/apt/apt-helper",
+ "/usr/lib/apt/apt.systemd.daily",
+ "/usr/lib/apt/methods/cdrom",
+ "/usr/lib/apt/methods/copy",
+ "/usr/lib/apt/methods/file",
+ "/usr/lib/apt/methods/gpgv",
+ "/usr/lib/apt/methods/http",
+ "/usr/lib/apt/methods/mirror",
+ "/usr/lib/apt/methods/rred",
+ "/usr/lib/apt/methods/sqv",
+ "/usr/lib/apt/methods/store",
+ "/usr/lib/apt/solvers/dump",
+ "/usr/lib/dpkg/methods/apt/desc.apt",
+ "/usr/lib/dpkg/methods/apt/install",
+ "/usr/lib/dpkg/methods/apt/names",
+ "/usr/lib/dpkg/methods/apt/setup",
+ "/usr/lib/dpkg/methods/apt/update",
+ "/usr/lib/systemd/system/apt-daily-upgrade.service",
+ "/usr/lib/systemd/system/apt-daily-upgrade.timer",
+ "/usr/lib/systemd/system/apt-daily.service",
+ "/usr/lib/systemd/system/apt-daily.timer",
+ "/usr/lib/x86_64-linux-gnu/libapt-private.so.0.0.0",
+ "/usr/share/apt/default-sequoia.config",
+ "/usr/share/bash-completion/completions/apt",
+ "/usr/share/bug/apt/script",
+ "/usr/share/doc/apt/NEWS.Debian.gz",
+ "/usr/share/doc/apt/README.md.gz",
+ "/usr/share/doc/apt/changelog.gz",
+ "/usr/share/doc/apt/copyright",
+ "/usr/share/doc/apt/examples/apt.conf",
+ "/usr/share/doc/apt/examples/configure-index",
+ "/usr/share/doc/apt/examples/debian.sources",
+ "/usr/share/doc/apt/examples/preferences",
+ "/usr/share/lintian/overrides/apt",
+ "/usr/share/locale/ar/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/da/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/de/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/el/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/es/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/it/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/km/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/th/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/apt.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/apt.mo",
+ "/usr/share/man/de/man1/apt-transport-http.1.gz",
+ "/usr/share/man/de/man1/apt-transport-https.1.gz",
+ "/usr/share/man/de/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/de/man5/apt.conf.5.gz",
+ "/usr/share/man/de/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/de/man5/apt_preferences.5.gz",
+ "/usr/share/man/de/man5/sources.list.5.gz",
+ "/usr/share/man/de/man7/apt-patterns.7.gz",
+ "/usr/share/man/de/man8/apt-cache.8.gz",
+ "/usr/share/man/de/man8/apt-cdrom.8.gz",
+ "/usr/share/man/de/man8/apt-config.8.gz",
+ "/usr/share/man/de/man8/apt-get.8.gz",
+ "/usr/share/man/de/man8/apt-mark.8.gz",
+ "/usr/share/man/de/man8/apt-secure.8.gz",
+ "/usr/share/man/de/man8/apt.8.gz",
+ "/usr/share/man/es/man5/apt_preferences.5.gz",
+ "/usr/share/man/es/man8/apt-cache.8.gz",
+ "/usr/share/man/es/man8/apt-cdrom.8.gz",
+ "/usr/share/man/es/man8/apt-config.8.gz",
+ "/usr/share/man/fr/man1/apt-transport-http.1.gz",
+ "/usr/share/man/fr/man1/apt-transport-https.1.gz",
+ "/usr/share/man/fr/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/fr/man5/apt.conf.5.gz",
+ "/usr/share/man/fr/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/fr/man5/apt_preferences.5.gz",
+ "/usr/share/man/fr/man5/sources.list.5.gz",
+ "/usr/share/man/fr/man7/apt-patterns.7.gz",
+ "/usr/share/man/fr/man8/apt-cache.8.gz",
+ "/usr/share/man/fr/man8/apt-cdrom.8.gz",
+ "/usr/share/man/fr/man8/apt-config.8.gz",
+ "/usr/share/man/fr/man8/apt-get.8.gz",
+ "/usr/share/man/fr/man8/apt-mark.8.gz",
+ "/usr/share/man/fr/man8/apt-secure.8.gz",
+ "/usr/share/man/fr/man8/apt.8.gz",
+ "/usr/share/man/it/man5/apt.conf.5.gz",
+ "/usr/share/man/it/man5/apt_preferences.5.gz",
+ "/usr/share/man/it/man8/apt-cache.8.gz",
+ "/usr/share/man/it/man8/apt-cdrom.8.gz",
+ "/usr/share/man/it/man8/apt-config.8.gz",
+ "/usr/share/man/it/man8/apt-mark.8.gz",
+ "/usr/share/man/it/man8/apt.8.gz",
+ "/usr/share/man/ja/man5/apt.conf.5.gz",
+ "/usr/share/man/ja/man5/apt_preferences.5.gz",
+ "/usr/share/man/ja/man8/apt-cache.8.gz",
+ "/usr/share/man/ja/man8/apt-cdrom.8.gz",
+ "/usr/share/man/ja/man8/apt-config.8.gz",
+ "/usr/share/man/ja/man8/apt-mark.8.gz",
+ "/usr/share/man/ja/man8/apt.8.gz",
+ "/usr/share/man/man1/apt-transport-http.1.gz",
+ "/usr/share/man/man1/apt-transport-https.1.gz",
+ "/usr/share/man/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/man5/apt.conf.5.gz",
+ "/usr/share/man/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/man5/apt_preferences.5.gz",
+ "/usr/share/man/man5/sources.list.5.gz",
+ "/usr/share/man/man7/apt-patterns.7.gz",
+ "/usr/share/man/man8/apt-cache.8.gz",
+ "/usr/share/man/man8/apt-cdrom.8.gz",
+ "/usr/share/man/man8/apt-config.8.gz",
+ "/usr/share/man/man8/apt-get.8.gz",
+ "/usr/share/man/man8/apt-mark.8.gz",
+ "/usr/share/man/man8/apt-secure.8.gz",
+ "/usr/share/man/man8/apt.8.gz",
+ "/usr/share/man/nl/man1/apt-transport-http.1.gz",
+ "/usr/share/man/nl/man1/apt-transport-https.1.gz",
+ "/usr/share/man/nl/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/nl/man5/apt.conf.5.gz",
+ "/usr/share/man/nl/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/nl/man5/apt_preferences.5.gz",
+ "/usr/share/man/nl/man5/sources.list.5.gz",
+ "/usr/share/man/nl/man7/apt-patterns.7.gz",
+ "/usr/share/man/nl/man8/apt-cache.8.gz",
+ "/usr/share/man/nl/man8/apt-cdrom.8.gz",
+ "/usr/share/man/nl/man8/apt-config.8.gz",
+ "/usr/share/man/nl/man8/apt-get.8.gz",
+ "/usr/share/man/nl/man8/apt-mark.8.gz",
+ "/usr/share/man/nl/man8/apt-secure.8.gz",
+ "/usr/share/man/nl/man8/apt.8.gz",
+ "/usr/share/man/pl/man5/apt_preferences.5.gz",
+ "/usr/share/man/pl/man8/apt-cache.8.gz",
+ "/usr/share/man/pl/man8/apt-cdrom.8.gz",
+ "/usr/share/man/pl/man8/apt-config.8.gz",
+ "/usr/share/man/pt/man1/apt-transport-http.1.gz",
+ "/usr/share/man/pt/man1/apt-transport-https.1.gz",
+ "/usr/share/man/pt/man1/apt-transport-mirror.1.gz",
+ "/usr/share/man/pt/man5/apt.conf.5.gz",
+ "/usr/share/man/pt/man5/apt_auth.conf.5.gz",
+ "/usr/share/man/pt/man5/apt_preferences.5.gz",
+ "/usr/share/man/pt/man5/sources.list.5.gz",
+ "/usr/share/man/pt/man7/apt-patterns.7.gz",
+ "/usr/share/man/pt/man8/apt-cache.8.gz",
+ "/usr/share/man/pt/man8/apt-cdrom.8.gz",
+ "/usr/share/man/pt/man8/apt-config.8.gz",
+ "/usr/share/man/pt/man8/apt-get.8.gz",
+ "/usr/share/man/pt/man8/apt-mark.8.gz",
+ "/usr/share/man/pt/man8/apt-secure.8.gz",
+ "/usr/share/man/pt/man8/apt.8.gz"
+ ]
+ },
+ {
+ "ID": "base-files@13.8+deb13u6",
+ "Name": "base-files",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/base-files@13.8%2Bdeb13u6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "4bb4c2ef5a12c64b"
+ },
+ "Version": "13.8+deb13u6",
+ "Arch": "amd64",
+ "SrcName": "base-files",
+ "SrcVersion": "13.8+deb13u6",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "verbatim"
+ ],
+ "Maintainer": "Santiago Vila \u003csanvila@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/os-release",
+ "/usr/share/base-files/dot.bashrc",
+ "/usr/share/base-files/dot.profile",
+ "/usr/share/base-files/dot.profile.md5sums",
+ "/usr/share/base-files/info.dir",
+ "/usr/share/base-files/motd",
+ "/usr/share/base-files/profile",
+ "/usr/share/base-files/profile.md5sums",
+ "/usr/share/base-files/staff-group-for-usr-local",
+ "/usr/share/common-licenses/Apache-2.0",
+ "/usr/share/common-licenses/Artistic",
+ "/usr/share/common-licenses/BSD",
+ "/usr/share/common-licenses/CC0-1.0",
+ "/usr/share/common-licenses/GFDL-1.2",
+ "/usr/share/common-licenses/GFDL-1.3",
+ "/usr/share/common-licenses/GPL-1",
+ "/usr/share/common-licenses/GPL-2",
+ "/usr/share/common-licenses/GPL-3",
+ "/usr/share/common-licenses/LGPL-2",
+ "/usr/share/common-licenses/LGPL-2.1",
+ "/usr/share/common-licenses/LGPL-3",
+ "/usr/share/common-licenses/MPL-1.1",
+ "/usr/share/common-licenses/MPL-2.0",
+ "/usr/share/doc/base-files/NEWS.Debian.gz",
+ "/usr/share/doc/base-files/README",
+ "/usr/share/doc/base-files/README.FHS",
+ "/usr/share/doc/base-files/changelog.gz",
+ "/usr/share/doc/base-files/copyright",
+ "/usr/share/lintian/overrides/base-files"
+ ]
+ },
+ {
+ "ID": "base-passwd@3.6.7",
+ "Name": "base-passwd",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/base-passwd@3.6.7?arch=amd64\u0026distro=debian-13.6",
+ "UID": "bc0cc430715927e6"
+ },
+ "Version": "3.6.7",
+ "Arch": "amd64",
+ "SrcName": "base-passwd",
+ "SrcVersion": "3.6.7",
+ "Licenses": [
+ "GPL-2.0-only",
+ "public-domain"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libdebconfclient0@0.280",
+ "libselinux1@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/update-passwd",
+ "/usr/share/base-passwd/group.master",
+ "/usr/share/base-passwd/passwd.master",
+ "/usr/share/doc-base/base-passwd.users-and-groups",
+ "/usr/share/doc/base-passwd/README",
+ "/usr/share/doc/base-passwd/changelog.gz",
+ "/usr/share/doc/base-passwd/copyright",
+ "/usr/share/doc/base-passwd/users-and-groups.html",
+ "/usr/share/doc/base-passwd/users-and-groups.txt.gz",
+ "/usr/share/lintian/overrides/base-passwd",
+ "/usr/share/man/de/man8/update-passwd.8.gz",
+ "/usr/share/man/es/man8/update-passwd.8.gz",
+ "/usr/share/man/fr/man8/update-passwd.8.gz",
+ "/usr/share/man/ja/man8/update-passwd.8.gz",
+ "/usr/share/man/man8/update-passwd.8.gz",
+ "/usr/share/man/pl/man8/update-passwd.8.gz",
+ "/usr/share/man/ro/man8/update-passwd.8.gz",
+ "/usr/share/man/ru/man8/update-passwd.8.gz"
+ ]
+ },
+ {
+ "ID": "bash@5.2.37-2+b9",
+ "Name": "bash",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/bash@5.2.37-2%2Bb9?arch=amd64\u0026distro=debian-13.6",
+ "UID": "2c8d7060f3972831"
+ },
+ "Version": "5.2.37",
+ "Release": "2+b9",
+ "Arch": "amd64",
+ "SrcName": "bash",
+ "SrcVersion": "5.2.37",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-only",
+ "GFDL-1.3-only",
+ "Latex2e",
+ "BSD-4-Clause-UC",
+ "MIT",
+ "permissive"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "DependsOn": [
+ "base-files@13.8+deb13u6",
+ "debianutils@5.23.2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/bash",
+ "/usr/bin/bashbug",
+ "/usr/bin/clear_console",
+ "/usr/share/debianutils/shells.d/bash",
+ "/usr/share/doc/bash/CHANGES.gz",
+ "/usr/share/doc/bash/COMPAT.gz",
+ "/usr/share/doc/bash/INTRO.gz",
+ "/usr/share/doc/bash/NEWS.gz",
+ "/usr/share/doc/bash/POSIX.gz",
+ "/usr/share/doc/bash/RBASH",
+ "/usr/share/doc/bash/README.Debian.gz",
+ "/usr/share/doc/bash/README.abs-guide",
+ "/usr/share/doc/bash/README.commands.gz",
+ "/usr/share/doc/bash/README.gz",
+ "/usr/share/doc/bash/changelog.Debian.amd64.gz",
+ "/usr/share/doc/bash/changelog.Debian.gz",
+ "/usr/share/doc/bash/changelog.gz",
+ "/usr/share/doc/bash/copyright",
+ "/usr/share/doc/bash/inputrc.arrows",
+ "/usr/share/lintian/overrides/bash",
+ "/usr/share/locale/af/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/da/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/de/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/el/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/en@boldquot/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/en@quot/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/es/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/et/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/id/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/it/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/bash.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/bash.mo",
+ "/usr/share/man/man1/bash.1.gz",
+ "/usr/share/man/man1/bashbug.1.gz",
+ "/usr/share/man/man1/clear_console.1.gz",
+ "/usr/share/man/man1/rbash.1.gz",
+ "/usr/share/man/man7/bash-builtins.7.gz",
+ "/usr/share/menu/bash"
+ ]
+ },
+ {
+ "ID": "bsdutils@1:2.41-5",
+ "Name": "bsdutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/bsdutils@2.41-5?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "c9de60be80a96a27"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/logger",
+ "/usr/bin/renice",
+ "/usr/bin/script",
+ "/usr/bin/scriptlive",
+ "/usr/bin/scriptreplay",
+ "/usr/bin/wall",
+ "/usr/share/bash-completion/completions/logger",
+ "/usr/share/bash-completion/completions/renice",
+ "/usr/share/bash-completion/completions/script",
+ "/usr/share/bash-completion/completions/scriptlive",
+ "/usr/share/bash-completion/completions/scriptreplay",
+ "/usr/share/bash-completion/completions/wall",
+ "/usr/share/doc/bsdutils/NEWS.Debian.gz",
+ "/usr/share/doc/bsdutils/changelog.Debian.gz",
+ "/usr/share/doc/bsdutils/changelog.gz",
+ "/usr/share/doc/bsdutils/copyright",
+ "/usr/share/lintian/overrides/bsdutils",
+ "/usr/share/man/man1/logger.1.gz",
+ "/usr/share/man/man1/renice.1.gz",
+ "/usr/share/man/man1/script.1.gz",
+ "/usr/share/man/man1/scriptlive.1.gz",
+ "/usr/share/man/man1/scriptreplay.1.gz",
+ "/usr/share/man/man1/wall.1.gz"
+ ]
+ },
+ {
+ "ID": "ca-certificates@20250419",
+ "Name": "ca-certificates",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ca-certificates@20250419?arch=all\u0026distro=debian-13.6",
+ "UID": "6365e842529686ef"
+ },
+ "Version": "20250419",
+ "Arch": "all",
+ "SrcName": "ca-certificates",
+ "SrcVersion": "20250419",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "MPL-2.0"
+ ],
+ "Maintainer": "Julien Cristau \u003cjcristau@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "openssl@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/update-ca-certificates",
+ "/usr/share/ca-certificates/mozilla/ACCVRAIZ1.crt",
+ "/usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM.crt",
+ "/usr/share/ca-certificates/mozilla/AC_RAIZ_FNMT-RCM_SERVIDORES_SEGUROS.crt",
+ "/usr/share/ca-certificates/mozilla/ANF_Secure_Server_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Actalis_Authentication_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Commercial.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Networking.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Premium.crt",
+ "/usr/share/ca-certificates/mozilla/AffirmTrust_Premium_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/Amazon_Root_CA_4.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_2011.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_Root_CA_ECC_TLS_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Atos_TrustedRoot_Root_CA_RSA_TLS_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Autoridad_de_Certificacion_Firmaprofesional_CIF_A62634068.crt",
+ "/usr/share/ca-certificates/mozilla/BJCA_Global_Root_CA1.crt",
+ "/usr/share/ca-certificates/mozilla/BJCA_Global_Root_CA2.crt",
+ "/usr/share/ca-certificates/mozilla/Baltimore_CyberTrust_Root.crt",
+ "/usr/share/ca-certificates/mozilla/Buypass_Class_2_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Buypass_Class_3_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/CA_Disig_Root_R2.crt",
+ "/usr/share/ca-certificates/mozilla/CFCA_EV_ROOT.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_ECC_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/COMODO_RSA_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Certainly_Root_E1.crt",
+ "/usr/share/ca-certificates/mozilla/Certainly_Root_R1.crt",
+ "/usr/share/ca-certificates/mozilla/Certigna.crt",
+ "/usr/share/ca-certificates/mozilla/Certigna_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_EC-384_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Network_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/Certum_Trusted_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_ECC_Root-01.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_ECC_Root-02.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_RSA_Root-01.crt",
+ "/usr/share/ca-certificates/mozilla/CommScope_Public_Trust_RSA_Root-02.crt",
+ "/usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_BR_Root_CA_1_2020.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_BR_Root_CA_2_2023.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_EV_Root_CA_1_2020.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_EV_Root_CA_2_2023.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_2009.crt",
+ "/usr/share/ca-certificates/mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G2.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_G3.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G2.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Global_Root_G3.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_High_Assurance_EV_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_TLS_ECC_P384_Root_G5.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_TLS_RSA4096_Root_G5.crt",
+ "/usr/share/ca-certificates/mozilla/DigiCert_Trusted_Root_G4.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust.net_Premium_2048_Secure_Server_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_EC1.crt",
+ "/usr/share/ca-certificates/mozilla/Entrust_Root_Certification_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/FIRMAPROFESIONAL_CA_ROOT-A_WEB.crt",
+ "/usr/share/ca-certificates/mozilla/GDCA_TrustAUTH_R5_ROOT.crt",
+ "/usr/share/ca-certificates/mozilla/GLOBALTRUST_2020.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R1.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R2.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R3.crt",
+ "/usr/share/ca-certificates/mozilla/GTS_Root_R4.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R4.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_ECC_Root_CA_-_R5.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R3.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_CA_-_R6.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_E46.crt",
+ "/usr/share/ca-certificates/mozilla/GlobalSign_Root_R46.crt",
+ "/usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Go_Daddy_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/HARICA_TLS_ECC_Root_CA_2021.crt",
+ "/usr/share/ca-certificates/mozilla/HARICA_TLS_RSA_Root_CA_2021.crt",
+ "/usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_ECC_RootCA_2015.crt",
+ "/usr/share/ca-certificates/mozilla/Hellenic_Academic_and_Research_Institutions_RootCA_2015.crt",
+ "/usr/share/ca-certificates/mozilla/HiPKI_Root_CA_-_G1.crt",
+ "/usr/share/ca-certificates/mozilla/Hongkong_Post_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt",
+ "/usr/share/ca-certificates/mozilla/ISRG_Root_X2.crt",
+ "/usr/share/ca-certificates/mozilla/IdenTrust_Commercial_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/IdenTrust_Public_Sector_Root_CA_1.crt",
+ "/usr/share/ca-certificates/mozilla/Izenpe.com.crt",
+ "/usr/share/ca-certificates/mozilla/Microsec_e-Szigno_Root_CA_2009.crt",
+ "/usr/share/ca-certificates/mozilla/Microsoft_ECC_Root_Certificate_Authority_2017.crt",
+ "/usr/share/ca-certificates/mozilla/Microsoft_RSA_Root_Certificate_Authority_2017.crt",
+ "/usr/share/ca-certificates/mozilla/NAVER_Global_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/NetLock_Arany_=Class_Gold=_Főtanúsítvány.crt",
+ "/usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GB_CA.crt",
+ "/usr/share/ca-certificates/mozilla/OISTE_WISeKey_Global_Root_GC_CA.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_1_G3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_2_G3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3.crt",
+ "/usr/share/ca-certificates/mozilla/QuoVadis_Root_CA_3_G3.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_EV_Root_Certification_Authority_RSA_R2.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_ECC.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_Root_Certification_Authority_RSA.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_TLS_ECC_Root_CA_2022.crt",
+ "/usr/share/ca-certificates/mozilla/SSL.com_TLS_RSA_Root_CA_2022.crt",
+ "/usr/share/ca-certificates/mozilla/SZAFIR_ROOT_CA2.crt",
+ "/usr/share/ca-certificates/mozilla/Sectigo_Public_Server_Authentication_Root_E46.crt",
+ "/usr/share/ca-certificates/mozilla/Sectigo_Public_Server_Authentication_Root_R46.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA12.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA14.crt",
+ "/usr/share/ca-certificates/mozilla/SecureSign_Root_CA15.crt",
+ "/usr/share/ca-certificates/mozilla/SecureTrust_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Secure_Global_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Security_Communication_ECC_RootCA1.crt",
+ "/usr/share/ca-certificates/mozilla/Security_Communication_RootCA2.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Class_2_CA.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/Starfield_Services_Root_Certificate_Authority_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/SwissSign_Gold_CA_-_G2.crt",
+ "/usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_2.crt",
+ "/usr/share/ca-certificates/mozilla/T-TeleSec_GlobalRoot_Class_3.crt",
+ "/usr/share/ca-certificates/mozilla/TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi_-_Surum_1.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_CYBER_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_Global_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/TWCA_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Telekom_Security_TLS_ECC_Root_2020.crt",
+ "/usr/share/ca-certificates/mozilla/Telekom_Security_TLS_RSA_Root_2023.crt",
+ "/usr/share/ca-certificates/mozilla/TeliaSonera_Root_CA_v1.crt",
+ "/usr/share/ca-certificates/mozilla/Telia_Root_CA_v2.crt",
+ "/usr/share/ca-certificates/mozilla/TrustAsia_Global_Root_CA_G3.crt",
+ "/usr/share/ca-certificates/mozilla/TrustAsia_Global_Root_CA_G4.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_ECC_P256_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/Trustwave_Global_ECC_P384_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/TunTrust_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/UCA_Extended_Validation_Root.crt",
+ "/usr/share/ca-certificates/mozilla/UCA_Global_G2_Root.crt",
+ "/usr/share/ca-certificates/mozilla/USERTrust_ECC_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/USERTrust_RSA_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/XRamp_Global_CA_Root.crt",
+ "/usr/share/ca-certificates/mozilla/certSIGN_ROOT_CA.crt",
+ "/usr/share/ca-certificates/mozilla/certSIGN_Root_CA_G2.crt",
+ "/usr/share/ca-certificates/mozilla/e-Szigno_Root_CA_2017.crt",
+ "/usr/share/ca-certificates/mozilla/ePKI_Root_Certification_Authority.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_C3.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_Root_CA_-_C1.crt",
+ "/usr/share/ca-certificates/mozilla/emSign_Root_CA_-_G1.crt",
+ "/usr/share/ca-certificates/mozilla/vTrus_ECC_Root_CA.crt",
+ "/usr/share/ca-certificates/mozilla/vTrus_Root_CA.crt",
+ "/usr/share/doc/ca-certificates/README.Debian",
+ "/usr/share/doc/ca-certificates/changelog.gz",
+ "/usr/share/doc/ca-certificates/copyright",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/Makefile",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/README",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/ca-certificates-local.triggers",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/changelog",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/compat",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/control",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/copyright",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/postrm",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/rules",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/debian/source/format",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/local/Local_Root_CA.crt",
+ "/usr/share/doc/ca-certificates/examples/ca-certificates-local/local/Makefile",
+ "/usr/share/man/man8/update-ca-certificates.8.gz"
+ ]
+ },
+ {
+ "ID": "coreutils@9.7-3",
+ "Name": "coreutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/coreutils@9.7-3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a90cbdbcbab1768e"
+ },
+ "Version": "9.7",
+ "Release": "3",
+ "Arch": "amd64",
+ "SrcName": "coreutils",
+ "SrcVersion": "9.7",
+ "SrcRelease": "3",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "BSD-4-Clause-UC",
+ "GPL-3.0-only",
+ "ISC",
+ "FSFULLR",
+ "GFDL-1.3-no-invariants-only",
+ "GFDL-1.3-only"
+ ],
+ "Maintainer": "Michael Stone \u003cmstone@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/[",
+ "/usr/bin/arch",
+ "/usr/bin/b2sum",
+ "/usr/bin/base32",
+ "/usr/bin/base64",
+ "/usr/bin/basename",
+ "/usr/bin/basenc",
+ "/usr/bin/cat",
+ "/usr/bin/chcon",
+ "/usr/bin/chgrp",
+ "/usr/bin/chmod",
+ "/usr/bin/chown",
+ "/usr/bin/cksum",
+ "/usr/bin/comm",
+ "/usr/bin/cp",
+ "/usr/bin/csplit",
+ "/usr/bin/cut",
+ "/usr/bin/date",
+ "/usr/bin/dd",
+ "/usr/bin/df",
+ "/usr/bin/dir",
+ "/usr/bin/dircolors",
+ "/usr/bin/dirname",
+ "/usr/bin/du",
+ "/usr/bin/echo",
+ "/usr/bin/env",
+ "/usr/bin/expand",
+ "/usr/bin/expr",
+ "/usr/bin/factor",
+ "/usr/bin/false",
+ "/usr/bin/fmt",
+ "/usr/bin/fold",
+ "/usr/bin/groups",
+ "/usr/bin/head",
+ "/usr/bin/hostid",
+ "/usr/bin/id",
+ "/usr/bin/install",
+ "/usr/bin/join",
+ "/usr/bin/link",
+ "/usr/bin/ln",
+ "/usr/bin/logname",
+ "/usr/bin/ls",
+ "/usr/bin/md5sum",
+ "/usr/bin/mkdir",
+ "/usr/bin/mkfifo",
+ "/usr/bin/mknod",
+ "/usr/bin/mktemp",
+ "/usr/bin/mv",
+ "/usr/bin/nice",
+ "/usr/bin/nl",
+ "/usr/bin/nohup",
+ "/usr/bin/nproc",
+ "/usr/bin/numfmt",
+ "/usr/bin/od",
+ "/usr/bin/paste",
+ "/usr/bin/pathchk",
+ "/usr/bin/pinky",
+ "/usr/bin/pr",
+ "/usr/bin/printenv",
+ "/usr/bin/printf",
+ "/usr/bin/ptx",
+ "/usr/bin/pwd",
+ "/usr/bin/readlink",
+ "/usr/bin/realpath",
+ "/usr/bin/rm",
+ "/usr/bin/rmdir",
+ "/usr/bin/runcon",
+ "/usr/bin/seq",
+ "/usr/bin/sha1sum",
+ "/usr/bin/sha224sum",
+ "/usr/bin/sha256sum",
+ "/usr/bin/sha384sum",
+ "/usr/bin/sha512sum",
+ "/usr/bin/shred",
+ "/usr/bin/shuf",
+ "/usr/bin/sleep",
+ "/usr/bin/sort",
+ "/usr/bin/split",
+ "/usr/bin/stat",
+ "/usr/bin/stdbuf",
+ "/usr/bin/stty",
+ "/usr/bin/sum",
+ "/usr/bin/sync",
+ "/usr/bin/tac",
+ "/usr/bin/tail",
+ "/usr/bin/tee",
+ "/usr/bin/test",
+ "/usr/bin/timeout",
+ "/usr/bin/touch",
+ "/usr/bin/tr",
+ "/usr/bin/true",
+ "/usr/bin/truncate",
+ "/usr/bin/tsort",
+ "/usr/bin/tty",
+ "/usr/bin/uname",
+ "/usr/bin/unexpand",
+ "/usr/bin/uniq",
+ "/usr/bin/unlink",
+ "/usr/bin/users",
+ "/usr/bin/vdir",
+ "/usr/bin/wc",
+ "/usr/bin/who",
+ "/usr/bin/whoami",
+ "/usr/bin/yes",
+ "/usr/libexec/coreutils/libstdbuf.so",
+ "/usr/sbin/chroot",
+ "/usr/share/doc/coreutils/AUTHORS",
+ "/usr/share/doc/coreutils/NEWS.gz",
+ "/usr/share/doc/coreutils/README.Debian",
+ "/usr/share/doc/coreutils/README.gz",
+ "/usr/share/doc/coreutils/THANKS.gz",
+ "/usr/share/doc/coreutils/TODO.gz",
+ "/usr/share/doc/coreutils/changelog.Debian.gz",
+ "/usr/share/doc/coreutils/changelog.gz",
+ "/usr/share/doc/coreutils/copyright",
+ "/usr/share/info/coreutils.info.gz",
+ "/usr/share/lintian/overrides/coreutils",
+ "/usr/share/locale/af/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/be/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/et/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ia/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/lg/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/coreutils.mo",
+ "/usr/share/man/man1/arch.1.gz",
+ "/usr/share/man/man1/b2sum.1.gz",
+ "/usr/share/man/man1/base32.1.gz",
+ "/usr/share/man/man1/base64.1.gz",
+ "/usr/share/man/man1/basename.1.gz",
+ "/usr/share/man/man1/basenc.1.gz",
+ "/usr/share/man/man1/cat.1.gz",
+ "/usr/share/man/man1/chcon.1.gz",
+ "/usr/share/man/man1/chgrp.1.gz",
+ "/usr/share/man/man1/chmod.1.gz",
+ "/usr/share/man/man1/chown.1.gz",
+ "/usr/share/man/man1/cksum.1.gz",
+ "/usr/share/man/man1/comm.1.gz",
+ "/usr/share/man/man1/cp.1.gz",
+ "/usr/share/man/man1/csplit.1.gz",
+ "/usr/share/man/man1/cut.1.gz",
+ "/usr/share/man/man1/date.1.gz",
+ "/usr/share/man/man1/dd.1.gz",
+ "/usr/share/man/man1/df.1.gz",
+ "/usr/share/man/man1/dir.1.gz",
+ "/usr/share/man/man1/dircolors.1.gz",
+ "/usr/share/man/man1/dirname.1.gz",
+ "/usr/share/man/man1/du.1.gz",
+ "/usr/share/man/man1/echo.1.gz",
+ "/usr/share/man/man1/env.1.gz",
+ "/usr/share/man/man1/expand.1.gz",
+ "/usr/share/man/man1/expr.1.gz",
+ "/usr/share/man/man1/factor.1.gz",
+ "/usr/share/man/man1/false.1.gz",
+ "/usr/share/man/man1/fmt.1.gz",
+ "/usr/share/man/man1/fold.1.gz",
+ "/usr/share/man/man1/groups.1.gz",
+ "/usr/share/man/man1/head.1.gz",
+ "/usr/share/man/man1/hostid.1.gz",
+ "/usr/share/man/man1/id.1.gz",
+ "/usr/share/man/man1/install.1.gz",
+ "/usr/share/man/man1/join.1.gz",
+ "/usr/share/man/man1/link.1.gz",
+ "/usr/share/man/man1/ln.1.gz",
+ "/usr/share/man/man1/logname.1.gz",
+ "/usr/share/man/man1/ls.1.gz",
+ "/usr/share/man/man1/md5sum.1.gz",
+ "/usr/share/man/man1/mkdir.1.gz",
+ "/usr/share/man/man1/mkfifo.1.gz",
+ "/usr/share/man/man1/mknod.1.gz",
+ "/usr/share/man/man1/mktemp.1.gz",
+ "/usr/share/man/man1/mv.1.gz",
+ "/usr/share/man/man1/nice.1.gz",
+ "/usr/share/man/man1/nl.1.gz",
+ "/usr/share/man/man1/nohup.1.gz",
+ "/usr/share/man/man1/nproc.1.gz",
+ "/usr/share/man/man1/numfmt.1.gz",
+ "/usr/share/man/man1/od.1.gz",
+ "/usr/share/man/man1/paste.1.gz",
+ "/usr/share/man/man1/pathchk.1.gz",
+ "/usr/share/man/man1/pinky.1.gz",
+ "/usr/share/man/man1/pr.1.gz",
+ "/usr/share/man/man1/printenv.1.gz",
+ "/usr/share/man/man1/printf.1.gz",
+ "/usr/share/man/man1/ptx.1.gz",
+ "/usr/share/man/man1/pwd.1.gz",
+ "/usr/share/man/man1/readlink.1.gz",
+ "/usr/share/man/man1/realpath.1.gz",
+ "/usr/share/man/man1/rm.1.gz",
+ "/usr/share/man/man1/rmdir.1.gz",
+ "/usr/share/man/man1/runcon.1.gz",
+ "/usr/share/man/man1/seq.1.gz",
+ "/usr/share/man/man1/sha1sum.1.gz",
+ "/usr/share/man/man1/sha224sum.1.gz",
+ "/usr/share/man/man1/sha256sum.1.gz",
+ "/usr/share/man/man1/sha384sum.1.gz",
+ "/usr/share/man/man1/sha512sum.1.gz",
+ "/usr/share/man/man1/shred.1.gz",
+ "/usr/share/man/man1/shuf.1.gz",
+ "/usr/share/man/man1/sleep.1.gz",
+ "/usr/share/man/man1/sort.1.gz",
+ "/usr/share/man/man1/split.1.gz",
+ "/usr/share/man/man1/stat.1.gz",
+ "/usr/share/man/man1/stdbuf.1.gz",
+ "/usr/share/man/man1/stty.1.gz",
+ "/usr/share/man/man1/sum.1.gz",
+ "/usr/share/man/man1/sync.1.gz",
+ "/usr/share/man/man1/tac.1.gz",
+ "/usr/share/man/man1/tail.1.gz",
+ "/usr/share/man/man1/tee.1.gz",
+ "/usr/share/man/man1/test.1.gz",
+ "/usr/share/man/man1/timeout.1.gz",
+ "/usr/share/man/man1/touch.1.gz",
+ "/usr/share/man/man1/tr.1.gz",
+ "/usr/share/man/man1/true.1.gz",
+ "/usr/share/man/man1/truncate.1.gz",
+ "/usr/share/man/man1/tsort.1.gz",
+ "/usr/share/man/man1/tty.1.gz",
+ "/usr/share/man/man1/uname.1.gz",
+ "/usr/share/man/man1/unexpand.1.gz",
+ "/usr/share/man/man1/uniq.1.gz",
+ "/usr/share/man/man1/unlink.1.gz",
+ "/usr/share/man/man1/users.1.gz",
+ "/usr/share/man/man1/vdir.1.gz",
+ "/usr/share/man/man1/wc.1.gz",
+ "/usr/share/man/man1/who.1.gz",
+ "/usr/share/man/man1/whoami.1.gz",
+ "/usr/share/man/man1/yes.1.gz",
+ "/usr/share/man/man8/chroot.8.gz"
+ ]
+ },
+ {
+ "ID": "cyrus-sasl-lib@2.1.26-24.el7_9",
+ "Name": "cyrus-sasl-lib",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9",
+ "UID": "b814395bf7062155",
+ "BOMRef": "pkg:rpm/centos/cyrus-sasl-lib@2.1.26-24.el7_9#31c73dc5f009ba5a48504f874a39167409302b93174b17cecb1e4e2033f1b9b2"
+ },
+ "Version": "2.1.26",
+ "Release": "24.el7_9",
+ "SrcName": "cyrus-sasl-lib",
+ "SrcVersion": "2.1.26",
+ "SrcRelease": "24.el7_9",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "dash@0.5.12-12",
+ "Name": "dash",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/dash@0.5.12-12?arch=amd64\u0026distro=debian-13.6",
+ "UID": "89c835b0985cdc5c"
+ },
+ "Version": "0.5.12",
+ "Release": "12",
+ "Arch": "amd64",
+ "SrcName": "dash",
+ "SrcVersion": "0.5.12",
+ "SrcRelease": "12",
+ "Licenses": [
+ "BSD-3-Clause",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Andrej Shadura \u003candrewsh@debian.org\u003e",
+ "DependsOn": [
+ "debianutils@5.23.2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/dash",
+ "/usr/share/debianutils/shells.d/dash",
+ "/usr/share/doc/dash/README.Debian.diet",
+ "/usr/share/doc/dash/README.source",
+ "/usr/share/doc/dash/changelog.Debian.gz",
+ "/usr/share/doc/dash/changelog.gz",
+ "/usr/share/doc/dash/copyright",
+ "/usr/share/lintian/overrides/dash",
+ "/usr/share/man/man1/dash.1.gz",
+ "/usr/share/menu/dash"
+ ]
+ },
+ {
+ "ID": "debconf@1.5.91",
+ "Name": "debconf",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debconf@1.5.91?arch=all\u0026distro=debian-13.6",
+ "UID": "dbd74d1c32616a65"
+ },
+ "Version": "1.5.91",
+ "Arch": "all",
+ "SrcName": "debconf",
+ "SrcVersion": "1.5.91",
+ "Licenses": [
+ "BSD-2-Clause"
+ ],
+ "Maintainer": "Debconf Developers \u003cdebconf-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/debconf",
+ "/usr/bin/debconf-apt-progress",
+ "/usr/bin/debconf-communicate",
+ "/usr/bin/debconf-copydb",
+ "/usr/bin/debconf-escape",
+ "/usr/bin/debconf-set-selections",
+ "/usr/bin/debconf-show",
+ "/usr/sbin/dpkg-preconfigure",
+ "/usr/sbin/dpkg-reconfigure",
+ "/usr/share/bash-completion/completions/debconf",
+ "/usr/share/debconf/confmodule",
+ "/usr/share/debconf/confmodule.sh",
+ "/usr/share/debconf/debconf.conf",
+ "/usr/share/debconf/fix_db.pl",
+ "/usr/share/debconf/frontend",
+ "/usr/share/doc/debconf/README.Debian",
+ "/usr/share/doc/debconf/changelog.gz",
+ "/usr/share/doc/debconf/copyright",
+ "/usr/share/lintian/overrides/debconf",
+ "/usr/share/man/man1/debconf-apt-progress.1.gz",
+ "/usr/share/man/man1/debconf-communicate.1.gz",
+ "/usr/share/man/man1/debconf-copydb.1.gz",
+ "/usr/share/man/man1/debconf-escape.1.gz",
+ "/usr/share/man/man1/debconf-set-selections.1.gz",
+ "/usr/share/man/man1/debconf-show.1.gz",
+ "/usr/share/man/man1/debconf.1.gz",
+ "/usr/share/man/man8/dpkg-preconfigure.8.gz",
+ "/usr/share/man/man8/dpkg-reconfigure.8.gz",
+ "/usr/share/perl5/Debconf/AutoSelect.pm",
+ "/usr/share/perl5/Debconf/Base.pm",
+ "/usr/share/perl5/Debconf/Client/ConfModule.pm",
+ "/usr/share/perl5/Debconf/ConfModule.pm",
+ "/usr/share/perl5/Debconf/Config.pm",
+ "/usr/share/perl5/Debconf/Db.pm",
+ "/usr/share/perl5/Debconf/DbDriver.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Backup.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Cache.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Copy.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Debug.pm",
+ "/usr/share/perl5/Debconf/DbDriver/DirTree.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Directory.pm",
+ "/usr/share/perl5/Debconf/DbDriver/File.pm",
+ "/usr/share/perl5/Debconf/DbDriver/LDAP.pm",
+ "/usr/share/perl5/Debconf/DbDriver/PackageDir.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Pipe.pm",
+ "/usr/share/perl5/Debconf/DbDriver/Stack.pm",
+ "/usr/share/perl5/Debconf/Element.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/String.pm",
+ "/usr/share/perl5/Debconf/Element/Dialog/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/String.pm",
+ "/usr/share/perl5/Debconf/Element/Editor/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/String.pm",
+ "/usr/share/perl5/Debconf/Element/Gnome/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/String.pm",
+ "/usr/share/perl5/Debconf/Element/Noninteractive/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/String.pm",
+ "/usr/share/perl5/Debconf/Element/Teletype/Text.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Boolean.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Error.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Multiselect.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Note.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Password.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Progress.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Select.pm",
+ "/usr/share/perl5/Debconf/Element/Web/String.pm",
+ "/usr/share/perl5/Debconf/Element/Web/Text.pm",
+ "/usr/share/perl5/Debconf/Encoding.pm",
+ "/usr/share/perl5/Debconf/Format.pm",
+ "/usr/share/perl5/Debconf/Format/822.pm",
+ "/usr/share/perl5/Debconf/FrontEnd.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Dialog.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Editor.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Gnome.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Kde.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Noninteractive.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Passthrough.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Readline.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/ScreenSize.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Teletype.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Text.pm",
+ "/usr/share/perl5/Debconf/FrontEnd/Web.pm",
+ "/usr/share/perl5/Debconf/Gettext.pm",
+ "/usr/share/perl5/Debconf/Iterator.pm",
+ "/usr/share/perl5/Debconf/Log.pm",
+ "/usr/share/perl5/Debconf/Path.pm",
+ "/usr/share/perl5/Debconf/Priority.pm",
+ "/usr/share/perl5/Debconf/Question.pm",
+ "/usr/share/perl5/Debconf/Template.pm",
+ "/usr/share/perl5/Debconf/Template/Transient.pm",
+ "/usr/share/perl5/Debconf/TmpFile.pm",
+ "/usr/share/perl5/Debian/DebConf/Client/ConfModule.pm",
+ "/usr/share/pixmaps/debian-logo.png"
+ ]
+ },
+ {
+ "ID": "debian-archive-keyring@2025.1",
+ "Name": "debian-archive-keyring",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debian-archive-keyring@2025.1?arch=all\u0026distro=debian-13.6",
+ "UID": "3d23f3bc34b84a13"
+ },
+ "Version": "2025.1",
+ "Arch": "all",
+ "SrcName": "debian-archive-keyring",
+ "SrcVersion": "2025.1",
+ "Licenses": [
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian Release Team \u003cpackages@release.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/debian-archive-keyring/NEWS.Debian.gz",
+ "/usr/share/doc/debian-archive-keyring/README",
+ "/usr/share/doc/debian-archive-keyring/changelog.gz",
+ "/usr/share/doc/debian-archive-keyring/copyright",
+ "/usr/share/keyrings/debian-archive-bookworm-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bookworm-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bookworm-stable.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-bullseye-stable.pgp",
+ "/usr/share/keyrings/debian-archive-keyring.pgp",
+ "/usr/share/keyrings/debian-archive-removed-keys.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-security-automatic.pgp",
+ "/usr/share/keyrings/debian-archive-trixie-stable.pgp"
+ ]
+ },
+ {
+ "ID": "debianutils@5.23.2",
+ "Name": "debianutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/debianutils@5.23.2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1faaee83f4beb2af"
+ },
+ "Version": "5.23.2",
+ "Arch": "amd64",
+ "SrcName": "debianutils",
+ "SrcVersion": "5.23.2",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "public-domain",
+ "SMAIL-GPL"
+ ],
+ "Maintainer": "Ileana Dumitrescu \u003cileanadumitrescu95@gmail.com\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/ischroot",
+ "/usr/bin/run-parts",
+ "/usr/bin/savelog",
+ "/usr/bin/tempfile",
+ "/usr/bin/which.debianutils",
+ "/usr/sbin/add-shell",
+ "/usr/sbin/installkernel",
+ "/usr/sbin/remove-shell",
+ "/usr/sbin/update-shells",
+ "/usr/share/debianutils/shells",
+ "/usr/share/doc/debianutils/README.shells",
+ "/usr/share/doc/debianutils/changelog.gz",
+ "/usr/share/doc/debianutils/copyright",
+ "/usr/share/man/de/man1/which.debianutils.1.gz",
+ "/usr/share/man/de/man8/add-shell.8.gz",
+ "/usr/share/man/de/man8/installkernel.8.gz",
+ "/usr/share/man/de/man8/remove-shell.8.gz",
+ "/usr/share/man/de/man8/run-parts.8.gz",
+ "/usr/share/man/de/man8/savelog.8.gz",
+ "/usr/share/man/es/man1/which.debianutils.1.gz",
+ "/usr/share/man/es/man8/add-shell.8.gz",
+ "/usr/share/man/es/man8/installkernel.8.gz",
+ "/usr/share/man/es/man8/remove-shell.8.gz",
+ "/usr/share/man/es/man8/run-parts.8.gz",
+ "/usr/share/man/es/man8/savelog.8.gz",
+ "/usr/share/man/fr/man1/which.debianutils.1.gz",
+ "/usr/share/man/fr/man8/add-shell.8.gz",
+ "/usr/share/man/fr/man8/installkernel.8.gz",
+ "/usr/share/man/fr/man8/remove-shell.8.gz",
+ "/usr/share/man/fr/man8/run-parts.8.gz",
+ "/usr/share/man/fr/man8/savelog.8.gz",
+ "/usr/share/man/it/man1/which.debianutils.1.gz",
+ "/usr/share/man/it/man8/add-shell.8.gz",
+ "/usr/share/man/it/man8/installkernel.8.gz",
+ "/usr/share/man/it/man8/remove-shell.8.gz",
+ "/usr/share/man/it/man8/run-parts.8.gz",
+ "/usr/share/man/it/man8/savelog.8.gz",
+ "/usr/share/man/ja/man1/which.debianutils.1.gz",
+ "/usr/share/man/ja/man8/add-shell.8.gz",
+ "/usr/share/man/ja/man8/installkernel.8.gz",
+ "/usr/share/man/ja/man8/remove-shell.8.gz",
+ "/usr/share/man/ja/man8/run-parts.8.gz",
+ "/usr/share/man/ja/man8/savelog.8.gz",
+ "/usr/share/man/man1/ischroot.1.gz",
+ "/usr/share/man/man1/tempfile.1.gz",
+ "/usr/share/man/man1/which.debianutils.1.gz",
+ "/usr/share/man/man8/add-shell.8.gz",
+ "/usr/share/man/man8/installkernel.8.gz",
+ "/usr/share/man/man8/remove-shell.8.gz",
+ "/usr/share/man/man8/run-parts.8.gz",
+ "/usr/share/man/man8/savelog.8.gz",
+ "/usr/share/man/man8/update-shells.8.gz",
+ "/usr/share/man/pl/man1/which.debianutils.1.gz",
+ "/usr/share/man/pl/man8/add-shell.8.gz",
+ "/usr/share/man/pl/man8/installkernel.8.gz",
+ "/usr/share/man/pl/man8/remove-shell.8.gz",
+ "/usr/share/man/pl/man8/run-parts.8.gz",
+ "/usr/share/man/pl/man8/savelog.8.gz",
+ "/usr/share/man/pt/man1/which.debianutils.1.gz",
+ "/usr/share/man/pt/man8/add-shell.8.gz",
+ "/usr/share/man/pt/man8/installkernel.8.gz",
+ "/usr/share/man/pt/man8/remove-shell.8.gz",
+ "/usr/share/man/pt/man8/run-parts.8.gz",
+ "/usr/share/man/pt/man8/savelog.8.gz",
+ "/usr/share/man/sl/man1/which.debianutils.1.gz",
+ "/usr/share/man/sl/man8/add-shell.8.gz",
+ "/usr/share/man/sl/man8/installkernel.8.gz",
+ "/usr/share/man/sl/man8/remove-shell.8.gz",
+ "/usr/share/man/sl/man8/run-parts.8.gz",
+ "/usr/share/man/sl/man8/savelog.8.gz"
+ ]
+ },
+ {
+ "ID": "diffutils@1:3.10-4",
+ "Name": "diffutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/diffutils@3.10-4?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "6ae1b70a720e3ebb"
+ },
+ "Version": "3.10",
+ "Release": "4",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "diffutils",
+ "SrcVersion": "3.10",
+ "SrcRelease": "4",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "FSFULLR",
+ "LGPL-2.1-or-later",
+ "GPL-3.0-with-autoconf-exception+",
+ "GPL-3.0-only",
+ "GPL-3+ with texinfo exception",
+ "LGPL-2.0-or-later",
+ "GPL-2.0-or-later",
+ "X11",
+ "FSFAP",
+ "GFDL-1.3-no-invariants-only",
+ "LGPL-3.0-or-later",
+ "LGPL-3.0-only",
+ "public-domain",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-2.0-only",
+ "GFDL-1.3-only"
+ ],
+ "Maintainer": "Santiago Vila \u003csanvila@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/cmp",
+ "/usr/bin/diff",
+ "/usr/bin/diff3",
+ "/usr/bin/sdiff",
+ "/usr/share/doc/diffutils/NEWS.gz",
+ "/usr/share/doc/diffutils/changelog.Debian.gz",
+ "/usr/share/doc/diffutils/changelog.gz",
+ "/usr/share/doc/diffutils/copyright",
+ "/usr/share/info/diffutils.info.gz",
+ "/usr/share/locale/bg/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/he/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/lv/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/diffutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/diffutils.mo",
+ "/usr/share/man/man1/cmp.1.gz",
+ "/usr/share/man/man1/diff.1.gz",
+ "/usr/share/man/man1/diff3.1.gz",
+ "/usr/share/man/man1/sdiff.1.gz"
+ ]
+ },
+ {
+ "ID": "dpkg@1.22.22",
+ "Name": "dpkg",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/dpkg@1.22.22?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d88bc872d04d38e8"
+ },
+ "Version": "1.22.22",
+ "Arch": "amd64",
+ "SrcName": "dpkg",
+ "SrcVersion": "1.22.22",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "public-domain-s-s-d",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Dpkg Developers \u003cdebian-dpkg@lists.debian.org\u003e",
+ "DependsOn": [
+ "tar@1.35+dfsg-3.1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/dpkg",
+ "/usr/bin/dpkg-deb",
+ "/usr/bin/dpkg-divert",
+ "/usr/bin/dpkg-maintscript-helper",
+ "/usr/bin/dpkg-query",
+ "/usr/bin/dpkg-realpath",
+ "/usr/bin/dpkg-split",
+ "/usr/bin/dpkg-statoverride",
+ "/usr/bin/dpkg-trigger",
+ "/usr/bin/update-alternatives",
+ "/usr/lib/systemd/system/dpkg-db-backup.service",
+ "/usr/lib/systemd/system/dpkg-db-backup.timer",
+ "/usr/libexec/dpkg/dpkg-db-backup",
+ "/usr/libexec/dpkg/dpkg-db-keeper",
+ "/usr/sbin/start-stop-daemon",
+ "/usr/share/doc/dpkg/AUTHORS",
+ "/usr/share/doc/dpkg/README.api",
+ "/usr/share/doc/dpkg/README.bug-usertags.gz",
+ "/usr/share/doc/dpkg/README.feature-removal-schedule.gz",
+ "/usr/share/doc/dpkg/THANKS.gz",
+ "/usr/share/doc/dpkg/changelog.gz",
+ "/usr/share/doc/dpkg/copyright",
+ "/usr/share/dpkg/abitable",
+ "/usr/share/dpkg/cputable",
+ "/usr/share/dpkg/ostable",
+ "/usr/share/dpkg/sh/dpkg-error.sh",
+ "/usr/share/dpkg/tupletable",
+ "/usr/share/lintian/overrides/dpkg",
+ "/usr/share/lintian/profiles/dpkg/main.profile",
+ "/usr/share/locale/ast/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/da/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/de/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/el/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/es/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/et/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/id/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/it/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/km/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/oc/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/th/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/dpkg.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/dpkg.mo",
+ "/usr/share/man/de/man1/dpkg-deb.1.gz",
+ "/usr/share/man/de/man1/dpkg-divert.1.gz",
+ "/usr/share/man/de/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/de/man1/dpkg-query.1.gz",
+ "/usr/share/man/de/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/de/man1/dpkg-split.1.gz",
+ "/usr/share/man/de/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/de/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/de/man1/dpkg.1.gz",
+ "/usr/share/man/de/man1/update-alternatives.1.gz",
+ "/usr/share/man/de/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/de/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/es/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/fr/man1/dpkg-divert.1.gz",
+ "/usr/share/man/fr/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/fr/man1/dpkg-query.1.gz",
+ "/usr/share/man/fr/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/fr/man1/dpkg-split.1.gz",
+ "/usr/share/man/fr/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/fr/man1/update-alternatives.1.gz",
+ "/usr/share/man/fr/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/fr/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/it/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/ja/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/man1/dpkg-deb.1.gz",
+ "/usr/share/man/man1/dpkg-divert.1.gz",
+ "/usr/share/man/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/man1/dpkg-query.1.gz",
+ "/usr/share/man/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/man1/dpkg-split.1.gz",
+ "/usr/share/man/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/man1/dpkg.1.gz",
+ "/usr/share/man/man1/update-alternatives.1.gz",
+ "/usr/share/man/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/nl/man1/dpkg-deb.1.gz",
+ "/usr/share/man/nl/man1/dpkg-divert.1.gz",
+ "/usr/share/man/nl/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/nl/man1/dpkg-query.1.gz",
+ "/usr/share/man/nl/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/nl/man1/dpkg-split.1.gz",
+ "/usr/share/man/nl/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/nl/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/nl/man1/dpkg.1.gz",
+ "/usr/share/man/nl/man1/update-alternatives.1.gz",
+ "/usr/share/man/nl/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/nl/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/pl/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/pt/man1/dpkg-deb.1.gz",
+ "/usr/share/man/pt/man1/dpkg-divert.1.gz",
+ "/usr/share/man/pt/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/pt/man1/dpkg-query.1.gz",
+ "/usr/share/man/pt/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/pt/man1/dpkg-split.1.gz",
+ "/usr/share/man/pt/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/pt/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/pt/man1/dpkg.1.gz",
+ "/usr/share/man/pt/man1/update-alternatives.1.gz",
+ "/usr/share/man/pt/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/pt/man8/start-stop-daemon.8.gz",
+ "/usr/share/man/sv/man1/dpkg-deb.1.gz",
+ "/usr/share/man/sv/man1/dpkg-divert.1.gz",
+ "/usr/share/man/sv/man1/dpkg-maintscript-helper.1.gz",
+ "/usr/share/man/sv/man1/dpkg-query.1.gz",
+ "/usr/share/man/sv/man1/dpkg-realpath.1.gz",
+ "/usr/share/man/sv/man1/dpkg-split.1.gz",
+ "/usr/share/man/sv/man1/dpkg-statoverride.1.gz",
+ "/usr/share/man/sv/man1/dpkg-trigger.1.gz",
+ "/usr/share/man/sv/man1/dpkg.1.gz",
+ "/usr/share/man/sv/man1/update-alternatives.1.gz",
+ "/usr/share/man/sv/man5/dpkg.cfg.5.gz",
+ "/usr/share/man/sv/man8/start-stop-daemon.8.gz",
+ "/usr/share/polkit-1/actions/org.dpkg.pkexec.update-alternatives.policy"
+ ]
+ },
+ {
+ "ID": "findutils@4.10.0-3",
+ "Name": "findutils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/findutils@4.10.0-3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "111949a4800741f1"
+ },
+ "Version": "4.10.0",
+ "Release": "3",
+ "Arch": "amd64",
+ "SrcName": "findutils",
+ "SrcVersion": "4.10.0",
+ "SrcRelease": "3",
+ "Licenses": [
+ "GFDL-1.3-no-invariants-or-later",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "GPL-2+ with Autoconf-data exception",
+ "GPL-3+ with Autoconf-data exception",
+ "FSFULLR",
+ "GPL-2.0-or-later",
+ "X11",
+ "public-domain",
+ "LGPL-2.1-or-later",
+ "GPL with automake exception",
+ "LGPL-2.0-or-later",
+ "LGPL-3.0-or-later",
+ "BSD-3-Clause",
+ "GPL-3+ with Bison-2.2 exception",
+ "LGPL-3.0-only",
+ "ISC",
+ "GFDL-1.3-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Andreas Metzler \u003cametzler@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/find",
+ "/usr/bin/xargs",
+ "/usr/share/doc-base/findutils.findutils",
+ "/usr/share/doc/findutils/NEWS.gz",
+ "/usr/share/doc/findutils/README.gz",
+ "/usr/share/doc/findutils/TODO",
+ "/usr/share/doc/findutils/changelog.Debian.gz",
+ "/usr/share/doc/findutils/changelog.gz",
+ "/usr/share/doc/findutils/copyright",
+ "/usr/share/info/find-maint.info.gz",
+ "/usr/share/info/find.info.gz",
+ "/usr/share/locale/be/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/da/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/de/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/el/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/es/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/et/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/id/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/it/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/lg/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/findutils.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/findutils.mo",
+ "/usr/share/man/man1/find.1.gz",
+ "/usr/share/man/man1/xargs.1.gz"
+ ]
+ },
+ {
+ "ID": "gcc-14-base@14.2.0-19",
+ "Name": "gcc-14-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/gcc-14-base@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a2d64c6b5f038075"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-3.0-only",
+ "GFDL-1.2-only",
+ "Artistic-2.0",
+ "LGPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/gcc-14-base/README.Debian.amd64.gz",
+ "/usr/share/doc/gcc-14-base/TODO.Debian",
+ "/usr/share/doc/gcc-14-base/changelog.Debian.gz",
+ "/usr/share/doc/gcc-14-base/copyright"
+ ]
+ },
+ {
+ "ID": "grep@3.11-4",
+ "Name": "grep",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/grep@3.11-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d450e0ea7fae458f"
+ },
+ "Version": "3.11",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "grep",
+ "SrcVersion": "3.11",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only"
+ ],
+ "Maintainer": "Anibal Monsalve Salazar \u003canibal@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/egrep",
+ "/usr/bin/fgrep",
+ "/usr/bin/grep",
+ "/usr/bin/rgrep",
+ "/usr/share/doc/grep/AUTHORS",
+ "/usr/share/doc/grep/NEWS.Debian.gz",
+ "/usr/share/doc/grep/NEWS.gz",
+ "/usr/share/doc/grep/README",
+ "/usr/share/doc/grep/THANKS.gz",
+ "/usr/share/doc/grep/TODO.gz",
+ "/usr/share/doc/grep/changelog.Debian.gz",
+ "/usr/share/doc/grep/changelog.gz",
+ "/usr/share/doc/grep/copyright",
+ "/usr/share/info/grep.info.gz",
+ "/usr/share/locale/af/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/be/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/da/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/de/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/el/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/es/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/et/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/he/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/id/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/it/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/th/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/grep.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/grep.mo",
+ "/usr/share/man/man1/grep.1.gz"
+ ]
+ },
+ {
+ "ID": "gzip@1.13-1",
+ "Name": "gzip",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/gzip@1.13-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "60254b2bea6a1f09"
+ },
+ "Version": "1.13",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "gzip",
+ "SrcVersion": "1.13",
+ "SrcRelease": "1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GFDL-1.3+-no-invariant",
+ "FSF-manpages",
+ "GPL-3.0-only",
+ "GFDL-3"
+ ],
+ "Maintainer": "Milan Kupcevic \u003cmilan@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/gunzip",
+ "/usr/bin/gzexe",
+ "/usr/bin/gzip",
+ "/usr/bin/zcat",
+ "/usr/bin/zcmp",
+ "/usr/bin/zdiff",
+ "/usr/bin/zegrep",
+ "/usr/bin/zfgrep",
+ "/usr/bin/zforce",
+ "/usr/bin/zgrep",
+ "/usr/bin/zless",
+ "/usr/bin/zmore",
+ "/usr/bin/znew",
+ "/usr/share/doc/gzip/NEWS.gz",
+ "/usr/share/doc/gzip/README.gz",
+ "/usr/share/doc/gzip/TODO",
+ "/usr/share/doc/gzip/changelog.Debian.gz",
+ "/usr/share/doc/gzip/changelog.gz",
+ "/usr/share/doc/gzip/copyright",
+ "/usr/share/info/gzip.info.gz",
+ "/usr/share/man/man1/gzexe.1.gz",
+ "/usr/share/man/man1/gzip.1.gz",
+ "/usr/share/man/man1/zdiff.1.gz",
+ "/usr/share/man/man1/zforce.1.gz",
+ "/usr/share/man/man1/zgrep.1.gz",
+ "/usr/share/man/man1/zless.1.gz",
+ "/usr/share/man/man1/zmore.1.gz",
+ "/usr/share/man/man1/znew.1.gz"
+ ]
+ },
+ {
+ "ID": "hostname@3.25",
+ "Name": "hostname",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/hostname@3.25?arch=amd64\u0026distro=debian-13.6",
+ "UID": "87ef62957d44b2c"
+ },
+ "Version": "3.25",
+ "Arch": "amd64",
+ "SrcName": "hostname",
+ "SrcVersion": "3.25",
+ "Licenses": [
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Michael Meskes \u003cmeskes@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/hostname",
+ "/usr/share/doc/hostname/changelog.gz",
+ "/usr/share/doc/hostname/copyright",
+ "/usr/share/man/man1/hostname.1.gz"
+ ]
+ },
+ {
+ "ID": "init-system-helpers@1.69~deb13u1",
+ "Name": "init-system-helpers",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/init-system-helpers@1.69~deb13u1?arch=all\u0026distro=debian-13.6",
+ "UID": "317be9d9c6744acd"
+ },
+ "Version": "1.69~deb13u1",
+ "Arch": "all",
+ "SrcName": "init-system-helpers",
+ "SrcVersion": "1.69~deb13u1",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/deb-systemd-helper",
+ "/usr/bin/deb-systemd-invoke",
+ "/usr/sbin/invoke-rc.d",
+ "/usr/sbin/service",
+ "/usr/sbin/update-rc.d",
+ "/usr/share/bug/init-system-helpers/control",
+ "/usr/share/doc/init-system-helpers/README.invoke-rc.d.gz",
+ "/usr/share/doc/init-system-helpers/README.policy-rc.d.gz",
+ "/usr/share/doc/init-system-helpers/changelog.gz",
+ "/usr/share/doc/init-system-helpers/copyright",
+ "/usr/share/lintian/overrides/init-system-helpers",
+ "/usr/share/man/man1/deb-systemd-helper.1p.gz",
+ "/usr/share/man/man1/deb-systemd-invoke.1p.gz",
+ "/usr/share/man/man8/invoke-rc.d.8.gz",
+ "/usr/share/man/man8/service.8.gz",
+ "/usr/share/man/man8/update-rc.d.8.gz"
+ ]
+ },
+ {
+ "ID": "keyutils-libs@1.5.8-3.el7",
+ "Name": "keyutils-libs",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7",
+ "UID": "93c3119deb6a93bf",
+ "BOMRef": "pkg:rpm/centos/keyutils-libs@1.5.8-3.el7#b0804f4bd8708c97010e5324dbe6e1ed8cd5e622524afc3f44b4cf95c9e6cfd9"
+ },
+ "Version": "1.5.8",
+ "Release": "3.el7",
+ "SrcName": "keyutils-libs",
+ "SrcVersion": "1.5.8",
+ "SrcRelease": "3.el7",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "krb5-libs@1.15.1-55.el7_9",
+ "Name": "krb5-libs",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9",
+ "UID": "b0fe59dc84398982",
+ "BOMRef": "pkg:rpm/centos/krb5-libs@1.15.1-55.el7_9#5b1da461e2c57feebadb3f96f47736f4b17ad56a83895f95d60a166ced6472b0"
+ },
+ "Version": "1.15.1",
+ "Release": "55.el7_9",
+ "SrcName": "krb5-libs",
+ "SrcVersion": "1.15.1",
+ "SrcRelease": "55.el7_9",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "libacl1@2.3.2-2+b1",
+ "Name": "libacl1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libacl1@2.3.2-2%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "82548f6f7baf25f3"
+ },
+ "Version": "2.3.2",
+ "Release": "2+b1",
+ "Arch": "amd64",
+ "SrcName": "acl",
+ "SrcVersion": "2.3.2",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libacl.so.1.1.2302",
+ "/usr/share/doc/libacl1/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libacl1/changelog.Debian.gz",
+ "/usr/share/doc/libacl1/changelog.gz",
+ "/usr/share/doc/libacl1/copyright",
+ "/usr/share/lintian/overrides/libacl1"
+ ]
+ },
+ {
+ "ID": "libapt-pkg7.0@3.0.3",
+ "Name": "libapt-pkg7.0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libapt-pkg7.0@3.0.3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "df08f16788e2e8a6"
+ },
+ "Version": "3.0.3",
+ "Arch": "amd64",
+ "SrcName": "apt",
+ "SrcVersion": "3.0.3",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "curl",
+ "BSD-3-Clause",
+ "MIT",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "APT Development Team \u003cdeity@lists.debian.org\u003e",
+ "DependsOn": [
+ "libbz2-1.0@1.0.8-6",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "liblz4-1@1.10.0-4",
+ "liblzma5@5.8.1-1+deb13u1",
+ "libssl3t64@3.5.6-1~deb13u2",
+ "libstdc++6@14.2.0-19",
+ "libsystemd0@257.13-1~deb13u1",
+ "libudev1@257.13-1~deb13u1",
+ "libxxhash0@0.8.3-2",
+ "libzstd1@1.5.7+dfsg-1",
+ "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libapt-pkg.so.7.0.0",
+ "/usr/share/doc/libapt-pkg7.0/NEWS.Debian.gz",
+ "/usr/share/doc/libapt-pkg7.0/changelog.gz",
+ "/usr/share/doc/libapt-pkg7.0/copyright",
+ "/usr/share/locale/ar/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/da/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/de/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/el/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/es/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/it/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/km/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ku/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/th/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/libapt-pkg7.0.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/libapt-pkg7.0.mo"
+ ]
+ },
+ {
+ "ID": "libattr1@1:2.5.2-3",
+ "Name": "libattr1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libattr1@2.5.2-3?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "953f1d1395118b4b"
+ },
+ "Version": "2.5.2",
+ "Release": "3",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "attr",
+ "SrcVersion": "2.5.2",
+ "SrcRelease": "3",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libattr.so.1.1.2502",
+ "/usr/share/doc/libattr1/changelog.Debian.gz",
+ "/usr/share/doc/libattr1/changelog.gz",
+ "/usr/share/doc/libattr1/copyright",
+ "/usr/share/lintian/overrides/libattr1"
+ ]
+ },
+ {
+ "ID": "libaudit-common@1:4.0.2-2",
+ "Name": "libaudit-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libaudit-common@4.0.2-2?arch=all\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "4845289e49197cbd"
+ },
+ "Version": "4.0.2",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "all",
+ "SrcName": "audit",
+ "SrcVersion": "4.0.2",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Laurent Bigonville \u003cbigon@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/libaudit-common/changelog.Debian.gz",
+ "/usr/share/doc/libaudit-common/changelog.gz",
+ "/usr/share/doc/libaudit-common/copyright",
+ "/usr/share/man/man5/libaudit.conf.5.gz"
+ ]
+ },
+ {
+ "ID": "libaudit1@1:4.0.2-2+b2",
+ "Name": "libaudit1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libaudit1@4.0.2-2%2Bb2?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "c9ebadb6608e2305"
+ },
+ "Version": "4.0.2",
+ "Release": "2+b2",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "audit",
+ "SrcVersion": "4.0.2",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "GPL-2.0-only",
+ "LGPL-2.1-only",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Laurent Bigonville \u003cbigon@debian.org\u003e",
+ "DependsOn": [
+ "libaudit-common@1:4.0.2-2",
+ "libc6@2.41-12+deb13u3",
+ "libcap-ng0@0.8.5-4+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libaudit.so.1.0.0",
+ "/usr/share/doc/libaudit1/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libaudit1/changelog.Debian.gz",
+ "/usr/share/doc/libaudit1/changelog.gz",
+ "/usr/share/doc/libaudit1/copyright"
+ ]
+ },
+ {
+ "ID": "libblkid1@2.41-5",
+ "Name": "libblkid1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libblkid1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c427952a98b1e3ee"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libblkid.so.1.1.0",
+ "/usr/share/doc/libblkid1/NEWS.Debian.gz",
+ "/usr/share/doc/libblkid1/changelog.Debian.gz",
+ "/usr/share/doc/libblkid1/changelog.gz",
+ "/usr/share/doc/libblkid1/copyright",
+ "/usr/share/lintian/overrides/libblkid1"
+ ]
+ },
+ {
+ "ID": "libbsd0@0.12.2-2",
+ "Name": "libbsd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libbsd0@0.12.2-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "6a35c140077b4eb4"
+ },
+ "Version": "0.12.2",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libbsd",
+ "SrcVersion": "0.12.2",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-3-Clause",
+ "BSD-3-clause-Regents",
+ "BSD-2-Clause-NetBSD",
+ "BSD-3-clause-author",
+ "BSD-3-clause-John-Birrell",
+ "BSD-5-clause-Peter-Wemm",
+ "BSD-2-Clause",
+ "BSD-2-clause-verbatim",
+ "BSD-2-clause-author",
+ "ISC",
+ "ISC-Original",
+ "MIT",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libmd0@1.1.0-2+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libbsd.so.0.12.2",
+ "/usr/share/doc/libbsd0/changelog.Debian.gz",
+ "/usr/share/doc/libbsd0/changelog.gz",
+ "/usr/share/doc/libbsd0/copyright",
+ "/usr/share/lintian/overrides/libbsd0"
+ ]
+ },
+ {
+ "ID": "libbz2-1.0@1.0.8-6",
+ "Name": "libbz2-1.0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libbz2-1.0@1.0.8-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "395e7ab13e254394"
+ },
+ "Version": "1.0.8",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "bzip2",
+ "SrcVersion": "1.0.8",
+ "SrcRelease": "6",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Anibal Monsalve Salazar \u003canibal@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libbz2.so.1.0.4",
+ "/usr/share/doc/libbz2-1.0/changelog.Debian.gz",
+ "/usr/share/doc/libbz2-1.0/changelog.gz",
+ "/usr/share/doc/libbz2-1.0/copyright"
+ ]
+ },
+ {
+ "ID": "libc-bin@2.41-12+deb13u3",
+ "Name": "libc-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libc-bin@2.41-12%2Bdeb13u3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c17717cca0e61621"
+ },
+ "Version": "2.41",
+ "Release": "12+deb13u3",
+ "Arch": "amd64",
+ "SrcName": "glibc",
+ "SrcVersion": "2.41",
+ "SrcRelease": "12+deb13u3",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1+-with-link-exception",
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GPL-2+-with-link-exception",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "Carnegie",
+ "Inner-Net",
+ "MIT-like-Lord",
+ "BSD-like-Spencer",
+ "PCRE",
+ "BSD-3-clause-Carnegie",
+ "Unicode-DFS-2016",
+ "BSL-1.0",
+ "SunPro",
+ "CORE-MATH",
+ "BSD-3-clause-Berkeley",
+ "BSD-3-clause-WIDE",
+ "BSD-2-Clause",
+ "BSD-3-clause-Oracle",
+ "DEC",
+ "IBM",
+ "ISC",
+ "Univ-Coimbra",
+ "public-domain",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/getconf",
+ "/usr/bin/getent",
+ "/usr/bin/iconv",
+ "/usr/bin/ldd",
+ "/usr/bin/locale",
+ "/usr/bin/localedef",
+ "/usr/bin/pldd",
+ "/usr/bin/tzselect",
+ "/usr/bin/zdump",
+ "/usr/lib/locale/C.utf8/LC_ADDRESS",
+ "/usr/lib/locale/C.utf8/LC_COLLATE",
+ "/usr/lib/locale/C.utf8/LC_CTYPE",
+ "/usr/lib/locale/C.utf8/LC_IDENTIFICATION",
+ "/usr/lib/locale/C.utf8/LC_MEASUREMENT",
+ "/usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES",
+ "/usr/lib/locale/C.utf8/LC_MONETARY",
+ "/usr/lib/locale/C.utf8/LC_NAME",
+ "/usr/lib/locale/C.utf8/LC_NUMERIC",
+ "/usr/lib/locale/C.utf8/LC_PAPER",
+ "/usr/lib/locale/C.utf8/LC_TELEPHONE",
+ "/usr/lib/locale/C.utf8/LC_TIME",
+ "/usr/sbin/iconvconfig",
+ "/usr/sbin/ldconfig",
+ "/usr/sbin/zic",
+ "/usr/share/doc/libc-bin/changelog.Debian.gz",
+ "/usr/share/doc/libc-bin/changelog.gz",
+ "/usr/share/doc/libc-bin/copyright",
+ "/usr/share/libc-bin/nsswitch.conf",
+ "/usr/share/lintian/overrides/libc-bin",
+ "/usr/share/man/man1/getconf.1.gz",
+ "/usr/share/man/man1/tzselect.1.gz"
+ ]
+ },
+ {
+ "ID": "libc6@2.41-12+deb13u3",
+ "Name": "libc6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libc6@2.41-12%2Bdeb13u3?arch=amd64\u0026distro=debian-13.6",
+ "UID": "19d151c4d1229080"
+ },
+ "Version": "2.41",
+ "Release": "12+deb13u3",
+ "Arch": "amd64",
+ "SrcName": "glibc",
+ "SrcVersion": "2.41",
+ "SrcRelease": "12+deb13u3",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.1+-with-link-exception",
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GPL-2+-with-link-exception",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "FSFAP",
+ "Carnegie",
+ "Inner-Net",
+ "MIT-like-Lord",
+ "BSD-like-Spencer",
+ "PCRE",
+ "BSD-3-clause-Carnegie",
+ "Unicode-DFS-2016",
+ "BSL-1.0",
+ "SunPro",
+ "CORE-MATH",
+ "BSD-3-clause-Berkeley",
+ "BSD-3-clause-WIDE",
+ "BSD-2-Clause",
+ "BSD-3-clause-Oracle",
+ "DEC",
+ "IBM",
+ "ISC",
+ "Univ-Coimbra",
+ "public-domain",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libgcc-s1@14.2.0-19"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/gconv/ANSI_X3.110.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ARMSCII-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ASMO_449.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BIG5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BIG5HKSCS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/BRF.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP10007.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1125.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1250.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1251.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1252.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1253.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1254.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1255.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1256.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1257.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP1258.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP737.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP770.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP771.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP772.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP773.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP774.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP775.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CP932.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CSN_369103.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/CWI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/DEC-MCS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-CA-FR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-S.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE-A.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IS-FRISS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-PT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-UK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EBCDIC-US.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ECMA-CYRILLIC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-CN.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JP-MS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-JP.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-KR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/EUC-TW.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GB18030.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBBIG5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBGBK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GBK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-ACADEMY.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-PS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GOST_19768-74.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK-CCITT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK7-OLD.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/GREEK7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-GREEK8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN9.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-THAI8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/HP-TURKISH8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM037.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM038.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1004.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1008.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1008_420.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1025.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1026.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1046.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1047.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1097.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1112.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1122.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1123.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1124.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1129.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1130.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1132.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1133.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1137.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1140.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1141.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1142.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1143.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1144.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1145.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1146.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1147.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1148.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1149.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1153.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1154.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1155.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1156.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1157.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1158.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1160.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1161.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1162.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1163.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1164.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1166.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1167.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM12712.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1364.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1371.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1388.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1390.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM1399.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM16804.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM256.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM273.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM274.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM275.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM277.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM278.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM280.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM281.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM284.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM285.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM290.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM297.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM420.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM423.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM424.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM437.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4517.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4899.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4909.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM4971.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM500.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM5347.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM803.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM850.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM851.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM852.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM855.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM856.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM857.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM858.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM860.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM861.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM862.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM863.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM864.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM865.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM866.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM866NAV.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM868.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM869.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM870.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM871.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM874.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM875.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM880.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM891.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM901.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM902.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM903.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9030.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM904.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM905.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9066.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM918.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM921.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM922.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM930.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM932.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM933.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM935.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM937.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM939.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM943.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IBM9448.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/IEC_P27-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS-CYRILLIC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/INIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISIRI-3342.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN-EXT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP-3.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-2022-KR.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-IR-197.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO-IR-209.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO646.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-10.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-11.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-13.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-14.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-15.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-16.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-3.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-4.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-5.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-6.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-9.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO8859-9E.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_10367-BOX.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_11548-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_2033.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5427-EXT.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5427.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_5428.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_6937-2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/ISO_6937.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/JOHAB.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI-8.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-R.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-RU.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-T.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/KOI8-U.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-CENTRALEUROPE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-IS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-SAMI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MAC-UK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MACINTOSH.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/MIK.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/NATS-DANO.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/NATS-SEFI.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/PT154.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/RK1048.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SAMI-WS2.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SHIFT_JISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/SJIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/T.61.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TCVN5712-1.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TIS-620.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/TSCII.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UHC.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UNICODE.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-16.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-32.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/UTF-7.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/VISCII.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache",
+ "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.d/gconv-modules-extra.conf",
+ "/usr/lib/x86_64-linux-gnu/gconv/libCNS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libGB.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libISOIR165.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libJIS.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libJISX0213.so",
+ "/usr/lib/x86_64-linux-gnu/gconv/libKSC.so",
+ "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2",
+ "/usr/lib/x86_64-linux-gnu/libBrokenLocale.so.1",
+ "/usr/lib/x86_64-linux-gnu/libanl.so.1",
+ "/usr/lib/x86_64-linux-gnu/libc.so.6",
+ "/usr/lib/x86_64-linux-gnu/libc_malloc_debug.so.0",
+ "/usr/lib/x86_64-linux-gnu/libdl.so.2",
+ "/usr/lib/x86_64-linux-gnu/libm.so.6",
+ "/usr/lib/x86_64-linux-gnu/libmemusage.so",
+ "/usr/lib/x86_64-linux-gnu/libmvec.so.1",
+ "/usr/lib/x86_64-linux-gnu/libnsl.so.1",
+ "/usr/lib/x86_64-linux-gnu/libnss_compat.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_dns.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_files.so.2",
+ "/usr/lib/x86_64-linux-gnu/libnss_hesiod.so.2",
+ "/usr/lib/x86_64-linux-gnu/libpcprofile.so",
+ "/usr/lib/x86_64-linux-gnu/libpthread.so.0",
+ "/usr/lib/x86_64-linux-gnu/libresolv.so.2",
+ "/usr/lib/x86_64-linux-gnu/librt.so.1",
+ "/usr/lib/x86_64-linux-gnu/libthread_db.so.1",
+ "/usr/lib/x86_64-linux-gnu/libutil.so.1",
+ "/usr/share/doc/libc6/NEWS.Debian.gz",
+ "/usr/share/doc/libc6/NEWS.gz",
+ "/usr/share/doc/libc6/README.Debian.gz",
+ "/usr/share/doc/libc6/README.hesiod.gz",
+ "/usr/share/doc/libc6/changelog.Debian.gz",
+ "/usr/share/doc/libc6/changelog.gz",
+ "/usr/share/doc/libc6/copyright",
+ "/usr/share/lintian/overrides/libc6"
+ ]
+ },
+ {
+ "ID": "libcap-ng0@0.8.5-4+b1",
+ "Name": "libcap-ng0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcap-ng0@0.8.5-4%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "853c3a4f587b1e09"
+ },
+ "Version": "0.8.5",
+ "Release": "4+b1",
+ "Arch": "amd64",
+ "SrcName": "libcap-ng",
+ "SrcVersion": "0.8.5",
+ "SrcRelease": "4",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "GPL-2.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Håvard F. Aasen \u003chavard.f.aasen@pfft.no\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcap-ng.so.0.0.0",
+ "/usr/lib/x86_64-linux-gnu/libdrop_ambient.so.0.0.0",
+ "/usr/share/doc/libcap-ng0/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libcap-ng0/changelog.Debian.gz",
+ "/usr/share/doc/libcap-ng0/changelog.gz",
+ "/usr/share/doc/libcap-ng0/copyright"
+ ]
+ },
+ {
+ "ID": "libcap2@1:2.75-10+deb13u1+b1",
+ "Name": "libcap2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcap2@2.75-10%2Bdeb13u1%2Bb1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "451a510e42b50c7c"
+ },
+ "Version": "2.75",
+ "Release": "10+deb13u1+b1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "libcap2",
+ "SrcVersion": "2.75",
+ "SrcRelease": "10+deb13u1",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Christian Kastner \u003cckk@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcap.so.2.75",
+ "/usr/lib/x86_64-linux-gnu/libpsx.so.2.75",
+ "/usr/share/doc/libcap2/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libcap2/changelog.Debian.gz",
+ "/usr/share/doc/libcap2/changelog.gz",
+ "/usr/share/doc/libcap2/copyright"
+ ]
+ },
+ {
+ "ID": "libcom_err@1.42.9-19.el7",
+ "Name": "libcom_err",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/libcom_err@1.42.9-19.el7",
+ "UID": "dd13ac5974bf1c3f",
+ "BOMRef": "pkg:rpm/centos/libcom_err@1.42.9-19.el7#acf5d4191003325e79febc61cc2cc17ecbb1c49f03b73edbc4677777f25b75ce"
+ },
+ "Version": "1.42.9",
+ "Release": "19.el7",
+ "SrcName": "libcom_err",
+ "SrcVersion": "1.42.9",
+ "SrcRelease": "19.el7",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "libcrypt1@1:4.4.38-1",
+ "Name": "libcrypt1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libcrypt1@4.4.38-1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "185d1b457ef399b8"
+ },
+ "Version": "4.4.38",
+ "Release": "1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "libxcrypt",
+ "SrcVersion": "4.4.38",
+ "SrcRelease": "1",
+ "SrcEpoch": 1,
+ "Maintainer": "Marco d'Itri \u003cmd@linux.it\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0",
+ "/usr/share/doc/libcrypt1/changelog.Debian.gz",
+ "/usr/share/doc/libcrypt1/changelog.gz",
+ "/usr/share/doc/libcrypt1/copyright"
+ ]
+ },
+ {
+ "ID": "libdb5.3t64@5.3.28+dfsg2-9",
+ "Name": "libdb5.3t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libdb5.3t64@5.3.28%2Bdfsg2-9?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1d93101a053d025d"
+ },
+ "Version": "5.3.28+dfsg2",
+ "Release": "9",
+ "Arch": "amd64",
+ "SrcName": "db5.3",
+ "SrcVersion": "5.3.28+dfsg2",
+ "SrcRelease": "9",
+ "Licenses": [
+ "Sleepycat",
+ "BSD-3-Clause",
+ "MS-PL",
+ "GPL-2.0-or-later",
+ "Artistic-2.0",
+ "X11",
+ "MIT-old",
+ "TCL-like",
+ "BSD-3-clause-fjord",
+ "GPL-3.0-only",
+ "Zlib"
+ ],
+ "Maintainer": "Debian QA Group \u003cpackages@qa.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libdb-5.3.so",
+ "/usr/share/doc/libdb5.3t64/build_signature_amd64.txt",
+ "/usr/share/doc/libdb5.3t64/changelog.Debian.gz",
+ "/usr/share/doc/libdb5.3t64/copyright",
+ "/usr/share/lintian/overrides/libdb5.3t64"
+ ]
+ },
+ {
+ "ID": "libdebconfclient0@0.280",
+ "Name": "libdebconfclient0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libdebconfclient0@0.280?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f4d35c54ea8ebcdc"
+ },
+ "Version": "0.280",
+ "Arch": "amd64",
+ "SrcName": "cdebconf",
+ "SrcVersion": "0.280",
+ "Licenses": [
+ "BSD-2-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian Install System Team \u003cdebian-boot@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libdebconfclient.so.0.0.0",
+ "/usr/share/doc/libdebconfclient0/changelog.gz",
+ "/usr/share/doc/libdebconfclient0/copyright"
+ ]
+ },
+ {
+ "ID": "libffi8@3.4.8-2",
+ "Name": "libffi8",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libffi8@3.4.8-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d78c144a996938aa"
+ },
+ "Version": "3.4.8",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libffi",
+ "SrcVersion": "3.4.8",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT",
+ "X11",
+ "GPL-2.0-or-later",
+ "GPL-3.0-or-later",
+ "MPL-1.1",
+ "LGPL-2.1-or-later",
+ "public-domain"
+ ],
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libffi.so.8.1.4",
+ "/usr/share/doc/libffi8/changelog.Debian.gz",
+ "/usr/share/doc/libffi8/copyright"
+ ]
+ },
+ {
+ "ID": "libgcc-s1@14.2.0-19",
+ "Name": "libgcc-s1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgcc-s1@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "a939ab1a9133b3fa"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "gcc-14-base@14.2.0-19",
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgcc_s.so.1",
+ "/usr/share/lintian/overrides/libgcc-s1"
+ ]
+ },
+ {
+ "ID": "libgdbm6t64@1.24-2",
+ "Name": "libgdbm6t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgdbm6t64@1.24-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "79fdad8a6bd05b2d"
+ },
+ "Version": "1.24",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "gdbm",
+ "SrcVersion": "1.24",
+ "SrcRelease": "2",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "GFDL-1.3-no-invariants-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Nicolas Mora \u003cbabelouest@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgdbm.so.6.0.0",
+ "/usr/share/doc/libgdbm6t64/changelog.Debian.gz",
+ "/usr/share/doc/libgdbm6t64/changelog.gz",
+ "/usr/share/doc/libgdbm6t64/copyright",
+ "/usr/share/lintian/overrides/libgdbm6t64"
+ ]
+ },
+ {
+ "ID": "libgmp10@2:6.3.0+dfsg-3",
+ "Name": "libgmp10",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libgmp10@6.3.0%2Bdfsg-3?arch=amd64\u0026distro=debian-13.6\u0026epoch=2",
+ "UID": "8d1eefd06321d7f5"
+ },
+ "Version": "6.3.0+dfsg",
+ "Release": "3",
+ "Epoch": 2,
+ "Arch": "amd64",
+ "SrcName": "gmp",
+ "SrcVersion": "6.3.0+dfsg",
+ "SrcRelease": "3",
+ "SrcEpoch": 2,
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-or-later",
+ "GPL-3+ with Bison exception",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Debian Science Maintainers \u003cdebian-science-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libgmp.so.10.5.0",
+ "/usr/share/doc/libgmp10/README.Debian",
+ "/usr/share/doc/libgmp10/changelog.Debian.gz",
+ "/usr/share/doc/libgmp10/changelog.gz",
+ "/usr/share/doc/libgmp10/copyright"
+ ]
+ },
+ {
+ "ID": "libhogweed6t64@3.10.1-1",
+ "Name": "libhogweed6t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libhogweed6t64@3.10.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8c7c2e41ab9a40c8"
+ },
+ "Version": "3.10.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "nettle",
+ "SrcVersion": "3.10.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "MIT",
+ "GPL-3.0-with-autoconf-exception+",
+ "public-domain",
+ "GPL-2.0-only",
+ "GAP"
+ ],
+ "Maintainer": "Magnus Holmgren \u003cholmgren@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libgmp10@2:6.3.0+dfsg-3",
+ "libnettle8t64@3.10.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libhogweed.so.6.10",
+ "/usr/share/doc/libhogweed6t64/changelog.Debian.gz",
+ "/usr/share/doc/libhogweed6t64/changelog.gz",
+ "/usr/share/doc/libhogweed6t64/copyright",
+ "/usr/share/lintian/overrides/libhogweed6t64"
+ ]
+ },
+ {
+ "ID": "liblastlog2-2@2.41-5",
+ "Name": "liblastlog2-2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblastlog2-2@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d5ec9bb1797e1476"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libsqlite3-0@3.46.1-7+deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblastlog2.so.2.0.0",
+ "/usr/share/doc/liblastlog2-2/NEWS.Debian.gz",
+ "/usr/share/doc/liblastlog2-2/changelog.Debian.gz",
+ "/usr/share/doc/liblastlog2-2/changelog.gz",
+ "/usr/share/doc/liblastlog2-2/copyright"
+ ]
+ },
+ {
+ "ID": "liblz4-1@1.10.0-4",
+ "Name": "liblz4-1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblz4-1@1.10.0-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d06629bc3067545a"
+ },
+ "Version": "1.10.0",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "lz4",
+ "SrcVersion": "1.10.0",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "BSD-2-Clause",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Nobuhiro Iwamatsu \u003ciwamatsu@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libxxhash0@0.8.3-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblz4.so.1.10.0",
+ "/usr/share/doc/liblz4-1/changelog.Debian.gz",
+ "/usr/share/doc/liblz4-1/copyright"
+ ]
+ },
+ {
+ "ID": "liblzma5@5.8.1-1+deb13u1",
+ "Name": "liblzma5",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/liblzma5@5.8.1-1%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "6bb07f060c067c08"
+ },
+ "Version": "5.8.1",
+ "Release": "1+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "xz-utils",
+ "SrcVersion": "5.8.1",
+ "SrcRelease": "1+deb13u1",
+ "Licenses": [
+ "0BSD",
+ "GPL-2.0-or-later",
+ "LGPL-2.1-or-later",
+ "FSFULLR",
+ "GPL-3.0-or-later-WITH-Autoconf-exception-macro",
+ "none",
+ "PD",
+ "permissive-nowarranty",
+ "FSFUL",
+ "noderivs",
+ "PD-debian",
+ "LGPL-2.1-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only"
+ ],
+ "Maintainer": "Sebastian Andrzej Siewior \u003csebastian@breakpoint.cc\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/liblzma.so.5.8.1",
+ "/usr/share/doc/liblzma5/AUTHORS",
+ "/usr/share/doc/liblzma5/NEWS.gz",
+ "/usr/share/doc/liblzma5/THANKS.gz",
+ "/usr/share/doc/liblzma5/changelog.Debian.gz",
+ "/usr/share/doc/liblzma5/changelog.gz",
+ "/usr/share/doc/liblzma5/copyright"
+ ]
+ },
+ {
+ "ID": "libmd0@1.1.0-2+b1",
+ "Name": "libmd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libmd0@1.1.0-2%2Bb1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8f7242077c74e850"
+ },
+ "Version": "1.1.0",
+ "Release": "2+b1",
+ "Arch": "amd64",
+ "SrcName": "libmd",
+ "SrcVersion": "1.1.0",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-3-Clause",
+ "BSD-3-clause-Aaron-D-Gifford",
+ "BSD-2-Clause",
+ "BSD-2-Clause-NetBSD",
+ "ISC",
+ "Beerware",
+ "public-domain-md4",
+ "public-domain-md5",
+ "public-domain-sha1"
+ ],
+ "Maintainer": "Guillem Jover \u003cguillem@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libmd.so.0.1.0",
+ "/usr/share/doc/libmd0/changelog.Debian.amd64.gz",
+ "/usr/share/doc/libmd0/changelog.Debian.gz",
+ "/usr/share/doc/libmd0/changelog.gz",
+ "/usr/share/doc/libmd0/copyright"
+ ]
+ },
+ {
+ "ID": "libmount1@2.41-5",
+ "Name": "libmount1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libmount1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "e4ddbeb1b284f3ca"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libblkid1@2.41-5",
+ "libc6@2.41-12+deb13u3",
+ "libselinux1@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libmount.so.1.1.0",
+ "/usr/share/doc/libmount1/NEWS.Debian.gz",
+ "/usr/share/doc/libmount1/changelog.Debian.gz",
+ "/usr/share/doc/libmount1/changelog.gz",
+ "/usr/share/doc/libmount1/copyright",
+ "/usr/share/lintian/overrides/libmount1"
+ ]
+ },
+ {
+ "ID": "libncursesw6@6.5+20250216-2",
+ "Name": "libncursesw6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libncursesw6@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "fac6fddb91f7c21c"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libtinfo6@6.5+20250216-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libformw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libmenuw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libncursesw.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libpanelw.so.6.5"
+ ]
+ },
+ {
+ "ID": "libnettle8t64@3.10.1-1",
+ "Name": "libnettle8t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libnettle8t64@3.10.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3cd10b6383088c9"
+ },
+ "Version": "3.10.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "nettle",
+ "SrcVersion": "3.10.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-3.0-or-later",
+ "GPL-2.0-or-later",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "MIT",
+ "GPL-3.0-with-autoconf-exception+",
+ "public-domain",
+ "GPL-2.0-only",
+ "GAP"
+ ],
+ "Maintainer": "Magnus Holmgren \u003cholmgren@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libnettle.so.8.10",
+ "/usr/share/doc/libnettle8t64/NEWS.gz",
+ "/usr/share/doc/libnettle8t64/README",
+ "/usr/share/doc/libnettle8t64/changelog.Debian.gz",
+ "/usr/share/doc/libnettle8t64/changelog.gz",
+ "/usr/share/doc/libnettle8t64/copyright",
+ "/usr/share/lintian/overrides/libnettle8t64"
+ ]
+ },
+ {
+ "ID": "libpam-modules@1.7.0-5",
+ "Name": "libpam-modules",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-modules@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "b9d6f9c66558c40d"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/security/pam_access.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_canonicalize_user.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_debug.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_deny.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_echo.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_env.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_exec.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_faildelay.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_faillock.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_filter.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_ftp.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_group.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_issue.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_keyinit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_limits.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_listfile.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_localuser.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_loginuid.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_mail.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_mkhomedir.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_motd.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_namespace.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_nologin.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_permit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_pwhistory.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_rhosts.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_rootok.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_securetty.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_selinux.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_sepermit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_setquota.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_shells.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_stress.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_succeed_if.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_time.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_timestamp.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_tty_audit.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_umask.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_unix.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_userdb.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_usertype.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_warn.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_wheel.so",
+ "/usr/lib/x86_64-linux-gnu/security/pam_xauth.so",
+ "/usr/share/doc/libpam-modules/NEWS.Debian.gz",
+ "/usr/share/doc/libpam-modules/changelog.Debian.gz",
+ "/usr/share/doc/libpam-modules/changelog.gz",
+ "/usr/share/doc/libpam-modules/copyright",
+ "/usr/share/doc/libpam-modules/examples/upperLOWER.c",
+ "/usr/share/lintian/overrides/libpam-modules",
+ "/usr/share/pam-configs/mkhomedir"
+ ]
+ },
+ {
+ "ID": "libpam-modules-bin@1.7.0-5",
+ "Name": "libpam-modules-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-modules-bin@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f047dc4396624183"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam0g@1.7.0-5",
+ "libselinux1@3.8.1-1",
+ "libsystemd0@257.13-1~deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/systemd/system/pam_namespace.service",
+ "/usr/sbin/faillock",
+ "/usr/sbin/mkhomedir_helper",
+ "/usr/sbin/pam_namespace_helper",
+ "/usr/sbin/pam_timestamp_check",
+ "/usr/sbin/pwhistory_helper",
+ "/usr/sbin/unix_chkpwd",
+ "/usr/sbin/unix_update",
+ "/usr/share/doc/libpam-modules-bin/changelog.Debian.gz",
+ "/usr/share/doc/libpam-modules-bin/changelog.gz",
+ "/usr/share/doc/libpam-modules-bin/copyright",
+ "/usr/share/lintian/overrides/libpam-modules-bin"
+ ]
+ },
+ {
+ "ID": "libpam-runtime@1.7.0-5",
+ "Name": "libpam-runtime",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam-runtime@1.7.0-5?arch=all\u0026distro=debian-13.6",
+ "UID": "2e8bd19930283d52"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "all",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "libpam-modules@1.7.0-5"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/sbin/pam-auth-update",
+ "/usr/sbin/pam_getenv",
+ "/usr/share/doc/libpam-runtime/changelog.Debian.gz",
+ "/usr/share/doc/libpam-runtime/changelog.gz",
+ "/usr/share/doc/libpam-runtime/copyright",
+ "/usr/share/lintian/overrides/libpam-runtime",
+ "/usr/share/locale/af/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/am/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ar/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/as/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/az/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/be/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bn_IN/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/bs/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/cy/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/da/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/de/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/de_CH/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/el/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/es/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/et/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fa/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/gu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/he/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ia/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/id/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/is/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/it/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/km/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/kw_GB/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/lt/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/lv/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ml/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/mr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/my/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/or/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pa/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/si/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sq/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sr@latin/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ta/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/te/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/tg/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/th/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/ur/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/yo/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_HK/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/locale/zu/LC_MESSAGES/Linux-PAM.mo",
+ "/usr/share/man/man5/access.conf.5.gz",
+ "/usr/share/man/man5/faillock.conf.5.gz",
+ "/usr/share/man/man5/group.conf.5.gz",
+ "/usr/share/man/man5/limits.conf.5.gz",
+ "/usr/share/man/man5/namespace.conf.5.gz",
+ "/usr/share/man/man5/pam.conf.5.gz",
+ "/usr/share/man/man5/pam_env.conf.5.gz",
+ "/usr/share/man/man5/pwhistory.conf.5.gz",
+ "/usr/share/man/man5/sepermit.conf.5.gz",
+ "/usr/share/man/man5/time.conf.5.gz",
+ "/usr/share/man/man7/PAM.7.gz",
+ "/usr/share/man/man8/faillock.8.gz",
+ "/usr/share/man/man8/mkhomedir_helper.8.gz",
+ "/usr/share/man/man8/pam-auth-update.8.gz",
+ "/usr/share/man/man8/pam_access.8.gz",
+ "/usr/share/man/man8/pam_canonicalize_user.8.gz",
+ "/usr/share/man/man8/pam_debug.8.gz",
+ "/usr/share/man/man8/pam_deny.8.gz",
+ "/usr/share/man/man8/pam_echo.8.gz",
+ "/usr/share/man/man8/pam_env.8.gz",
+ "/usr/share/man/man8/pam_exec.8.gz",
+ "/usr/share/man/man8/pam_faildelay.8.gz",
+ "/usr/share/man/man8/pam_faillock.8.gz",
+ "/usr/share/man/man8/pam_filter.8.gz",
+ "/usr/share/man/man8/pam_ftp.8.gz",
+ "/usr/share/man/man8/pam_getenv.8.gz",
+ "/usr/share/man/man8/pam_group.8.gz",
+ "/usr/share/man/man8/pam_issue.8.gz",
+ "/usr/share/man/man8/pam_keyinit.8.gz",
+ "/usr/share/man/man8/pam_limits.8.gz",
+ "/usr/share/man/man8/pam_listfile.8.gz",
+ "/usr/share/man/man8/pam_localuser.8.gz",
+ "/usr/share/man/man8/pam_loginuid.8.gz",
+ "/usr/share/man/man8/pam_mail.8.gz",
+ "/usr/share/man/man8/pam_mkhomedir.8.gz",
+ "/usr/share/man/man8/pam_motd.8.gz",
+ "/usr/share/man/man8/pam_namespace.8.gz",
+ "/usr/share/man/man8/pam_namespace_helper.8.gz",
+ "/usr/share/man/man8/pam_nologin.8.gz",
+ "/usr/share/man/man8/pam_permit.8.gz",
+ "/usr/share/man/man8/pam_pwhistory.8.gz",
+ "/usr/share/man/man8/pam_rhosts.8.gz",
+ "/usr/share/man/man8/pam_rootok.8.gz",
+ "/usr/share/man/man8/pam_securetty.8.gz",
+ "/usr/share/man/man8/pam_selinux.8.gz",
+ "/usr/share/man/man8/pam_sepermit.8.gz",
+ "/usr/share/man/man8/pam_setquota.8.gz",
+ "/usr/share/man/man8/pam_shells.8.gz",
+ "/usr/share/man/man8/pam_stress.8.gz",
+ "/usr/share/man/man8/pam_succeed_if.8.gz",
+ "/usr/share/man/man8/pam_time.8.gz",
+ "/usr/share/man/man8/pam_timestamp.8.gz",
+ "/usr/share/man/man8/pam_timestamp_check.8.gz",
+ "/usr/share/man/man8/pam_tty_audit.8.gz",
+ "/usr/share/man/man8/pam_umask.8.gz",
+ "/usr/share/man/man8/pam_unix.8.gz",
+ "/usr/share/man/man8/pam_userdb.8.gz",
+ "/usr/share/man/man8/pam_usertype.8.gz",
+ "/usr/share/man/man8/pam_warn.8.gz",
+ "/usr/share/man/man8/pam_wheel.8.gz",
+ "/usr/share/man/man8/pam_xauth.8.gz",
+ "/usr/share/man/man8/pwhistory_helper.8.gz",
+ "/usr/share/man/man8/unix_chkpwd.8.gz",
+ "/usr/share/man/man8/unix_update.8.gz",
+ "/usr/share/pam-configs/unix",
+ "/usr/share/pam/common-account",
+ "/usr/share/pam/common-account.md5sums",
+ "/usr/share/pam/common-auth",
+ "/usr/share/pam/common-auth.md5sums",
+ "/usr/share/pam/common-password",
+ "/usr/share/pam/common-password.md5sums",
+ "/usr/share/pam/common-session",
+ "/usr/share/pam/common-session-noninteractive",
+ "/usr/share/pam/common-session-noninteractive.md5sums",
+ "/usr/share/pam/common-session.md5sums"
+ ]
+ },
+ {
+ "ID": "libpam0g@1.7.0-5",
+ "Name": "libpam0g",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpam0g@1.7.0-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "5dbda12bb939f426"
+ },
+ "Version": "1.7.0",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "pam",
+ "SrcVersion": "1.7.0",
+ "SrcRelease": "5",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-or-later",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "BSD-tcp_wrappers",
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only",
+ "public-domain",
+ "Beerware"
+ ],
+ "Maintainer": "Sam Hartman \u003chartmans@debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91",
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libpam.so.0.85.1",
+ "/usr/lib/x86_64-linux-gnu/libpam_misc.so.0.82.1",
+ "/usr/lib/x86_64-linux-gnu/libpamc.so.0.82.1",
+ "/usr/share/doc/libpam0g/Debian-PAM-MiniPolicy.gz",
+ "/usr/share/doc/libpam0g/README",
+ "/usr/share/doc/libpam0g/README.Debian",
+ "/usr/share/doc/libpam0g/TODO.Debian",
+ "/usr/share/doc/libpam0g/changelog.Debian.gz",
+ "/usr/share/doc/libpam0g/changelog.gz",
+ "/usr/share/doc/libpam0g/copyright",
+ "/usr/share/lintian/overrides/libpam0g"
+ ]
+ },
+ {
+ "ID": "libpcre2-8-0@10.46-1~deb13u1",
+ "Name": "libpcre2-8-0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libpcre2-8-0@10.46-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "cb52bbc65534e04d"
+ },
+ "Version": "10.46",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "pcre2",
+ "SrcVersion": "10.46",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "BSD-3-clause-Cambridge with BINARY LIBRARY-LIKE PACKAGES exception",
+ "BSD-3-Clause",
+ "X11",
+ "BSD-2-Clause",
+ "public-domain"
+ ],
+ "Maintainer": "Matthew Vernon \u003cmatthew@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libpcre2-8.so.0.14.0",
+ "/usr/share/doc/libpcre2-8-0/README.Debian",
+ "/usr/share/doc/libpcre2-8-0/changelog.Debian.gz",
+ "/usr/share/doc/libpcre2-8-0/changelog.gz",
+ "/usr/share/doc/libpcre2-8-0/copyright"
+ ]
+ },
+ {
+ "ID": "libreadline8t64@8.2-6",
+ "Name": "libreadline8t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libreadline8t64@8.2-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "3182860c74d6d08d"
+ },
+ "Version": "8.2",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "readline",
+ "SrcVersion": "8.2",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-or-later",
+ "ISC-no-attribution"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libtinfo6@6.5+20250216-2",
+ "readline-common@8.2-6"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libhistory.so.8.2",
+ "/usr/lib/x86_64-linux-gnu/libreadline.so.8.2",
+ "/usr/share/doc/libreadline8t64/README.Debian",
+ "/usr/share/doc/libreadline8t64/USAGE",
+ "/usr/share/doc/libreadline8t64/changelog.Debian.gz",
+ "/usr/share/doc/libreadline8t64/changelog.gz",
+ "/usr/share/doc/libreadline8t64/copyright",
+ "/usr/share/doc/libreadline8t64/examples/Inputrc",
+ "/usr/share/doc/libreadline8t64/inputrc.arrows"
+ ]
+ },
+ {
+ "ID": "libseccomp2@2.6.0-2",
+ "Name": "libseccomp2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libseccomp2@2.6.0-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "872fd916e9134574"
+ },
+ "Version": "2.6.0",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "libseccomp",
+ "SrcVersion": "2.6.0",
+ "SrcRelease": "2",
+ "Licenses": [
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Kees Cook \u003ckees@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libseccomp.so.2.6.0",
+ "/usr/share/doc/libseccomp2/changelog.Debian.gz",
+ "/usr/share/doc/libseccomp2/changelog.gz",
+ "/usr/share/doc/libseccomp2/copyright"
+ ]
+ },
+ {
+ "ID": "libselinux@2.5-15.el7",
+ "Name": "libselinux",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/libselinux@2.5-15.el7",
+ "UID": "6e37f06bf3057b37",
+ "BOMRef": "pkg:rpm/centos/libselinux@2.5-15.el7#02193ff4a4eff6fcc27e9c3cf39839797d150f578de0826f36a41de8ede637ed"
+ },
+ "Version": "2.5",
+ "Release": "15.el7",
+ "SrcName": "libselinux",
+ "SrcVersion": "2.5",
+ "SrcRelease": "15.el7",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "libselinux1@3.8.1-1",
+ "Name": "libselinux1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libselinux1@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "dad36e826c972129"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libselinux",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "public-domain",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libpcre2-8-0@10.46-1~deb13u1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/tmpfiles.d/libselinux1.conf",
+ "/usr/lib/x86_64-linux-gnu/libselinux.so.1",
+ "/usr/share/doc/libselinux1/changelog.Debian.gz",
+ "/usr/share/doc/libselinux1/copyright"
+ ]
+ },
+ {
+ "ID": "libsemanage-common@3.8.1-1",
+ "Name": "libsemanage-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsemanage-common@3.8.1-1?arch=all\u0026distro=debian-13.6",
+ "UID": "82e27fcff653c8e2"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "all",
+ "SrcName": "libsemanage",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/libsemanage-common/changelog.Debian.gz",
+ "/usr/share/doc/libsemanage-common/copyright",
+ "/usr/share/man/man5/semanage.conf.5.gz"
+ ]
+ },
+ {
+ "ID": "libsemanage2@3.8.1-1",
+ "Name": "libsemanage2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsemanage2@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "dc362d6ee87a25c7"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libsemanage",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libbz2-1.0@1.0.8-6",
+ "libc6@2.41-12+deb13u3",
+ "libselinux1@3.8.1-1",
+ "libsemanage-common@3.8.1-1",
+ "libsepol2@3.8.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsemanage.so.2",
+ "/usr/share/doc/libsemanage2/changelog.Debian.gz",
+ "/usr/share/doc/libsemanage2/copyright"
+ ]
+ },
+ {
+ "ID": "libsepol2@3.8.1-1",
+ "Name": "libsepol2",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsepol2@3.8.1-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8a467f0e7ce023a5"
+ },
+ "Version": "3.8.1",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libsepol",
+ "SrcVersion": "3.8.1",
+ "SrcRelease": "1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "Zlib",
+ "GPL-2.0-only",
+ "GPL-2.0-or-later"
+ ],
+ "Maintainer": "Debian SELinux maintainers \u003cselinux-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsepol.so.2",
+ "/usr/share/doc/libsepol2/changelog.Debian.gz",
+ "/usr/share/doc/libsepol2/copyright"
+ ]
+ },
+ {
+ "ID": "libsmartcols1@2.41-5",
+ "Name": "libsmartcols1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsmartcols1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "4d10e734941c1d1d"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsmartcols.so.1.1.0",
+ "/usr/share/doc/libsmartcols1/NEWS.Debian.gz",
+ "/usr/share/doc/libsmartcols1/changelog.Debian.gz",
+ "/usr/share/doc/libsmartcols1/changelog.gz",
+ "/usr/share/doc/libsmartcols1/copyright",
+ "/usr/share/lintian/overrides/libsmartcols1"
+ ]
+ },
+ {
+ "ID": "libsqlite3-0@3.46.1-7+deb13u1",
+ "Name": "libsqlite3-0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsqlite3-0@3.46.1-7%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "49853bfc5d923fa8"
+ },
+ "Version": "3.46.1",
+ "Release": "7+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "sqlite3",
+ "SrcVersion": "3.46.1",
+ "SrcRelease": "7+deb13u1",
+ "Licenses": [
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Laszlo Boszormenyi (GCS) \u003cgcs@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6",
+ "/usr/share/doc/libsqlite3-0/README.Debian",
+ "/usr/share/doc/libsqlite3-0/changelog.Debian.gz",
+ "/usr/share/doc/libsqlite3-0/changelog.gz",
+ "/usr/share/doc/libsqlite3-0/changelog.html.gz",
+ "/usr/share/doc/libsqlite3-0/copyright"
+ ]
+ },
+ {
+ "ID": "libssl3t64@3.5.6-1~deb13u2",
+ "Name": "libssl3t64",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libssl3t64@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "1ca83fc0831fc12a"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libzstd1@1.5.7+dfsg-1",
+ "openssl-provider-legacy@3.5.6-1~deb13u2",
+ "zlib1g@1:1.3.dfsg+really1.3.1-1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/engines-3/afalg.so",
+ "/usr/lib/x86_64-linux-gnu/engines-3/loader_attic.so",
+ "/usr/lib/x86_64-linux-gnu/engines-3/padlock.so",
+ "/usr/lib/x86_64-linux-gnu/libcrypto.so.3",
+ "/usr/lib/x86_64-linux-gnu/libssl.so.3",
+ "/usr/share/doc/libssl3t64/NEWS.Debian.gz",
+ "/usr/share/doc/libssl3t64/changelog.Debian.gz",
+ "/usr/share/doc/libssl3t64/changelog.gz",
+ "/usr/share/doc/libssl3t64/copyright",
+ "/usr/share/lintian/overrides/libssl3t64"
+ ]
+ },
+ {
+ "ID": "libstdc++6@14.2.0-19",
+ "Name": "libstdc++6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libstdc%2B%2B6@14.2.0-19?arch=amd64\u0026distro=debian-13.6",
+ "UID": "44612415c1730efa"
+ },
+ "Version": "14.2.0",
+ "Release": "19",
+ "Arch": "amd64",
+ "SrcName": "gcc-14",
+ "SrcVersion": "14.2.0",
+ "SrcRelease": "19",
+ "Maintainer": "Debian GCC Maintainers \u003cdebian-gcc@lists.debian.org\u003e",
+ "DependsOn": [
+ "gcc-14-base@14.2.0-19",
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33",
+ "/usr/share/gcc/python/libstdcxx/__init__.py",
+ "/usr/share/gcc/python/libstdcxx/v6/__init__.py",
+ "/usr/share/gcc/python/libstdcxx/v6/printers.py",
+ "/usr/share/gcc/python/libstdcxx/v6/xmethods.py",
+ "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.33-gdb.py"
+ ]
+ },
+ {
+ "ID": "libsystemd0@257.13-1~deb13u1",
+ "Name": "libsystemd0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libsystemd0@257.13-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d7f6e0bcc5fd6683"
+ },
+ "Version": "257.13",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "systemd",
+ "SrcVersion": "257.13",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "CC0-1.0",
+ "GPL-2 with Linux-syscall-note exception",
+ "MIT",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libcap2@1:2.75-10+deb13u1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libsystemd.so.0.40.0",
+ "/usr/share/doc/libsystemd0/NEWS.Debian.gz",
+ "/usr/share/doc/libsystemd0/changelog.Debian.gz",
+ "/usr/share/doc/libsystemd0/copyright"
+ ]
+ },
+ {
+ "ID": "libtinfo6@6.5+20250216-2",
+ "Name": "libtinfo6",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libtinfo6@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "12095a35cca3541c"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libtic.so.6.5",
+ "/usr/lib/x86_64-linux-gnu/libtinfo.so.6.5",
+ "/usr/share/doc/libtinfo6/changelog.Debian.gz",
+ "/usr/share/doc/libtinfo6/changelog.gz",
+ "/usr/share/doc/libtinfo6/copyright"
+ ]
+ },
+ {
+ "ID": "libudev1@257.13-1~deb13u1",
+ "Name": "libudev1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libudev1@257.13-1~deb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "151b8b6a80baf5ce"
+ },
+ "Version": "257.13",
+ "Release": "1~deb13u1",
+ "Arch": "amd64",
+ "SrcName": "systemd",
+ "SrcVersion": "257.13",
+ "SrcRelease": "1~deb13u1",
+ "Licenses": [
+ "LGPL-2.1-or-later",
+ "CC0-1.0",
+ "GPL-2 with Linux-syscall-note exception",
+ "MIT",
+ "public-domain",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian systemd Maintainers \u003cpkg-systemd-maintainers@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libcap2@1:2.75-10+deb13u1+b1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libudev.so.1.7.10",
+ "/usr/share/doc/libudev1/NEWS.Debian.gz",
+ "/usr/share/doc/libudev1/changelog.Debian.gz",
+ "/usr/share/doc/libudev1/copyright"
+ ]
+ },
+ {
+ "ID": "libuuid1@2.41-5",
+ "Name": "libuuid1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libuuid1@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "ad45ef419bdcd798"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libuuid.so.1.3.0",
+ "/usr/share/doc/libuuid1/NEWS.Debian.gz",
+ "/usr/share/doc/libuuid1/changelog.Debian.gz",
+ "/usr/share/doc/libuuid1/changelog.gz",
+ "/usr/share/doc/libuuid1/copyright"
+ ]
+ },
+ {
+ "ID": "libxxhash0@0.8.3-2",
+ "Name": "libxxhash0",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libxxhash0@0.8.3-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "413b9b44940ce169"
+ },
+ "Version": "0.8.3",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "xxhash",
+ "SrcVersion": "0.8.3",
+ "SrcRelease": "2",
+ "Licenses": [
+ "BSD-2-Clause",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Josue Ortega \u003cjosue@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libxxhash.so.0.8.3",
+ "/usr/share/doc/libxxhash0/changelog.Debian.gz",
+ "/usr/share/doc/libxxhash0/changelog.gz",
+ "/usr/share/doc/libxxhash0/copyright"
+ ]
+ },
+ {
+ "ID": "libzstd1@1.5.7+dfsg-1",
+ "Name": "libzstd1",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/libzstd1@1.5.7%2Bdfsg-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "7262601866572971"
+ },
+ "Version": "1.5.7+dfsg",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "libzstd",
+ "SrcVersion": "1.5.7+dfsg",
+ "SrcRelease": "1",
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-2.0-only",
+ "Zlib",
+ "MIT"
+ ],
+ "Maintainer": "RPM packaging team \u003cteam+pkg-rpm@tracker.debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libzstd.so.1.5.7",
+ "/usr/share/doc/libzstd1/changelog.Debian.gz",
+ "/usr/share/doc/libzstd1/changelog.gz",
+ "/usr/share/doc/libzstd1/copyright"
+ ]
+ },
+ {
+ "ID": "login@1:4.16.0-2+really2.41-5",
+ "Name": "login",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/login@4.16.0-2%2Breally2.41-5?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "468f3d4a374ef1"
+ },
+ "Version": "4.16.0-2+really2.41",
+ "Release": "5",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "DependsOn": [
+ "libaudit1@1:4.0.2-2+b2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam-modules@1.7.0-5",
+ "libpam-runtime@1.7.0-5",
+ "libpam0g@1.7.0-5"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/login",
+ "/usr/bin/newgrp",
+ "/usr/sbin/nologin",
+ "/usr/share/bash-completion/completions/newgrp",
+ "/usr/share/doc/login/NEWS.Debian.gz",
+ "/usr/share/doc/login/changelog.Debian.gz",
+ "/usr/share/doc/login/changelog.gz",
+ "/usr/share/doc/login/copyright",
+ "/usr/share/lintian/overrides/login",
+ "/usr/share/man/de/man1/login.1.gz",
+ "/usr/share/man/de/man8/nologin.8.gz",
+ "/usr/share/man/fr/man1/login.1.gz",
+ "/usr/share/man/man1/login.1.gz",
+ "/usr/share/man/man1/newgrp.1.gz",
+ "/usr/share/man/man8/nologin.8.gz",
+ "/usr/share/man/pl/man1/login.1.gz",
+ "/usr/share/man/pl/man1/newgrp.1.gz",
+ "/usr/share/man/pl/man8/nologin.8.gz",
+ "/usr/share/man/ro/man1/login.1.gz",
+ "/usr/share/man/ro/man1/newgrp.1.gz",
+ "/usr/share/man/ro/man8/nologin.8.gz",
+ "/usr/share/man/sr/man1/login.1.gz",
+ "/usr/share/man/sr/man8/nologin.8.gz",
+ "/usr/share/man/uk/man1/login.1.gz",
+ "/usr/share/man/uk/man1/newgrp.1.gz",
+ "/usr/share/man/uk/man8/nologin.8.gz"
+ ]
+ },
+ {
+ "ID": "login.defs@1:4.17.4-2",
+ "Name": "login.defs",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/login.defs@4.17.4-2?arch=all\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "b2ebc9108569350a"
+ },
+ "Version": "4.17.4",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "all",
+ "SrcName": "shadow",
+ "SrcVersion": "4.17.4",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-1.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/login.defs/NEWS.Debian.gz",
+ "/usr/share/doc/login.defs/changelog.Debian.gz",
+ "/usr/share/doc/login.defs/changelog.gz",
+ "/usr/share/doc/login.defs/copyright",
+ "/usr/share/man/de/man5/login.defs.5.gz",
+ "/usr/share/man/fr/man5/login.defs.5.gz",
+ "/usr/share/man/it/man5/login.defs.5.gz",
+ "/usr/share/man/ja/man5/login.defs.5.gz",
+ "/usr/share/man/man5/login.defs.5.gz",
+ "/usr/share/man/ru/man5/login.defs.5.gz",
+ "/usr/share/man/uk/man5/login.defs.5.gz",
+ "/usr/share/man/zh_CN/man5/login.defs.5.gz"
+ ]
+ },
+ {
+ "ID": "mawk@1.3.4.20250131-1",
+ "Name": "mawk",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/mawk@1.3.4.20250131-1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "9048a1b0d5acbb7e"
+ },
+ "Version": "1.3.4.20250131",
+ "Release": "1",
+ "Arch": "amd64",
+ "SrcName": "mawk",
+ "SrcVersion": "1.3.4.20250131",
+ "SrcRelease": "1",
+ "Licenses": [
+ "GPL-2.0-only",
+ "X11",
+ "CC-BY-3.0"
+ ],
+ "Maintainer": "Boyuan Yang \u003cbyang@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/mawk",
+ "/usr/share/doc/mawk/ACKNOWLEDGMENT",
+ "/usr/share/doc/mawk/README",
+ "/usr/share/doc/mawk/changelog.Debian.gz",
+ "/usr/share/doc/mawk/changelog.gz",
+ "/usr/share/doc/mawk/copyright",
+ "/usr/share/doc/mawk/examples/ct_length.awk",
+ "/usr/share/doc/mawk/examples/decl.awk",
+ "/usr/share/doc/mawk/examples/deps.awk",
+ "/usr/share/doc/mawk/examples/eatc.awk",
+ "/usr/share/doc/mawk/examples/gdecl.awk",
+ "/usr/share/doc/mawk/examples/hcal",
+ "/usr/share/doc/mawk/examples/hical",
+ "/usr/share/doc/mawk/examples/nocomment.awk",
+ "/usr/share/doc/mawk/examples/primes.awk",
+ "/usr/share/doc/mawk/examples/qsort.awk",
+ "/usr/share/man/man1/mawk.1.gz",
+ "/usr/share/man/man7/mawk-arrays.7.gz",
+ "/usr/share/man/man7/mawk-code.7.gz"
+ ]
+ },
+ {
+ "ID": "mount@2.41-5",
+ "Name": "mount",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/mount@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "c6fdc5cf989db569"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/mount",
+ "/usr/bin/umount",
+ "/usr/sbin/losetup",
+ "/usr/sbin/swapoff",
+ "/usr/sbin/swapon",
+ "/usr/share/bash-completion/completions/losetup",
+ "/usr/share/bash-completion/completions/mount",
+ "/usr/share/bash-completion/completions/swapoff",
+ "/usr/share/bash-completion/completions/swapon",
+ "/usr/share/bash-completion/completions/umount",
+ "/usr/share/doc/mount/NEWS.Debian.gz",
+ "/usr/share/doc/mount/changelog.Debian.gz",
+ "/usr/share/doc/mount/changelog.gz",
+ "/usr/share/doc/mount/copyright",
+ "/usr/share/doc/mount/examples/filesystems",
+ "/usr/share/doc/mount/examples/fstab",
+ "/usr/share/doc/mount/examples/mount.fstab",
+ "/usr/share/doc/mount/mount.txt",
+ "/usr/share/lintian/overrides/mount",
+ "/usr/share/man/man5/fstab.5.gz",
+ "/usr/share/man/man8/losetup.8.gz",
+ "/usr/share/man/man8/mount.8.gz",
+ "/usr/share/man/man8/swapon.8.gz",
+ "/usr/share/man/man8/umount.8.gz"
+ ]
+ },
+ {
+ "ID": "ncurses-base@6.5+20250216-2",
+ "Name": "ncurses-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ncurses-base@6.5%2B20250216-2?arch=all\u0026distro=debian-13.6",
+ "UID": "76a1fb5936f344dc"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "all",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/ncurses-base/FAQ",
+ "/usr/share/doc/ncurses-base/TODO.Debian",
+ "/usr/share/doc/ncurses-base/changelog.Debian.gz",
+ "/usr/share/doc/ncurses-base/changelog.gz",
+ "/usr/share/doc/ncurses-base/copyright",
+ "/usr/share/lintian/overrides/ncurses-base",
+ "/usr/share/tabset/std",
+ "/usr/share/tabset/stdcrt",
+ "/usr/share/tabset/vt100",
+ "/usr/share/tabset/vt300",
+ "/usr/share/terminfo/E/Eterm",
+ "/usr/share/terminfo/a/ansi",
+ "/usr/share/terminfo/c/cons25",
+ "/usr/share/terminfo/c/cygwin",
+ "/usr/share/terminfo/d/dumb",
+ "/usr/share/terminfo/h/hurd",
+ "/usr/share/terminfo/l/linux",
+ "/usr/share/terminfo/m/mach",
+ "/usr/share/terminfo/m/mach-bold",
+ "/usr/share/terminfo/m/mach-color",
+ "/usr/share/terminfo/m/mach-gnu",
+ "/usr/share/terminfo/m/mach-gnu-color",
+ "/usr/share/terminfo/p/pcansi",
+ "/usr/share/terminfo/r/rxvt",
+ "/usr/share/terminfo/r/rxvt-basic",
+ "/usr/share/terminfo/r/rxvt-unicode",
+ "/usr/share/terminfo/r/rxvt-unicode-256color",
+ "/usr/share/terminfo/s/screen",
+ "/usr/share/terminfo/s/screen-256color",
+ "/usr/share/terminfo/s/screen-256color-bce",
+ "/usr/share/terminfo/s/screen-bce",
+ "/usr/share/terminfo/s/screen-s",
+ "/usr/share/terminfo/s/screen-w",
+ "/usr/share/terminfo/s/screen.xterm-256color",
+ "/usr/share/terminfo/s/sun",
+ "/usr/share/terminfo/t/tmux",
+ "/usr/share/terminfo/t/tmux-256color",
+ "/usr/share/terminfo/v/vt100",
+ "/usr/share/terminfo/v/vt102",
+ "/usr/share/terminfo/v/vt220",
+ "/usr/share/terminfo/v/vt52",
+ "/usr/share/terminfo/w/wsvt25",
+ "/usr/share/terminfo/w/wsvt25m",
+ "/usr/share/terminfo/x/xterm",
+ "/usr/share/terminfo/x/xterm-256color",
+ "/usr/share/terminfo/x/xterm-color",
+ "/usr/share/terminfo/x/xterm-mono",
+ "/usr/share/terminfo/x/xterm-r5",
+ "/usr/share/terminfo/x/xterm-r6",
+ "/usr/share/terminfo/x/xterm-vt220",
+ "/usr/share/terminfo/x/xterm-xfree86"
+ ]
+ },
+ {
+ "ID": "ncurses-bin@6.5+20250216-2",
+ "Name": "ncurses-bin",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/ncurses-bin@6.5%2B20250216-2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d03e89ad6a7a5243"
+ },
+ "Version": "6.5+20250216",
+ "Release": "2",
+ "Arch": "amd64",
+ "SrcName": "ncurses",
+ "SrcVersion": "6.5+20250216",
+ "SrcRelease": "2",
+ "Licenses": [
+ "MIT/X11",
+ "X11",
+ "BSD-3-Clause"
+ ],
+ "Maintainer": "Ncurses Maintainers \u003cncurses@packages.debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/clear",
+ "/usr/bin/infocmp",
+ "/usr/bin/tabs",
+ "/usr/bin/tic",
+ "/usr/bin/toe",
+ "/usr/bin/tput",
+ "/usr/bin/tset",
+ "/usr/share/doc/ncurses-bin/changelog.Debian.gz",
+ "/usr/share/doc/ncurses-bin/changelog.gz",
+ "/usr/share/doc/ncurses-bin/copyright",
+ "/usr/share/man/man1/captoinfo.1.gz",
+ "/usr/share/man/man1/clear.1.gz",
+ "/usr/share/man/man1/infocmp.1.gz",
+ "/usr/share/man/man1/infotocap.1.gz",
+ "/usr/share/man/man1/tabs.1.gz",
+ "/usr/share/man/man1/tic.1.gz",
+ "/usr/share/man/man1/toe.1.gz",
+ "/usr/share/man/man1/tput.1.gz",
+ "/usr/share/man/man1/tset.1.gz",
+ "/usr/share/man/man5/scr_dump.5.gz",
+ "/usr/share/man/man5/term.5.gz",
+ "/usr/share/man/man5/terminfo.5.gz",
+ "/usr/share/man/man5/user_caps.5.gz",
+ "/usr/share/man/man7/term.7.gz"
+ ]
+ },
+ {
+ "ID": "netbase@6.5",
+ "Name": "netbase",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/netbase@6.5?arch=all\u0026distro=debian-13.6",
+ "UID": "b9a2c240e75fe15e"
+ },
+ "Version": "6.5",
+ "Arch": "all",
+ "SrcName": "netbase",
+ "SrcVersion": "6.5",
+ "Licenses": [
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Marco d'Itri \u003cmd@linux.it\u003e",
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/netbase/changelog.gz",
+ "/usr/share/doc/netbase/copyright"
+ ]
+ },
+ {
+ "ID": "openssl@3.5.6-1~deb13u2",
+ "Name": "openssl",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/openssl@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8f9e5d7117307079"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libssl3t64@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:ccbaccfc0388284959cf106031557105fad2067d6c4435937b3414ce90760167"
+ },
+ "InstalledFiles": [
+ "/usr/bin/c_rehash",
+ "/usr/bin/openssl",
+ "/usr/lib/ssl/misc/CA.pl",
+ "/usr/lib/ssl/misc/tsget.pl",
+ "/usr/share/doc/openssl/HOWTO/certificates.txt.gz",
+ "/usr/share/doc/openssl/HOWTO/documenting-functions-and-macros.md.gz",
+ "/usr/share/doc/openssl/HOWTO/keys.txt.gz",
+ "/usr/share/doc/openssl/NEWS.md.gz",
+ "/usr/share/doc/openssl/README-ENGINES.md.gz",
+ "/usr/share/doc/openssl/README-PROVIDERS.md.gz",
+ "/usr/share/doc/openssl/README-QUIC.md.gz",
+ "/usr/share/doc/openssl/README.Debian",
+ "/usr/share/doc/openssl/README.md.gz",
+ "/usr/share/doc/openssl/changelog.Debian.gz",
+ "/usr/share/doc/openssl/changelog.gz",
+ "/usr/share/doc/openssl/copyright",
+ "/usr/share/doc/openssl/fingerprints.txt",
+ "/usr/share/lintian/overrides/openssl",
+ "/usr/share/man/man1/CA.pl.1ssl.gz",
+ "/usr/share/man/man1/openssl-asn1parse.1ssl.gz",
+ "/usr/share/man/man1/openssl-ca.1ssl.gz",
+ "/usr/share/man/man1/openssl-ciphers.1ssl.gz",
+ "/usr/share/man/man1/openssl-cmds.1ssl.gz",
+ "/usr/share/man/man1/openssl-cmp.1ssl.gz",
+ "/usr/share/man/man1/openssl-cms.1ssl.gz",
+ "/usr/share/man/man1/openssl-crl.1ssl.gz",
+ "/usr/share/man/man1/openssl-crl2pkcs7.1ssl.gz",
+ "/usr/share/man/man1/openssl-dgst.1ssl.gz",
+ "/usr/share/man/man1/openssl-dhparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-dsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-dsaparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-ec.1ssl.gz",
+ "/usr/share/man/man1/openssl-ecparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-enc.1ssl.gz",
+ "/usr/share/man/man1/openssl-engine.1ssl.gz",
+ "/usr/share/man/man1/openssl-errstr.1ssl.gz",
+ "/usr/share/man/man1/openssl-fipsinstall.1ssl.gz",
+ "/usr/share/man/man1/openssl-format-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-gendsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-genpkey.1ssl.gz",
+ "/usr/share/man/man1/openssl-genrsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-info.1ssl.gz",
+ "/usr/share/man/man1/openssl-kdf.1ssl.gz",
+ "/usr/share/man/man1/openssl-list.1ssl.gz",
+ "/usr/share/man/man1/openssl-mac.1ssl.gz",
+ "/usr/share/man/man1/openssl-namedisplay-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-nseq.1ssl.gz",
+ "/usr/share/man/man1/openssl-ocsp.1ssl.gz",
+ "/usr/share/man/man1/openssl-passphrase-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-passwd.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs12.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs7.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkcs8.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkey.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkeyparam.1ssl.gz",
+ "/usr/share/man/man1/openssl-pkeyutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-prime.1ssl.gz",
+ "/usr/share/man/man1/openssl-rand.1ssl.gz",
+ "/usr/share/man/man1/openssl-rehash.1ssl.gz",
+ "/usr/share/man/man1/openssl-req.1ssl.gz",
+ "/usr/share/man/man1/openssl-rsa.1ssl.gz",
+ "/usr/share/man/man1/openssl-rsautl.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_client.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_server.1ssl.gz",
+ "/usr/share/man/man1/openssl-s_time.1ssl.gz",
+ "/usr/share/man/man1/openssl-sess_id.1ssl.gz",
+ "/usr/share/man/man1/openssl-skeyutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-smime.1ssl.gz",
+ "/usr/share/man/man1/openssl-speed.1ssl.gz",
+ "/usr/share/man/man1/openssl-spkac.1ssl.gz",
+ "/usr/share/man/man1/openssl-srp.1ssl.gz",
+ "/usr/share/man/man1/openssl-storeutl.1ssl.gz",
+ "/usr/share/man/man1/openssl-ts.1ssl.gz",
+ "/usr/share/man/man1/openssl-verification-options.1ssl.gz",
+ "/usr/share/man/man1/openssl-verify.1ssl.gz",
+ "/usr/share/man/man1/openssl-version.1ssl.gz",
+ "/usr/share/man/man1/openssl-x509.1ssl.gz",
+ "/usr/share/man/man1/openssl.1ssl.gz",
+ "/usr/share/man/man1/tsget.1ssl.gz",
+ "/usr/share/man/man5/config.5ssl.gz",
+ "/usr/share/man/man5/fips_config.5ssl.gz",
+ "/usr/share/man/man5/x509v3_config.5ssl.gz",
+ "/usr/share/man/man7/EVP_ASYM_CIPHER-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_ASYM_CIPHER-SM2.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-AES.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-ARIA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-BLOWFISH.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CAMELLIA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CAST.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-CHACHA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-DES.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-IDEA.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-NULL.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC2.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC4.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-RC5.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-SEED.7ssl.gz",
+ "/usr/share/man/man7/EVP_CIPHER-SM4.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-ARGON2.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-HKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-HMAC-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-KB.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-KRB5KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PBKDF1.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PBKDF2.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PKCS12KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-PVKKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SCRYPT.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SS.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-SSHKDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-TLS13_KDF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-TLS1_PRF.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X942-ASN1.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X942-CONCAT.7ssl.gz",
+ "/usr/share/man/man7/EVP_KDF-X963.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-EC.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-ML-KEM.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEM-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-DH.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-ECDH.7ssl.gz",
+ "/usr/share/man/man7/EVP_KEYEXCH-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-BLAKE2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-CMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-GMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-KMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-Poly1305.7ssl.gz",
+ "/usr/share/man/man7/EVP_MAC-Siphash.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-BLAKE2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-KECCAK.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD4.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD5-SHA1.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MD5.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-MDC2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-NULL.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-RIPEMD160.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA1.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA2.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHA3.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SHAKE.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-SM3.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-WHIRLPOOL.7ssl.gz",
+ "/usr/share/man/man7/EVP_MD-common.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-DH.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-EC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-FFC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-ML-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-ML-KEM.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-SLH-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-SM2.7ssl.gz",
+ "/usr/share/man/man7/EVP_PKEY-X25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-CRNG-TEST.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-CTR-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-HASH-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-HMAC-DRBG.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-JITTER.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-SEED-SRC.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND-TEST-RAND.7ssl.gz",
+ "/usr/share/man/man7/EVP_RAND.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ECDSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ED25519.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-HMAC.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-ML-DSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-RSA.7ssl.gz",
+ "/usr/share/man/man7/EVP_SIGNATURE-SLH-DSA.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-FIPS.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-base.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-default.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-legacy.7ssl.gz",
+ "/usr/share/man/man7/OSSL_PROVIDER-null.7ssl.gz",
+ "/usr/share/man/man7/OSSL_STORE-winstore.7ssl.gz",
+ "/usr/share/man/man7/RAND.7ssl.gz",
+ "/usr/share/man/man7/RSA-PSS.7ssl.gz",
+ "/usr/share/man/man7/X25519.7ssl.gz",
+ "/usr/share/man/man7/bio.7ssl.gz",
+ "/usr/share/man/man7/ct.7ssl.gz",
+ "/usr/share/man/man7/des_modes.7ssl.gz",
+ "/usr/share/man/man7/evp.7ssl.gz",
+ "/usr/share/man/man7/fips_module.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-cipher.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-digest.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-kdf.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-mac.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-pkey.7ssl.gz",
+ "/usr/share/man/man7/life_cycle-rand.7ssl.gz",
+ "/usr/share/man/man7/openssl-core.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-core_dispatch.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-core_names.h.7ssl.gz",
+ "/usr/share/man/man7/openssl-env.7ssl.gz",
+ "/usr/share/man/man7/openssl-glossary.7ssl.gz",
+ "/usr/share/man/man7/openssl-qlog.7ssl.gz",
+ "/usr/share/man/man7/openssl-quic-concurrency.7ssl.gz",
+ "/usr/share/man/man7/openssl-quic.7ssl.gz",
+ "/usr/share/man/man7/openssl-threads.7ssl.gz",
+ "/usr/share/man/man7/openssl_user_macros.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libcrypto-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libraries-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-libssl-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-migration.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-client-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-client-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-multi-stream.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-server-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-quic-server-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-client-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-client-non-block.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-introduction.7ssl.gz",
+ "/usr/share/man/man7/ossl-guide-tls-server-block.7ssl.gz",
+ "/usr/share/man/man7/ossl_store-file.7ssl.gz",
+ "/usr/share/man/man7/ossl_store.7ssl.gz",
+ "/usr/share/man/man7/passphrase-encoding.7ssl.gz",
+ "/usr/share/man/man7/property.7ssl.gz",
+ "/usr/share/man/man7/provider-asym_cipher.7ssl.gz",
+ "/usr/share/man/man7/provider-base.7ssl.gz",
+ "/usr/share/man/man7/provider-cipher.7ssl.gz",
+ "/usr/share/man/man7/provider-decoder.7ssl.gz",
+ "/usr/share/man/man7/provider-digest.7ssl.gz",
+ "/usr/share/man/man7/provider-encoder.7ssl.gz",
+ "/usr/share/man/man7/provider-kdf.7ssl.gz",
+ "/usr/share/man/man7/provider-kem.7ssl.gz",
+ "/usr/share/man/man7/provider-keyexch.7ssl.gz",
+ "/usr/share/man/man7/provider-keymgmt.7ssl.gz",
+ "/usr/share/man/man7/provider-mac.7ssl.gz",
+ "/usr/share/man/man7/provider-object.7ssl.gz",
+ "/usr/share/man/man7/provider-rand.7ssl.gz",
+ "/usr/share/man/man7/provider-signature.7ssl.gz",
+ "/usr/share/man/man7/provider-skeymgmt.7ssl.gz",
+ "/usr/share/man/man7/provider-storemgmt.7ssl.gz",
+ "/usr/share/man/man7/provider.7ssl.gz",
+ "/usr/share/man/man7/proxy-certificates.7ssl.gz",
+ "/usr/share/man/man7/x509.7ssl.gz"
+ ]
+ },
+ {
+ "ID": "openssl-provider-legacy@3.5.6-1~deb13u2",
+ "Name": "openssl-provider-legacy",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/openssl-provider-legacy@3.5.6-1~deb13u2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "f40d953a73d33d41"
+ },
+ "Version": "3.5.6",
+ "Release": "1~deb13u2",
+ "Arch": "amd64",
+ "SrcName": "openssl",
+ "SrcVersion": "3.5.6",
+ "SrcRelease": "1~deb13u2",
+ "Licenses": [
+ "Apache-2.0",
+ "Artistic-2.0",
+ "GPL-1.0-or-later",
+ "GPL-1.0-only"
+ ],
+ "Maintainer": "Debian OpenSSL Team \u003cpkg-openssl-devel@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libssl3t64@3.5.6-1~deb13u2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/ossl-modules/legacy.so",
+ "/usr/share/doc/openssl-provider-legacy/changelog.Debian.gz",
+ "/usr/share/doc/openssl-provider-legacy/changelog.gz",
+ "/usr/share/doc/openssl-provider-legacy/copyright"
+ ]
+ },
+ {
+ "ID": "passwd@1:4.17.4-2",
+ "Name": "passwd",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/passwd@4.17.4-2?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "5c48c1fc5bd92522"
+ },
+ "Version": "4.17.4",
+ "Release": "2",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "shadow",
+ "SrcVersion": "4.17.4",
+ "SrcRelease": "2",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "BSD-3-Clause",
+ "GPL-1.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Shadow package maintainers \u003cpkg-shadow-devel@lists.alioth.debian.org\u003e",
+ "DependsOn": [
+ "base-passwd@3.6.7",
+ "libacl1@2.3.2-2+b1",
+ "libattr1@1:2.5.2-3",
+ "libaudit1@1:4.0.2-2+b2",
+ "libbsd0@0.12.2-2",
+ "libc6@2.41-12+deb13u3",
+ "libcrypt1@1:4.4.38-1",
+ "libpam-modules@1.7.0-5",
+ "libpam0g@1.7.0-5",
+ "libselinux1@3.8.1-1",
+ "libsemanage2@3.8.1-1",
+ "login.defs@1:4.17.4-2"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/chage",
+ "/usr/bin/chfn",
+ "/usr/bin/chsh",
+ "/usr/bin/expiry",
+ "/usr/bin/gpasswd",
+ "/usr/bin/passwd",
+ "/usr/lib/tmpfiles.d/passwd.conf",
+ "/usr/sbin/chgpasswd",
+ "/usr/sbin/chpasswd",
+ "/usr/sbin/groupadd",
+ "/usr/sbin/groupdel",
+ "/usr/sbin/groupmod",
+ "/usr/sbin/grpck",
+ "/usr/sbin/grpconv",
+ "/usr/sbin/grpunconv",
+ "/usr/sbin/newusers",
+ "/usr/sbin/pwck",
+ "/usr/sbin/pwconv",
+ "/usr/sbin/pwunconv",
+ "/usr/sbin/shadowconfig",
+ "/usr/sbin/useradd",
+ "/usr/sbin/userdel",
+ "/usr/sbin/usermod",
+ "/usr/sbin/vipw",
+ "/usr/share/doc/passwd/NEWS.Debian.gz",
+ "/usr/share/doc/passwd/README.Debian",
+ "/usr/share/doc/passwd/TODO.Debian",
+ "/usr/share/doc/passwd/changelog.Debian.gz",
+ "/usr/share/doc/passwd/changelog.gz",
+ "/usr/share/doc/passwd/copyright",
+ "/usr/share/doc/passwd/examples/passwd.expire.cron",
+ "/usr/share/lintian/overrides/passwd",
+ "/usr/share/locale/bs/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/da/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/de/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/dz/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/el/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/es/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/he/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/id/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/it/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/kk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/km/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ne/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/nn/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sq/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/tl/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/shadow.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/shadow.mo",
+ "/usr/share/man/cs/man1/expiry.1.gz",
+ "/usr/share/man/cs/man1/gpasswd.1.gz",
+ "/usr/share/man/cs/man5/gshadow.5.gz",
+ "/usr/share/man/cs/man5/passwd.5.gz",
+ "/usr/share/man/cs/man5/shadow.5.gz",
+ "/usr/share/man/cs/man8/groupadd.8.gz",
+ "/usr/share/man/cs/man8/groupdel.8.gz",
+ "/usr/share/man/cs/man8/groupmod.8.gz",
+ "/usr/share/man/cs/man8/grpck.8.gz",
+ "/usr/share/man/cs/man8/vipw.8.gz",
+ "/usr/share/man/da/man1/chfn.1.gz",
+ "/usr/share/man/da/man5/gshadow.5.gz",
+ "/usr/share/man/da/man8/groupdel.8.gz",
+ "/usr/share/man/da/man8/vipw.8.gz",
+ "/usr/share/man/de/man1/chage.1.gz",
+ "/usr/share/man/de/man1/chfn.1.gz",
+ "/usr/share/man/de/man1/chsh.1.gz",
+ "/usr/share/man/de/man1/expiry.1.gz",
+ "/usr/share/man/de/man1/gpasswd.1.gz",
+ "/usr/share/man/de/man1/passwd.1.gz",
+ "/usr/share/man/de/man5/gshadow.5.gz",
+ "/usr/share/man/de/man5/passwd.5.gz",
+ "/usr/share/man/de/man5/shadow.5.gz",
+ "/usr/share/man/de/man8/chgpasswd.8.gz",
+ "/usr/share/man/de/man8/chpasswd.8.gz",
+ "/usr/share/man/de/man8/groupadd.8.gz",
+ "/usr/share/man/de/man8/groupdel.8.gz",
+ "/usr/share/man/de/man8/groupmod.8.gz",
+ "/usr/share/man/de/man8/grpck.8.gz",
+ "/usr/share/man/de/man8/newusers.8.gz",
+ "/usr/share/man/de/man8/pwck.8.gz",
+ "/usr/share/man/de/man8/pwconv.8.gz",
+ "/usr/share/man/de/man8/useradd.8.gz",
+ "/usr/share/man/de/man8/userdel.8.gz",
+ "/usr/share/man/de/man8/usermod.8.gz",
+ "/usr/share/man/de/man8/vipw.8.gz",
+ "/usr/share/man/fi/man1/chfn.1.gz",
+ "/usr/share/man/fi/man1/chsh.1.gz",
+ "/usr/share/man/fr/man1/chage.1.gz",
+ "/usr/share/man/fr/man1/chfn.1.gz",
+ "/usr/share/man/fr/man1/chsh.1.gz",
+ "/usr/share/man/fr/man1/expiry.1.gz",
+ "/usr/share/man/fr/man1/gpasswd.1.gz",
+ "/usr/share/man/fr/man1/passwd.1.gz",
+ "/usr/share/man/fr/man5/gshadow.5.gz",
+ "/usr/share/man/fr/man5/passwd.5.gz",
+ "/usr/share/man/fr/man5/shadow.5.gz",
+ "/usr/share/man/fr/man5/subgid.5.gz",
+ "/usr/share/man/fr/man5/subuid.5.gz",
+ "/usr/share/man/fr/man8/chgpasswd.8.gz",
+ "/usr/share/man/fr/man8/chpasswd.8.gz",
+ "/usr/share/man/fr/man8/groupadd.8.gz",
+ "/usr/share/man/fr/man8/groupdel.8.gz",
+ "/usr/share/man/fr/man8/groupmod.8.gz",
+ "/usr/share/man/fr/man8/grpck.8.gz",
+ "/usr/share/man/fr/man8/newusers.8.gz",
+ "/usr/share/man/fr/man8/pwck.8.gz",
+ "/usr/share/man/fr/man8/pwconv.8.gz",
+ "/usr/share/man/fr/man8/useradd.8.gz",
+ "/usr/share/man/fr/man8/userdel.8.gz",
+ "/usr/share/man/fr/man8/usermod.8.gz",
+ "/usr/share/man/fr/man8/vipw.8.gz",
+ "/usr/share/man/hu/man1/chsh.1.gz",
+ "/usr/share/man/hu/man1/gpasswd.1.gz",
+ "/usr/share/man/hu/man1/passwd.1.gz",
+ "/usr/share/man/hu/man5/passwd.5.gz",
+ "/usr/share/man/id/man1/chsh.1.gz",
+ "/usr/share/man/id/man8/useradd.8.gz",
+ "/usr/share/man/it/man1/chage.1.gz",
+ "/usr/share/man/it/man1/chfn.1.gz",
+ "/usr/share/man/it/man1/chsh.1.gz",
+ "/usr/share/man/it/man1/expiry.1.gz",
+ "/usr/share/man/it/man1/gpasswd.1.gz",
+ "/usr/share/man/it/man1/passwd.1.gz",
+ "/usr/share/man/it/man5/gshadow.5.gz",
+ "/usr/share/man/it/man5/passwd.5.gz",
+ "/usr/share/man/it/man5/shadow.5.gz",
+ "/usr/share/man/it/man8/chgpasswd.8.gz",
+ "/usr/share/man/it/man8/chpasswd.8.gz",
+ "/usr/share/man/it/man8/groupadd.8.gz",
+ "/usr/share/man/it/man8/groupdel.8.gz",
+ "/usr/share/man/it/man8/groupmod.8.gz",
+ "/usr/share/man/it/man8/grpck.8.gz",
+ "/usr/share/man/it/man8/newusers.8.gz",
+ "/usr/share/man/it/man8/pwck.8.gz",
+ "/usr/share/man/it/man8/pwconv.8.gz",
+ "/usr/share/man/it/man8/useradd.8.gz",
+ "/usr/share/man/it/man8/userdel.8.gz",
+ "/usr/share/man/it/man8/usermod.8.gz",
+ "/usr/share/man/it/man8/vipw.8.gz",
+ "/usr/share/man/ja/man1/chage.1.gz",
+ "/usr/share/man/ja/man1/chfn.1.gz",
+ "/usr/share/man/ja/man1/chsh.1.gz",
+ "/usr/share/man/ja/man1/expiry.1.gz",
+ "/usr/share/man/ja/man1/gpasswd.1.gz",
+ "/usr/share/man/ja/man1/passwd.1.gz",
+ "/usr/share/man/ja/man5/passwd.5.gz",
+ "/usr/share/man/ja/man5/shadow.5.gz",
+ "/usr/share/man/ja/man8/chpasswd.8.gz",
+ "/usr/share/man/ja/man8/groupadd.8.gz",
+ "/usr/share/man/ja/man8/groupdel.8.gz",
+ "/usr/share/man/ja/man8/groupmod.8.gz",
+ "/usr/share/man/ja/man8/grpck.8.gz",
+ "/usr/share/man/ja/man8/newusers.8.gz",
+ "/usr/share/man/ja/man8/pwck.8.gz",
+ "/usr/share/man/ja/man8/pwconv.8.gz",
+ "/usr/share/man/ja/man8/useradd.8.gz",
+ "/usr/share/man/ja/man8/userdel.8.gz",
+ "/usr/share/man/ja/man8/usermod.8.gz",
+ "/usr/share/man/ja/man8/vipw.8.gz",
+ "/usr/share/man/ko/man1/chfn.1.gz",
+ "/usr/share/man/ko/man1/chsh.1.gz",
+ "/usr/share/man/ko/man5/passwd.5.gz",
+ "/usr/share/man/ko/man8/vipw.8.gz",
+ "/usr/share/man/man1/chage.1.gz",
+ "/usr/share/man/man1/chfn.1.gz",
+ "/usr/share/man/man1/chsh.1.gz",
+ "/usr/share/man/man1/expiry.1.gz",
+ "/usr/share/man/man1/gpasswd.1.gz",
+ "/usr/share/man/man1/passwd.1.gz",
+ "/usr/share/man/man5/gshadow.5.gz",
+ "/usr/share/man/man5/passwd.5.gz",
+ "/usr/share/man/man5/shadow.5.gz",
+ "/usr/share/man/man5/subgid.5.gz",
+ "/usr/share/man/man5/subuid.5.gz",
+ "/usr/share/man/man8/chgpasswd.8.gz",
+ "/usr/share/man/man8/chpasswd.8.gz",
+ "/usr/share/man/man8/groupadd.8.gz",
+ "/usr/share/man/man8/groupdel.8.gz",
+ "/usr/share/man/man8/groupmod.8.gz",
+ "/usr/share/man/man8/grpck.8.gz",
+ "/usr/share/man/man8/newusers.8.gz",
+ "/usr/share/man/man8/pwck.8.gz",
+ "/usr/share/man/man8/pwconv.8.gz",
+ "/usr/share/man/man8/shadowconfig.8.gz",
+ "/usr/share/man/man8/useradd.8.gz",
+ "/usr/share/man/man8/userdel.8.gz",
+ "/usr/share/man/man8/usermod.8.gz",
+ "/usr/share/man/man8/vipw.8.gz",
+ "/usr/share/man/pl/man1/chage.1.gz",
+ "/usr/share/man/pl/man1/chsh.1.gz",
+ "/usr/share/man/pl/man1/expiry.1.gz",
+ "/usr/share/man/pl/man8/groupadd.8.gz",
+ "/usr/share/man/pl/man8/groupdel.8.gz",
+ "/usr/share/man/pl/man8/groupmod.8.gz",
+ "/usr/share/man/pl/man8/grpck.8.gz",
+ "/usr/share/man/pl/man8/userdel.8.gz",
+ "/usr/share/man/pl/man8/usermod.8.gz",
+ "/usr/share/man/pl/man8/vipw.8.gz",
+ "/usr/share/man/pt_BR/man1/gpasswd.1.gz",
+ "/usr/share/man/pt_BR/man5/passwd.5.gz",
+ "/usr/share/man/pt_BR/man5/shadow.5.gz",
+ "/usr/share/man/pt_BR/man8/groupadd.8.gz",
+ "/usr/share/man/pt_BR/man8/groupdel.8.gz",
+ "/usr/share/man/pt_BR/man8/groupmod.8.gz",
+ "/usr/share/man/ru/man1/chage.1.gz",
+ "/usr/share/man/ru/man1/chfn.1.gz",
+ "/usr/share/man/ru/man1/chsh.1.gz",
+ "/usr/share/man/ru/man1/expiry.1.gz",
+ "/usr/share/man/ru/man1/gpasswd.1.gz",
+ "/usr/share/man/ru/man1/passwd.1.gz",
+ "/usr/share/man/ru/man5/gshadow.5.gz",
+ "/usr/share/man/ru/man5/passwd.5.gz",
+ "/usr/share/man/ru/man5/shadow.5.gz",
+ "/usr/share/man/ru/man8/chgpasswd.8.gz",
+ "/usr/share/man/ru/man8/chpasswd.8.gz",
+ "/usr/share/man/ru/man8/groupadd.8.gz",
+ "/usr/share/man/ru/man8/groupdel.8.gz",
+ "/usr/share/man/ru/man8/groupmod.8.gz",
+ "/usr/share/man/ru/man8/grpck.8.gz",
+ "/usr/share/man/ru/man8/newusers.8.gz",
+ "/usr/share/man/ru/man8/pwck.8.gz",
+ "/usr/share/man/ru/man8/pwconv.8.gz",
+ "/usr/share/man/ru/man8/useradd.8.gz",
+ "/usr/share/man/ru/man8/userdel.8.gz",
+ "/usr/share/man/ru/man8/usermod.8.gz",
+ "/usr/share/man/ru/man8/vipw.8.gz",
+ "/usr/share/man/sv/man1/chage.1.gz",
+ "/usr/share/man/sv/man1/chsh.1.gz",
+ "/usr/share/man/sv/man1/expiry.1.gz",
+ "/usr/share/man/sv/man1/passwd.1.gz",
+ "/usr/share/man/sv/man5/gshadow.5.gz",
+ "/usr/share/man/sv/man5/passwd.5.gz",
+ "/usr/share/man/sv/man8/groupadd.8.gz",
+ "/usr/share/man/sv/man8/groupdel.8.gz",
+ "/usr/share/man/sv/man8/groupmod.8.gz",
+ "/usr/share/man/sv/man8/grpck.8.gz",
+ "/usr/share/man/sv/man8/pwck.8.gz",
+ "/usr/share/man/sv/man8/userdel.8.gz",
+ "/usr/share/man/sv/man8/vipw.8.gz",
+ "/usr/share/man/tr/man1/chage.1.gz",
+ "/usr/share/man/tr/man1/chfn.1.gz",
+ "/usr/share/man/tr/man1/passwd.1.gz",
+ "/usr/share/man/tr/man5/passwd.5.gz",
+ "/usr/share/man/tr/man5/shadow.5.gz",
+ "/usr/share/man/tr/man8/groupadd.8.gz",
+ "/usr/share/man/tr/man8/groupdel.8.gz",
+ "/usr/share/man/tr/man8/groupmod.8.gz",
+ "/usr/share/man/tr/man8/useradd.8.gz",
+ "/usr/share/man/tr/man8/userdel.8.gz",
+ "/usr/share/man/tr/man8/usermod.8.gz",
+ "/usr/share/man/uk/man1/chage.1.gz",
+ "/usr/share/man/uk/man1/chfn.1.gz",
+ "/usr/share/man/uk/man1/chsh.1.gz",
+ "/usr/share/man/uk/man1/expiry.1.gz",
+ "/usr/share/man/uk/man1/gpasswd.1.gz",
+ "/usr/share/man/uk/man1/passwd.1.gz",
+ "/usr/share/man/uk/man5/gshadow.5.gz",
+ "/usr/share/man/uk/man5/passwd.5.gz",
+ "/usr/share/man/uk/man5/shadow.5.gz",
+ "/usr/share/man/uk/man8/chgpasswd.8.gz",
+ "/usr/share/man/uk/man8/chpasswd.8.gz",
+ "/usr/share/man/uk/man8/groupadd.8.gz",
+ "/usr/share/man/uk/man8/groupdel.8.gz",
+ "/usr/share/man/uk/man8/groupmod.8.gz",
+ "/usr/share/man/uk/man8/grpck.8.gz",
+ "/usr/share/man/uk/man8/newusers.8.gz",
+ "/usr/share/man/uk/man8/pwck.8.gz",
+ "/usr/share/man/uk/man8/pwconv.8.gz",
+ "/usr/share/man/uk/man8/useradd.8.gz",
+ "/usr/share/man/uk/man8/userdel.8.gz",
+ "/usr/share/man/uk/man8/usermod.8.gz",
+ "/usr/share/man/uk/man8/vipw.8.gz",
+ "/usr/share/man/zh_CN/man1/chage.1.gz",
+ "/usr/share/man/zh_CN/man1/chfn.1.gz",
+ "/usr/share/man/zh_CN/man1/chsh.1.gz",
+ "/usr/share/man/zh_CN/man1/expiry.1.gz",
+ "/usr/share/man/zh_CN/man1/gpasswd.1.gz",
+ "/usr/share/man/zh_CN/man1/passwd.1.gz",
+ "/usr/share/man/zh_CN/man5/gshadow.5.gz",
+ "/usr/share/man/zh_CN/man5/passwd.5.gz",
+ "/usr/share/man/zh_CN/man5/shadow.5.gz",
+ "/usr/share/man/zh_CN/man8/chgpasswd.8.gz",
+ "/usr/share/man/zh_CN/man8/chpasswd.8.gz",
+ "/usr/share/man/zh_CN/man8/groupadd.8.gz",
+ "/usr/share/man/zh_CN/man8/groupdel.8.gz",
+ "/usr/share/man/zh_CN/man8/groupmod.8.gz",
+ "/usr/share/man/zh_CN/man8/grpck.8.gz",
+ "/usr/share/man/zh_CN/man8/newusers.8.gz",
+ "/usr/share/man/zh_CN/man8/pwck.8.gz",
+ "/usr/share/man/zh_CN/man8/pwconv.8.gz",
+ "/usr/share/man/zh_CN/man8/useradd.8.gz",
+ "/usr/share/man/zh_CN/man8/userdel.8.gz",
+ "/usr/share/man/zh_CN/man8/usermod.8.gz",
+ "/usr/share/man/zh_CN/man8/vipw.8.gz",
+ "/usr/share/man/zh_TW/man1/chfn.1.gz",
+ "/usr/share/man/zh_TW/man1/chsh.1.gz",
+ "/usr/share/man/zh_TW/man5/passwd.5.gz",
+ "/usr/share/man/zh_TW/man8/chpasswd.8.gz",
+ "/usr/share/man/zh_TW/man8/groupadd.8.gz",
+ "/usr/share/man/zh_TW/man8/groupdel.8.gz",
+ "/usr/share/man/zh_TW/man8/groupmod.8.gz",
+ "/usr/share/man/zh_TW/man8/useradd.8.gz",
+ "/usr/share/man/zh_TW/man8/userdel.8.gz",
+ "/usr/share/man/zh_TW/man8/usermod.8.gz"
+ ]
+ },
+ {
+ "ID": "pcre@8.32-17.el7",
+ "Name": "pcre",
+ "Identifier": {
+ "PURL": "pkg:rpm/centos/pcre@8.32-17.el7",
+ "UID": "bb3e738eb75d1a13",
+ "BOMRef": "pkg:rpm/centos/pcre@8.32-17.el7#13c83851f49804fee35d2a5d04c7c9838574be59111e142a6f19d928b13e7f72"
+ },
+ "Version": "8.32",
+ "Release": "17.el7",
+ "SrcName": "pcre",
+ "SrcVersion": "8.32",
+ "SrcRelease": "17.el7",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "perl-base@5.40.1-6",
+ "Name": "perl-base",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/perl-base@5.40.1-6?arch=amd64\u0026distro=debian-13.6",
+ "UID": "17f06da2c02a11c6"
+ },
+ "Version": "5.40.1",
+ "Release": "6",
+ "Arch": "amd64",
+ "SrcName": "perl",
+ "SrcVersion": "5.40.1",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-1.0-or-later",
+ "Artistic-2.0",
+ "MIT",
+ "REGCOMP",
+ "GPL-2.0-with-bison-exception+",
+ "Unicode",
+ "BZIP",
+ "Zlib",
+ "GPL-2.0-or-later",
+ "FSFAP",
+ "BSD-3-clause-with-weird-numbering",
+ "CC0-1.0",
+ "TEXT-TABS",
+ "BSD-4-clause-POWERDOG",
+ "BSD-3-clause-GENERIC",
+ "BSD-3-Clause",
+ "SDBM-PUBLIC-DOMAIN",
+ "DONT-CHANGE-THE-GPL",
+ "Artistic-dist",
+ "LGPL-2.1-only",
+ "GPL-1.0-only",
+ "GPL-2.0-only",
+ "Artistic-2"
+ ],
+ "Maintainer": "Niko Tyni \u003cntyni@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/perl",
+ "/usr/bin/perl5.40.1",
+ "/usr/lib/x86_64-linux-gnu/perl-base/AutoLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Carp.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Carp/Heavy.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config_git.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Config_heavy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Cwd.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/DynaLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Errno.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Exporter.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Exporter/Heavy.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Fcntl.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Basename.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Glob.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Path.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Spec.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Spec/Unix.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/File/Temp.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/FileHandle.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Getopt/Long.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Getopt/Long/Parser.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Hash/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/File.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Handle.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Pipe.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Seekable.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/INET.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/IP.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/UNIX.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IPC/Open2.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/IPC/Open3.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/List/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/POSIX.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Scalar/Util.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/SelectSaver.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Socket.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Symbol.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/ParseWords.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/Tabs.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Text/Wrap.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/Tie/Hash.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/XSLoader.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/attributes.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Cwd/Cwd.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Fcntl/Fcntl.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/File/Glob/Glob.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Hash/Util/Util.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/IO/IO.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/List/Util/Util.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/POSIX/POSIX.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/Socket/Socket.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/attributes/attributes.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/auto/re/re.so",
+ "/usr/lib/x86_64-linux-gnu/perl-base/base.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/builtin.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/bytes.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/constant.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/feature.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/fields.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/integer.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/lib.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/locale.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/overload.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/overloading.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/parent.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/re.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/strict.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Age.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bmg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Cf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Ea.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/EqUIdeo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/GCB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Gc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Hst.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Identif2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Identifi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InPC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InSC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Isc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFCQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFDQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCCF.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKDQC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Na1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NameAlia.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nv.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/PerlDeci.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/SB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Sc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Scx.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Tc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Uc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Vo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/WB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlLB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlSCX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V100.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V11.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V110.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V120.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V130.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V140.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V150.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V20.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V30.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V31.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V32.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V40.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V41.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V50.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V51.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V52.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V60.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V61.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V70.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V80.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V90.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Alpha/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/B.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/BN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/CS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/EN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ES.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ET.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/NSM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ON.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/WS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Blk/NB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/O.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CE/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CI/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCF/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWKCF/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWL/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWT/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWU/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Cased/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/A.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/AR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/ATAR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/B.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/BR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/DB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NK.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/OV.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/VR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CompEx/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/DI/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dash/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dep/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dia/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Com.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Enc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Fin.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Font.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Init.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Iso.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Med.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nar.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/NonCanon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sqr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sub.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sup.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Vert.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EBase/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EComp/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/EPres/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/A.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/H.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/Na.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/W.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Emoji/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ext/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/ExtPict/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/CN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LV.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LVT.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/PP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/SM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/LC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ll.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/M.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Me.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/No.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/P.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pe.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Po.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ps.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/S.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sk.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/So.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Z.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Zs.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrBase/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrExt/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hex/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hst/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hyphen/T.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdStatus/Allowed.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdStatus/Restrict.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/DefaultI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Exclusio.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Inclusio.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/LimitedU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotChara.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotNFKC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/NotXID.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Obsolete.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Recommen.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Technica.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IdType/Uncommon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ideo/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/10_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/11_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/12_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/12_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/13_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/14_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/15_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/7_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/8_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/9_0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Bottom.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/BottomAn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Left.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/LeftAndR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/NA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Overstru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Right.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Top.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndBo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndL2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndLe.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndRi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/VisualOr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Avagraha.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Bindu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Cantilla.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona5.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona7.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona9.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consonan.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Geminati.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Invisibl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Nukta.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Number.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Other.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/PureKill.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Syllable.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/ToneMark.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Virama.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Visarga.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Vowel.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelDep.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelInd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Ain.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Alef.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Beh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Dal.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/FarsiYeh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Feh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Gaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Hah.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/HanifiRo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Kaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Lam.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/NoJoinin.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Noon.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Qaf.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Reh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Sad.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Seen.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Tah.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Waw.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Yeh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/C.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/D.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/L.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/T.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/U.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CJ.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CM.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/GL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/ID.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/NS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/OP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PR.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/QU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/SA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lower/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Math/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/M.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/N.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Di.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/None.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Nu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/0.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/100.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/100000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/11.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/12.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/13.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/14.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/15.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/17.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/18.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/19.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/20.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/200.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/20000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2_3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/30.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/300.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/30000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3_16.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3_4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/4.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/40.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/400.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/4000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/40000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/500.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/6.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/60.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/600.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/6000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/60000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/7.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/70.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/700.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/7000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/70000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/8.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/80.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/800.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/8000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/80000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/9.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/90.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/900.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/9000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/90000.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PCM/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PatSyn/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Alnum.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Assigned.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Blank.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Graph.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PerlWord.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PosixPun.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Print.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/SpacePer.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Title.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Word.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/XPosixPu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlAny.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCh2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCha.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlFol.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDS.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIsI.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlNch.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPat.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPr2.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPro.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlQuo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/QMark/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/AT.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/CL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/FO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LE.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/SC.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/ST.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/Sp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/UP.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SD/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/STerm/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Arab.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Beng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cprt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cyrl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Deva.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Dupl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Geor.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Glag.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gonm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gran.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Grek.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gujr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Guru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Han.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hira.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Kana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Knda.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Latn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Limb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Linb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mlym.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mult.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Orya.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Sinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Syrc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Taml.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Telu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zyyy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Adlm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Arab.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Armn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Beng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Bhks.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Bopo.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cakm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cham.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Copt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cprt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cyrl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Deva.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Diak.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Dupl.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Ethi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Geor.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Glag.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gonm.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gran.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Grek.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gujr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Guru.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Han.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hebr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hira.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hmng.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hmnp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Kana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khar.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khmr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Khoj.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Knda.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Kthi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lana.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lao.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Latn.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Limb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Lina.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Linb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mlym.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mong.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mult.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mymr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Nand.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Nko.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Orya.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Phlp.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Rohg.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Shrd.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sind.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Syrc.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tagb.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Takr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Talu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Taml.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tang.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Telu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Thaa.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tibt.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tirh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Vith.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Xsux.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Yezi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Yi.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zinh.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zyyy.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zzzz.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Term/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/UIdeo/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Upper/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/VS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/R.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/Tr.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/Tu.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Vo/U.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/EX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/Extend.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/FO.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/HL.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/KA.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/LE.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MB.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/ML.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MN.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/NU.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/WSegSpac.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/XX.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDC/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDS/Y.pl",
+ "/usr/lib/x86_64-linux-gnu/perl-base/utf8.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/vars.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/warnings.pm",
+ "/usr/lib/x86_64-linux-gnu/perl-base/warnings/register.pm",
+ "/usr/share/doc/perl-base/changelog.Debian.gz",
+ "/usr/share/doc/perl-base/changelog.gz",
+ "/usr/share/doc/perl-base/copyright",
+ "/usr/share/doc/perl/AUTHORS.gz",
+ "/usr/share/doc/perl/Documentation",
+ "/usr/share/lintian/overrides/perl-base",
+ "/usr/share/man/man1/perl.1.gz"
+ ]
+ },
+ {
+ "ID": "readline-common@8.2-6",
+ "Name": "readline-common",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/readline-common@8.2-6?arch=all\u0026distro=debian-13.6",
+ "UID": "7f5f4bcfd1669a46"
+ },
+ "Version": "8.2",
+ "Release": "6",
+ "Arch": "all",
+ "SrcName": "readline",
+ "SrcVersion": "8.2",
+ "SrcRelease": "6",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-or-later",
+ "ISC-no-attribution"
+ ],
+ "Maintainer": "Matthias Klose \u003cdoko@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/readline-common/changelog.Debian.gz",
+ "/usr/share/doc/readline-common/changelog.gz",
+ "/usr/share/doc/readline-common/copyright",
+ "/usr/share/doc/readline-common/inputrc.arrows",
+ "/usr/share/info/rluserman.info.gz",
+ "/usr/share/lintian/overrides/readline-common",
+ "/usr/share/man/man3/history.3readline.gz",
+ "/usr/share/man/man3/readline.3readline.gz",
+ "/usr/share/readline/inputrc"
+ ]
+ },
+ {
+ "ID": "sed@4.9-2+deb13u1",
+ "Name": "sed",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sed@4.9-2%2Bdeb13u1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "d9e2231b96ca2bda"
+ },
+ "Version": "4.9",
+ "Release": "2+deb13u1",
+ "Arch": "amd64",
+ "SrcName": "sed",
+ "SrcVersion": "4.9",
+ "SrcRelease": "2+deb13u1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "X11",
+ "GFDL-1.3-no-invariants-or-later",
+ "GFDL-1.3-only",
+ "ISC",
+ "BSD-4-Clause-UC",
+ "BSL-1",
+ "pcre"
+ ],
+ "Maintainer": "Clint Adams \u003cclint@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/sed",
+ "/usr/share/doc/sed/AUTHORS",
+ "/usr/share/doc/sed/BUGS.gz",
+ "/usr/share/doc/sed/NEWS.gz",
+ "/usr/share/doc/sed/README",
+ "/usr/share/doc/sed/THANKS.gz",
+ "/usr/share/doc/sed/changelog.Debian.gz",
+ "/usr/share/doc/sed/changelog.gz",
+ "/usr/share/doc/sed/copyright",
+ "/usr/share/doc/sed/examples/dc.sed",
+ "/usr/share/doc/sed/sedfaq.txt.gz",
+ "/usr/share/info/sed.info.gz",
+ "/usr/share/locale/af/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ast/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/bg/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/da/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/de/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/el/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/es/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/et/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/he/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/id/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/it/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/sed.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/sed.mo",
+ "/usr/share/man/man1/sed.1.gz"
+ ]
+ },
+ {
+ "ID": "sqv@1.3.0-3+b2",
+ "Name": "sqv",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sqv@1.3.0-3%2Bb2?arch=amd64\u0026distro=debian-13.6",
+ "UID": "82c65dd56fbcfd0e"
+ },
+ "Version": "1.3.0",
+ "Release": "3+b2",
+ "Arch": "amd64",
+ "SrcName": "rust-sequoia-sqv",
+ "SrcVersion": "1.3.0",
+ "SrcRelease": "3",
+ "Licenses": [
+ "LGPL-2.0-or-later",
+ "LGPL-2.0-only"
+ ],
+ "Maintainer": "Debian Rust Maintainers \u003cpkg-rust-maintainers@alioth-lists.debian.net\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3",
+ "libgcc-s1@14.2.0-19",
+ "libgmp10@2:6.3.0+dfsg-3",
+ "libhogweed6t64@3.10.1-1",
+ "libnettle8t64@3.10.1-1"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/sqv",
+ "/usr/share/bash-completion/completions/sqv.bash",
+ "/usr/share/doc/sqv/NEWS.gz",
+ "/usr/share/doc/sqv/changelog.Debian.amd64.gz",
+ "/usr/share/doc/sqv/changelog.Debian.gz",
+ "/usr/share/doc/sqv/copyright",
+ "/usr/share/fish/completions/sqv.fish",
+ "/usr/share/man/man1/sqv.1.gz",
+ "/usr/share/zsh/vendor-completions/_sqv"
+ ]
+ },
+ {
+ "ID": "sysvinit-utils@3.14-4",
+ "Name": "sysvinit-utils",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/sysvinit-utils@3.14-4?arch=amd64\u0026distro=debian-13.6",
+ "UID": "8699daa05d734d69"
+ },
+ "Version": "3.14",
+ "Release": "4",
+ "Arch": "amd64",
+ "SrcName": "sysvinit",
+ "SrcVersion": "3.14",
+ "SrcRelease": "4",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "LGPL-2.1-or-later",
+ "GPL-3.0-only",
+ "GPL-2.0-only",
+ "LGPL-2.1-only"
+ ],
+ "Maintainer": "Debian sysvinit maintainers \u003cdebian-init-diversity@chiark.greenend.org.uk\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/init/init-d-script",
+ "/usr/lib/init/vars.sh",
+ "/usr/lib/lsb/init-functions",
+ "/usr/lib/lsb/init-functions.d/00-verbose",
+ "/usr/sbin/fstab-decode",
+ "/usr/sbin/killall5",
+ "/usr/share/doc/sysvinit-utils/changelog.Debian.gz",
+ "/usr/share/doc/sysvinit-utils/copyright",
+ "/usr/share/man/man5/init-d-script.5.gz",
+ "/usr/share/man/man8/fstab-decode.8.gz",
+ "/usr/share/man/man8/killall5.8.gz",
+ "/usr/share/man/man8/pidof.8.gz"
+ ]
+ },
+ {
+ "ID": "tar@1.35+dfsg-3.1",
+ "Name": "tar",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/tar@1.35%2Bdfsg-3.1?arch=amd64\u0026distro=debian-13.6",
+ "UID": "50aee76d081ea925"
+ },
+ "Version": "1.35+dfsg",
+ "Release": "3.1",
+ "Arch": "amd64",
+ "SrcName": "tar",
+ "SrcVersion": "1.35+dfsg",
+ "SrcRelease": "3.1",
+ "Licenses": [
+ "GPL-3.0-or-later",
+ "GPL-3.0-only",
+ "GPL-3+ with Bison exception",
+ "LGPL-2.1-or-later",
+ "LGPL-2.1-only",
+ "LGPL-3.0-or-later",
+ "LGPL-3.0-only",
+ "GPL-2.0-or-later",
+ "GPL-2.0-only"
+ ],
+ "Maintainer": "Janos Lenart \u003cocsi@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/tar",
+ "/usr/lib/mime/packages/tar",
+ "/usr/sbin/rmt-tar",
+ "/usr/sbin/tarcat",
+ "/usr/share/doc/tar/AUTHORS",
+ "/usr/share/doc/tar/NEWS.gz",
+ "/usr/share/doc/tar/README.Debian",
+ "/usr/share/doc/tar/THANKS.gz",
+ "/usr/share/doc/tar/changelog.1.gz",
+ "/usr/share/doc/tar/changelog.Debian.gz",
+ "/usr/share/doc/tar/changelog.gz",
+ "/usr/share/doc/tar/copyright",
+ "/usr/share/locale/bg/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ca/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/cs/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/da/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/de/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/el/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/eo/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/es/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/et/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/eu/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/fi/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/fr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ga/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/gl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/hr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/hu/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/id/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/it/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ja/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ka/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ko/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ky/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ms/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/nb/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/nl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pt/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/pt_BR/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ro/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/ru/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sk/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sl/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/sv/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/tr/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/uk/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/vi/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/zh_CN/LC_MESSAGES/tar.mo",
+ "/usr/share/locale/zh_TW/LC_MESSAGES/tar.mo",
+ "/usr/share/man/man1/tar.1.gz",
+ "/usr/share/man/man1/tarcat.1.gz",
+ "/usr/share/man/man8/rmt-tar.8.gz"
+ ]
+ },
+ {
+ "ID": "tzdata@2026b-0+deb13u1",
+ "Name": "tzdata",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/tzdata@2026b-0%2Bdeb13u1?arch=all\u0026distro=debian-13.6",
+ "UID": "6698e2883de2f799"
+ },
+ "Version": "2026b",
+ "Release": "0+deb13u1",
+ "Arch": "all",
+ "SrcName": "tzdata",
+ "SrcVersion": "2026b",
+ "SrcRelease": "0+deb13u1",
+ "Licenses": [
+ "public-domain"
+ ],
+ "Maintainer": "GNU Libc Maintainers \u003cdebian-glibc@lists.debian.org\u003e",
+ "DependsOn": [
+ "debconf@1.5.91"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/share/doc/tzdata/NEWS.Debian.gz",
+ "/usr/share/doc/tzdata/README.Debian",
+ "/usr/share/doc/tzdata/changelog.Debian.gz",
+ "/usr/share/doc/tzdata/changelog.gz",
+ "/usr/share/doc/tzdata/copyright",
+ "/usr/share/lintian/overrides/tzdata",
+ "/usr/share/zoneinfo/Africa/Abidjan",
+ "/usr/share/zoneinfo/Africa/Accra",
+ "/usr/share/zoneinfo/Africa/Addis_Ababa",
+ "/usr/share/zoneinfo/Africa/Algiers",
+ "/usr/share/zoneinfo/Africa/Asmara",
+ "/usr/share/zoneinfo/Africa/Bamako",
+ "/usr/share/zoneinfo/Africa/Bangui",
+ "/usr/share/zoneinfo/Africa/Banjul",
+ "/usr/share/zoneinfo/Africa/Bissau",
+ "/usr/share/zoneinfo/Africa/Blantyre",
+ "/usr/share/zoneinfo/Africa/Brazzaville",
+ "/usr/share/zoneinfo/Africa/Bujumbura",
+ "/usr/share/zoneinfo/Africa/Cairo",
+ "/usr/share/zoneinfo/Africa/Casablanca",
+ "/usr/share/zoneinfo/Africa/Ceuta",
+ "/usr/share/zoneinfo/Africa/Conakry",
+ "/usr/share/zoneinfo/Africa/Dakar",
+ "/usr/share/zoneinfo/Africa/Dar_es_Salaam",
+ "/usr/share/zoneinfo/Africa/Djibouti",
+ "/usr/share/zoneinfo/Africa/Douala",
+ "/usr/share/zoneinfo/Africa/El_Aaiun",
+ "/usr/share/zoneinfo/Africa/Freetown",
+ "/usr/share/zoneinfo/Africa/Gaborone",
+ "/usr/share/zoneinfo/Africa/Harare",
+ "/usr/share/zoneinfo/Africa/Johannesburg",
+ "/usr/share/zoneinfo/Africa/Juba",
+ "/usr/share/zoneinfo/Africa/Kampala",
+ "/usr/share/zoneinfo/Africa/Khartoum",
+ "/usr/share/zoneinfo/Africa/Kigali",
+ "/usr/share/zoneinfo/Africa/Kinshasa",
+ "/usr/share/zoneinfo/Africa/Lagos",
+ "/usr/share/zoneinfo/Africa/Libreville",
+ "/usr/share/zoneinfo/Africa/Lome",
+ "/usr/share/zoneinfo/Africa/Luanda",
+ "/usr/share/zoneinfo/Africa/Lubumbashi",
+ "/usr/share/zoneinfo/Africa/Lusaka",
+ "/usr/share/zoneinfo/Africa/Malabo",
+ "/usr/share/zoneinfo/Africa/Maputo",
+ "/usr/share/zoneinfo/Africa/Maseru",
+ "/usr/share/zoneinfo/Africa/Mbabane",
+ "/usr/share/zoneinfo/Africa/Mogadishu",
+ "/usr/share/zoneinfo/Africa/Monrovia",
+ "/usr/share/zoneinfo/Africa/Nairobi",
+ "/usr/share/zoneinfo/Africa/Ndjamena",
+ "/usr/share/zoneinfo/Africa/Niamey",
+ "/usr/share/zoneinfo/Africa/Nouakchott",
+ "/usr/share/zoneinfo/Africa/Ouagadougou",
+ "/usr/share/zoneinfo/Africa/Porto-Novo",
+ "/usr/share/zoneinfo/Africa/Sao_Tome",
+ "/usr/share/zoneinfo/Africa/Tripoli",
+ "/usr/share/zoneinfo/Africa/Tunis",
+ "/usr/share/zoneinfo/Africa/Windhoek",
+ "/usr/share/zoneinfo/America/Adak",
+ "/usr/share/zoneinfo/America/Anchorage",
+ "/usr/share/zoneinfo/America/Anguilla",
+ "/usr/share/zoneinfo/America/Antigua",
+ "/usr/share/zoneinfo/America/Araguaina",
+ "/usr/share/zoneinfo/America/Argentina/Buenos_Aires",
+ "/usr/share/zoneinfo/America/Argentina/Catamarca",
+ "/usr/share/zoneinfo/America/Argentina/Cordoba",
+ "/usr/share/zoneinfo/America/Argentina/Jujuy",
+ "/usr/share/zoneinfo/America/Argentina/La_Rioja",
+ "/usr/share/zoneinfo/America/Argentina/Mendoza",
+ "/usr/share/zoneinfo/America/Argentina/Rio_Gallegos",
+ "/usr/share/zoneinfo/America/Argentina/Salta",
+ "/usr/share/zoneinfo/America/Argentina/San_Juan",
+ "/usr/share/zoneinfo/America/Argentina/San_Luis",
+ "/usr/share/zoneinfo/America/Argentina/Tucuman",
+ "/usr/share/zoneinfo/America/Argentina/Ushuaia",
+ "/usr/share/zoneinfo/America/Aruba",
+ "/usr/share/zoneinfo/America/Asuncion",
+ "/usr/share/zoneinfo/America/Atikokan",
+ "/usr/share/zoneinfo/America/Bahia",
+ "/usr/share/zoneinfo/America/Bahia_Banderas",
+ "/usr/share/zoneinfo/America/Barbados",
+ "/usr/share/zoneinfo/America/Belem",
+ "/usr/share/zoneinfo/America/Belize",
+ "/usr/share/zoneinfo/America/Blanc-Sablon",
+ "/usr/share/zoneinfo/America/Boa_Vista",
+ "/usr/share/zoneinfo/America/Bogota",
+ "/usr/share/zoneinfo/America/Boise",
+ "/usr/share/zoneinfo/America/Cambridge_Bay",
+ "/usr/share/zoneinfo/America/Campo_Grande",
+ "/usr/share/zoneinfo/America/Cancun",
+ "/usr/share/zoneinfo/America/Caracas",
+ "/usr/share/zoneinfo/America/Cayenne",
+ "/usr/share/zoneinfo/America/Cayman",
+ "/usr/share/zoneinfo/America/Chicago",
+ "/usr/share/zoneinfo/America/Chihuahua",
+ "/usr/share/zoneinfo/America/Ciudad_Juarez",
+ "/usr/share/zoneinfo/America/Costa_Rica",
+ "/usr/share/zoneinfo/America/Coyhaique",
+ "/usr/share/zoneinfo/America/Creston",
+ "/usr/share/zoneinfo/America/Cuiaba",
+ "/usr/share/zoneinfo/America/Curacao",
+ "/usr/share/zoneinfo/America/Danmarkshavn",
+ "/usr/share/zoneinfo/America/Dawson",
+ "/usr/share/zoneinfo/America/Dawson_Creek",
+ "/usr/share/zoneinfo/America/Denver",
+ "/usr/share/zoneinfo/America/Detroit",
+ "/usr/share/zoneinfo/America/Dominica",
+ "/usr/share/zoneinfo/America/Edmonton",
+ "/usr/share/zoneinfo/America/Eirunepe",
+ "/usr/share/zoneinfo/America/El_Salvador",
+ "/usr/share/zoneinfo/America/Fort_Nelson",
+ "/usr/share/zoneinfo/America/Fortaleza",
+ "/usr/share/zoneinfo/America/Glace_Bay",
+ "/usr/share/zoneinfo/America/Goose_Bay",
+ "/usr/share/zoneinfo/America/Grand_Turk",
+ "/usr/share/zoneinfo/America/Grenada",
+ "/usr/share/zoneinfo/America/Guadeloupe",
+ "/usr/share/zoneinfo/America/Guatemala",
+ "/usr/share/zoneinfo/America/Guayaquil",
+ "/usr/share/zoneinfo/America/Guyana",
+ "/usr/share/zoneinfo/America/Halifax",
+ "/usr/share/zoneinfo/America/Havana",
+ "/usr/share/zoneinfo/America/Hermosillo",
+ "/usr/share/zoneinfo/America/Indiana/Indianapolis",
+ "/usr/share/zoneinfo/America/Indiana/Knox",
+ "/usr/share/zoneinfo/America/Indiana/Marengo",
+ "/usr/share/zoneinfo/America/Indiana/Petersburg",
+ "/usr/share/zoneinfo/America/Indiana/Tell_City",
+ "/usr/share/zoneinfo/America/Indiana/Vevay",
+ "/usr/share/zoneinfo/America/Indiana/Vincennes",
+ "/usr/share/zoneinfo/America/Indiana/Winamac",
+ "/usr/share/zoneinfo/America/Inuvik",
+ "/usr/share/zoneinfo/America/Iqaluit",
+ "/usr/share/zoneinfo/America/Jamaica",
+ "/usr/share/zoneinfo/America/Juneau",
+ "/usr/share/zoneinfo/America/Kentucky/Louisville",
+ "/usr/share/zoneinfo/America/Kentucky/Monticello",
+ "/usr/share/zoneinfo/America/La_Paz",
+ "/usr/share/zoneinfo/America/Lima",
+ "/usr/share/zoneinfo/America/Los_Angeles",
+ "/usr/share/zoneinfo/America/Maceio",
+ "/usr/share/zoneinfo/America/Managua",
+ "/usr/share/zoneinfo/America/Manaus",
+ "/usr/share/zoneinfo/America/Martinique",
+ "/usr/share/zoneinfo/America/Matamoros",
+ "/usr/share/zoneinfo/America/Mazatlan",
+ "/usr/share/zoneinfo/America/Menominee",
+ "/usr/share/zoneinfo/America/Merida",
+ "/usr/share/zoneinfo/America/Metlakatla",
+ "/usr/share/zoneinfo/America/Mexico_City",
+ "/usr/share/zoneinfo/America/Miquelon",
+ "/usr/share/zoneinfo/America/Moncton",
+ "/usr/share/zoneinfo/America/Monterrey",
+ "/usr/share/zoneinfo/America/Montevideo",
+ "/usr/share/zoneinfo/America/Montserrat",
+ "/usr/share/zoneinfo/America/Nassau",
+ "/usr/share/zoneinfo/America/New_York",
+ "/usr/share/zoneinfo/America/Nome",
+ "/usr/share/zoneinfo/America/Noronha",
+ "/usr/share/zoneinfo/America/North_Dakota/Beulah",
+ "/usr/share/zoneinfo/America/North_Dakota/Center",
+ "/usr/share/zoneinfo/America/North_Dakota/New_Salem",
+ "/usr/share/zoneinfo/America/Nuuk",
+ "/usr/share/zoneinfo/America/Ojinaga",
+ "/usr/share/zoneinfo/America/Panama",
+ "/usr/share/zoneinfo/America/Paramaribo",
+ "/usr/share/zoneinfo/America/Phoenix",
+ "/usr/share/zoneinfo/America/Port-au-Prince",
+ "/usr/share/zoneinfo/America/Port_of_Spain",
+ "/usr/share/zoneinfo/America/Porto_Velho",
+ "/usr/share/zoneinfo/America/Puerto_Rico",
+ "/usr/share/zoneinfo/America/Punta_Arenas",
+ "/usr/share/zoneinfo/America/Rankin_Inlet",
+ "/usr/share/zoneinfo/America/Recife",
+ "/usr/share/zoneinfo/America/Regina",
+ "/usr/share/zoneinfo/America/Resolute",
+ "/usr/share/zoneinfo/America/Rio_Branco",
+ "/usr/share/zoneinfo/America/Santarem",
+ "/usr/share/zoneinfo/America/Santiago",
+ "/usr/share/zoneinfo/America/Santo_Domingo",
+ "/usr/share/zoneinfo/America/Sao_Paulo",
+ "/usr/share/zoneinfo/America/Scoresbysund",
+ "/usr/share/zoneinfo/America/Sitka",
+ "/usr/share/zoneinfo/America/St_Johns",
+ "/usr/share/zoneinfo/America/St_Kitts",
+ "/usr/share/zoneinfo/America/St_Lucia",
+ "/usr/share/zoneinfo/America/St_Thomas",
+ "/usr/share/zoneinfo/America/St_Vincent",
+ "/usr/share/zoneinfo/America/Swift_Current",
+ "/usr/share/zoneinfo/America/Tegucigalpa",
+ "/usr/share/zoneinfo/America/Thule",
+ "/usr/share/zoneinfo/America/Tijuana",
+ "/usr/share/zoneinfo/America/Toronto",
+ "/usr/share/zoneinfo/America/Tortola",
+ "/usr/share/zoneinfo/America/Vancouver",
+ "/usr/share/zoneinfo/America/Whitehorse",
+ "/usr/share/zoneinfo/America/Winnipeg",
+ "/usr/share/zoneinfo/America/Yakutat",
+ "/usr/share/zoneinfo/Antarctica/Casey",
+ "/usr/share/zoneinfo/Antarctica/Davis",
+ "/usr/share/zoneinfo/Antarctica/DumontDUrville",
+ "/usr/share/zoneinfo/Antarctica/Macquarie",
+ "/usr/share/zoneinfo/Antarctica/Mawson",
+ "/usr/share/zoneinfo/Antarctica/McMurdo",
+ "/usr/share/zoneinfo/Antarctica/Palmer",
+ "/usr/share/zoneinfo/Antarctica/Rothera",
+ "/usr/share/zoneinfo/Antarctica/Syowa",
+ "/usr/share/zoneinfo/Antarctica/Troll",
+ "/usr/share/zoneinfo/Antarctica/Vostok",
+ "/usr/share/zoneinfo/Asia/Aden",
+ "/usr/share/zoneinfo/Asia/Almaty",
+ "/usr/share/zoneinfo/Asia/Amman",
+ "/usr/share/zoneinfo/Asia/Anadyr",
+ "/usr/share/zoneinfo/Asia/Aqtau",
+ "/usr/share/zoneinfo/Asia/Aqtobe",
+ "/usr/share/zoneinfo/Asia/Ashgabat",
+ "/usr/share/zoneinfo/Asia/Atyrau",
+ "/usr/share/zoneinfo/Asia/Baghdad",
+ "/usr/share/zoneinfo/Asia/Bahrain",
+ "/usr/share/zoneinfo/Asia/Baku",
+ "/usr/share/zoneinfo/Asia/Bangkok",
+ "/usr/share/zoneinfo/Asia/Barnaul",
+ "/usr/share/zoneinfo/Asia/Beirut",
+ "/usr/share/zoneinfo/Asia/Bishkek",
+ "/usr/share/zoneinfo/Asia/Brunei",
+ "/usr/share/zoneinfo/Asia/Chita",
+ "/usr/share/zoneinfo/Asia/Colombo",
+ "/usr/share/zoneinfo/Asia/Damascus",
+ "/usr/share/zoneinfo/Asia/Dhaka",
+ "/usr/share/zoneinfo/Asia/Dili",
+ "/usr/share/zoneinfo/Asia/Dubai",
+ "/usr/share/zoneinfo/Asia/Dushanbe",
+ "/usr/share/zoneinfo/Asia/Famagusta",
+ "/usr/share/zoneinfo/Asia/Gaza",
+ "/usr/share/zoneinfo/Asia/Hebron",
+ "/usr/share/zoneinfo/Asia/Ho_Chi_Minh",
+ "/usr/share/zoneinfo/Asia/Hong_Kong",
+ "/usr/share/zoneinfo/Asia/Hovd",
+ "/usr/share/zoneinfo/Asia/Irkutsk",
+ "/usr/share/zoneinfo/Asia/Jakarta",
+ "/usr/share/zoneinfo/Asia/Jayapura",
+ "/usr/share/zoneinfo/Asia/Jerusalem",
+ "/usr/share/zoneinfo/Asia/Kabul",
+ "/usr/share/zoneinfo/Asia/Kamchatka",
+ "/usr/share/zoneinfo/Asia/Karachi",
+ "/usr/share/zoneinfo/Asia/Kathmandu",
+ "/usr/share/zoneinfo/Asia/Khandyga",
+ "/usr/share/zoneinfo/Asia/Kolkata",
+ "/usr/share/zoneinfo/Asia/Krasnoyarsk",
+ "/usr/share/zoneinfo/Asia/Kuala_Lumpur",
+ "/usr/share/zoneinfo/Asia/Kuching",
+ "/usr/share/zoneinfo/Asia/Kuwait",
+ "/usr/share/zoneinfo/Asia/Macau",
+ "/usr/share/zoneinfo/Asia/Magadan",
+ "/usr/share/zoneinfo/Asia/Makassar",
+ "/usr/share/zoneinfo/Asia/Manila",
+ "/usr/share/zoneinfo/Asia/Muscat",
+ "/usr/share/zoneinfo/Asia/Nicosia",
+ "/usr/share/zoneinfo/Asia/Novokuznetsk",
+ "/usr/share/zoneinfo/Asia/Novosibirsk",
+ "/usr/share/zoneinfo/Asia/Omsk",
+ "/usr/share/zoneinfo/Asia/Oral",
+ "/usr/share/zoneinfo/Asia/Phnom_Penh",
+ "/usr/share/zoneinfo/Asia/Pontianak",
+ "/usr/share/zoneinfo/Asia/Pyongyang",
+ "/usr/share/zoneinfo/Asia/Qatar",
+ "/usr/share/zoneinfo/Asia/Qostanay",
+ "/usr/share/zoneinfo/Asia/Qyzylorda",
+ "/usr/share/zoneinfo/Asia/Riyadh",
+ "/usr/share/zoneinfo/Asia/Sakhalin",
+ "/usr/share/zoneinfo/Asia/Samarkand",
+ "/usr/share/zoneinfo/Asia/Seoul",
+ "/usr/share/zoneinfo/Asia/Shanghai",
+ "/usr/share/zoneinfo/Asia/Singapore",
+ "/usr/share/zoneinfo/Asia/Srednekolymsk",
+ "/usr/share/zoneinfo/Asia/Taipei",
+ "/usr/share/zoneinfo/Asia/Tashkent",
+ "/usr/share/zoneinfo/Asia/Tbilisi",
+ "/usr/share/zoneinfo/Asia/Tehran",
+ "/usr/share/zoneinfo/Asia/Thimphu",
+ "/usr/share/zoneinfo/Asia/Tokyo",
+ "/usr/share/zoneinfo/Asia/Tomsk",
+ "/usr/share/zoneinfo/Asia/Ulaanbaatar",
+ "/usr/share/zoneinfo/Asia/Urumqi",
+ "/usr/share/zoneinfo/Asia/Ust-Nera",
+ "/usr/share/zoneinfo/Asia/Vientiane",
+ "/usr/share/zoneinfo/Asia/Vladivostok",
+ "/usr/share/zoneinfo/Asia/Yakutsk",
+ "/usr/share/zoneinfo/Asia/Yangon",
+ "/usr/share/zoneinfo/Asia/Yekaterinburg",
+ "/usr/share/zoneinfo/Asia/Yerevan",
+ "/usr/share/zoneinfo/Atlantic/Azores",
+ "/usr/share/zoneinfo/Atlantic/Bermuda",
+ "/usr/share/zoneinfo/Atlantic/Canary",
+ "/usr/share/zoneinfo/Atlantic/Cape_Verde",
+ "/usr/share/zoneinfo/Atlantic/Faroe",
+ "/usr/share/zoneinfo/Atlantic/Madeira",
+ "/usr/share/zoneinfo/Atlantic/Reykjavik",
+ "/usr/share/zoneinfo/Atlantic/South_Georgia",
+ "/usr/share/zoneinfo/Atlantic/St_Helena",
+ "/usr/share/zoneinfo/Atlantic/Stanley",
+ "/usr/share/zoneinfo/Australia/Adelaide",
+ "/usr/share/zoneinfo/Australia/Brisbane",
+ "/usr/share/zoneinfo/Australia/Broken_Hill",
+ "/usr/share/zoneinfo/Australia/Darwin",
+ "/usr/share/zoneinfo/Australia/Eucla",
+ "/usr/share/zoneinfo/Australia/Hobart",
+ "/usr/share/zoneinfo/Australia/Lindeman",
+ "/usr/share/zoneinfo/Australia/Lord_Howe",
+ "/usr/share/zoneinfo/Australia/Melbourne",
+ "/usr/share/zoneinfo/Australia/Perth",
+ "/usr/share/zoneinfo/Australia/Sydney",
+ "/usr/share/zoneinfo/Etc/GMT",
+ "/usr/share/zoneinfo/Etc/GMT+1",
+ "/usr/share/zoneinfo/Etc/GMT+10",
+ "/usr/share/zoneinfo/Etc/GMT+11",
+ "/usr/share/zoneinfo/Etc/GMT+12",
+ "/usr/share/zoneinfo/Etc/GMT+2",
+ "/usr/share/zoneinfo/Etc/GMT+3",
+ "/usr/share/zoneinfo/Etc/GMT+4",
+ "/usr/share/zoneinfo/Etc/GMT+5",
+ "/usr/share/zoneinfo/Etc/GMT+6",
+ "/usr/share/zoneinfo/Etc/GMT+7",
+ "/usr/share/zoneinfo/Etc/GMT+8",
+ "/usr/share/zoneinfo/Etc/GMT+9",
+ "/usr/share/zoneinfo/Etc/GMT-1",
+ "/usr/share/zoneinfo/Etc/GMT-10",
+ "/usr/share/zoneinfo/Etc/GMT-11",
+ "/usr/share/zoneinfo/Etc/GMT-12",
+ "/usr/share/zoneinfo/Etc/GMT-13",
+ "/usr/share/zoneinfo/Etc/GMT-14",
+ "/usr/share/zoneinfo/Etc/GMT-2",
+ "/usr/share/zoneinfo/Etc/GMT-3",
+ "/usr/share/zoneinfo/Etc/GMT-4",
+ "/usr/share/zoneinfo/Etc/GMT-5",
+ "/usr/share/zoneinfo/Etc/GMT-6",
+ "/usr/share/zoneinfo/Etc/GMT-7",
+ "/usr/share/zoneinfo/Etc/GMT-8",
+ "/usr/share/zoneinfo/Etc/GMT-9",
+ "/usr/share/zoneinfo/Etc/UTC",
+ "/usr/share/zoneinfo/Europe/Amsterdam",
+ "/usr/share/zoneinfo/Europe/Andorra",
+ "/usr/share/zoneinfo/Europe/Astrakhan",
+ "/usr/share/zoneinfo/Europe/Athens",
+ "/usr/share/zoneinfo/Europe/Belgrade",
+ "/usr/share/zoneinfo/Europe/Berlin",
+ "/usr/share/zoneinfo/Europe/Brussels",
+ "/usr/share/zoneinfo/Europe/Bucharest",
+ "/usr/share/zoneinfo/Europe/Budapest",
+ "/usr/share/zoneinfo/Europe/Chisinau",
+ "/usr/share/zoneinfo/Europe/Copenhagen",
+ "/usr/share/zoneinfo/Europe/Dublin",
+ "/usr/share/zoneinfo/Europe/Gibraltar",
+ "/usr/share/zoneinfo/Europe/Guernsey",
+ "/usr/share/zoneinfo/Europe/Helsinki",
+ "/usr/share/zoneinfo/Europe/Isle_of_Man",
+ "/usr/share/zoneinfo/Europe/Istanbul",
+ "/usr/share/zoneinfo/Europe/Jersey",
+ "/usr/share/zoneinfo/Europe/Kaliningrad",
+ "/usr/share/zoneinfo/Europe/Kirov",
+ "/usr/share/zoneinfo/Europe/Kyiv",
+ "/usr/share/zoneinfo/Europe/Lisbon",
+ "/usr/share/zoneinfo/Europe/Ljubljana",
+ "/usr/share/zoneinfo/Europe/London",
+ "/usr/share/zoneinfo/Europe/Luxembourg",
+ "/usr/share/zoneinfo/Europe/Madrid",
+ "/usr/share/zoneinfo/Europe/Malta",
+ "/usr/share/zoneinfo/Europe/Minsk",
+ "/usr/share/zoneinfo/Europe/Monaco",
+ "/usr/share/zoneinfo/Europe/Moscow",
+ "/usr/share/zoneinfo/Europe/Oslo",
+ "/usr/share/zoneinfo/Europe/Paris",
+ "/usr/share/zoneinfo/Europe/Prague",
+ "/usr/share/zoneinfo/Europe/Riga",
+ "/usr/share/zoneinfo/Europe/Rome",
+ "/usr/share/zoneinfo/Europe/Samara",
+ "/usr/share/zoneinfo/Europe/Sarajevo",
+ "/usr/share/zoneinfo/Europe/Saratov",
+ "/usr/share/zoneinfo/Europe/Simferopol",
+ "/usr/share/zoneinfo/Europe/Skopje",
+ "/usr/share/zoneinfo/Europe/Sofia",
+ "/usr/share/zoneinfo/Europe/Stockholm",
+ "/usr/share/zoneinfo/Europe/Tallinn",
+ "/usr/share/zoneinfo/Europe/Tirane",
+ "/usr/share/zoneinfo/Europe/Ulyanovsk",
+ "/usr/share/zoneinfo/Europe/Vaduz",
+ "/usr/share/zoneinfo/Europe/Vienna",
+ "/usr/share/zoneinfo/Europe/Vilnius",
+ "/usr/share/zoneinfo/Europe/Volgograd",
+ "/usr/share/zoneinfo/Europe/Warsaw",
+ "/usr/share/zoneinfo/Europe/Zagreb",
+ "/usr/share/zoneinfo/Europe/Zurich",
+ "/usr/share/zoneinfo/Factory",
+ "/usr/share/zoneinfo/Indian/Antananarivo",
+ "/usr/share/zoneinfo/Indian/Chagos",
+ "/usr/share/zoneinfo/Indian/Christmas",
+ "/usr/share/zoneinfo/Indian/Cocos",
+ "/usr/share/zoneinfo/Indian/Comoro",
+ "/usr/share/zoneinfo/Indian/Kerguelen",
+ "/usr/share/zoneinfo/Indian/Mahe",
+ "/usr/share/zoneinfo/Indian/Maldives",
+ "/usr/share/zoneinfo/Indian/Mauritius",
+ "/usr/share/zoneinfo/Indian/Mayotte",
+ "/usr/share/zoneinfo/Indian/Reunion",
+ "/usr/share/zoneinfo/Pacific/Apia",
+ "/usr/share/zoneinfo/Pacific/Auckland",
+ "/usr/share/zoneinfo/Pacific/Bougainville",
+ "/usr/share/zoneinfo/Pacific/Chatham",
+ "/usr/share/zoneinfo/Pacific/Chuuk",
+ "/usr/share/zoneinfo/Pacific/Easter",
+ "/usr/share/zoneinfo/Pacific/Efate",
+ "/usr/share/zoneinfo/Pacific/Fakaofo",
+ "/usr/share/zoneinfo/Pacific/Fiji",
+ "/usr/share/zoneinfo/Pacific/Funafuti",
+ "/usr/share/zoneinfo/Pacific/Galapagos",
+ "/usr/share/zoneinfo/Pacific/Gambier",
+ "/usr/share/zoneinfo/Pacific/Guadalcanal",
+ "/usr/share/zoneinfo/Pacific/Guam",
+ "/usr/share/zoneinfo/Pacific/Honolulu",
+ "/usr/share/zoneinfo/Pacific/Kanton",
+ "/usr/share/zoneinfo/Pacific/Kiritimati",
+ "/usr/share/zoneinfo/Pacific/Kosrae",
+ "/usr/share/zoneinfo/Pacific/Kwajalein",
+ "/usr/share/zoneinfo/Pacific/Majuro",
+ "/usr/share/zoneinfo/Pacific/Marquesas",
+ "/usr/share/zoneinfo/Pacific/Midway",
+ "/usr/share/zoneinfo/Pacific/Nauru",
+ "/usr/share/zoneinfo/Pacific/Niue",
+ "/usr/share/zoneinfo/Pacific/Norfolk",
+ "/usr/share/zoneinfo/Pacific/Noumea",
+ "/usr/share/zoneinfo/Pacific/Pago_Pago",
+ "/usr/share/zoneinfo/Pacific/Palau",
+ "/usr/share/zoneinfo/Pacific/Pitcairn",
+ "/usr/share/zoneinfo/Pacific/Pohnpei",
+ "/usr/share/zoneinfo/Pacific/Port_Moresby",
+ "/usr/share/zoneinfo/Pacific/Rarotonga",
+ "/usr/share/zoneinfo/Pacific/Saipan",
+ "/usr/share/zoneinfo/Pacific/Tahiti",
+ "/usr/share/zoneinfo/Pacific/Tarawa",
+ "/usr/share/zoneinfo/Pacific/Tongatapu",
+ "/usr/share/zoneinfo/Pacific/Wake",
+ "/usr/share/zoneinfo/Pacific/Wallis",
+ "/usr/share/zoneinfo/iso3166.tab",
+ "/usr/share/zoneinfo/leap-seconds.list",
+ "/usr/share/zoneinfo/leapseconds",
+ "/usr/share/zoneinfo/tzdata.zi",
+ "/usr/share/zoneinfo/zone.tab",
+ "/usr/share/zoneinfo/zone1970.tab",
+ "/usr/share/zoneinfo/zonenow.tab"
+ ]
+ },
+ {
+ "ID": "util-linux@2.41-5",
+ "Name": "util-linux",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/util-linux@2.41-5?arch=amd64\u0026distro=debian-13.6",
+ "UID": "38be4846f19b7fa"
+ },
+ "Version": "2.41",
+ "Release": "5",
+ "Arch": "amd64",
+ "SrcName": "util-linux",
+ "SrcVersion": "2.41",
+ "SrcRelease": "5",
+ "Licenses": [
+ "GPL-2.0-or-later",
+ "GPL-2.0-only",
+ "GPL-3.0-or-later",
+ "LGPL-2.1-or-later",
+ "public-domain",
+ "BSD-4-Clause",
+ "MIT",
+ "ISC",
+ "BSD-3-Clause",
+ "BSLA",
+ "LGPL-2.0-or-later",
+ "BSD-2-Clause",
+ "LGPL-3.0-or-later",
+ "GPL-3.0-only",
+ "LGPL-2.0-only",
+ "LGPL-2.1-only",
+ "LGPL-3.0-only"
+ ],
+ "Maintainer": "Chris Hofstaedtler \u003czeha@debian.org\u003e",
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/bin/choom",
+ "/usr/bin/chrt",
+ "/usr/bin/dmesg",
+ "/usr/bin/fallocate",
+ "/usr/bin/findmnt",
+ "/usr/bin/flock",
+ "/usr/bin/getopt",
+ "/usr/bin/hardlink",
+ "/usr/bin/ionice",
+ "/usr/bin/ipcmk",
+ "/usr/bin/ipcrm",
+ "/usr/bin/ipcs",
+ "/usr/bin/lsblk",
+ "/usr/bin/lscpu",
+ "/usr/bin/lsipc",
+ "/usr/bin/lslocks",
+ "/usr/bin/lslogins",
+ "/usr/bin/lsmem",
+ "/usr/bin/lsns",
+ "/usr/bin/mcookie",
+ "/usr/bin/more",
+ "/usr/bin/mountpoint",
+ "/usr/bin/namei",
+ "/usr/bin/nsenter",
+ "/usr/bin/partx",
+ "/usr/bin/prlimit",
+ "/usr/bin/rename.ul",
+ "/usr/bin/rev",
+ "/usr/bin/setarch",
+ "/usr/bin/setpriv",
+ "/usr/bin/setsid",
+ "/usr/bin/setterm",
+ "/usr/bin/su",
+ "/usr/bin/taskset",
+ "/usr/bin/uclampset",
+ "/usr/bin/unshare",
+ "/usr/bin/wdctl",
+ "/usr/bin/whereis",
+ "/usr/lib/mime/packages/util-linux",
+ "/usr/lib/systemd/system/fstrim.service",
+ "/usr/lib/systemd/system/fstrim.timer",
+ "/usr/sbin/agetty",
+ "/usr/sbin/blkdiscard",
+ "/usr/sbin/blkid",
+ "/usr/sbin/blkzone",
+ "/usr/sbin/blockdev",
+ "/usr/sbin/chcpu",
+ "/usr/sbin/chmem",
+ "/usr/sbin/findfs",
+ "/usr/sbin/fsck",
+ "/usr/sbin/fsfreeze",
+ "/usr/sbin/fstrim",
+ "/usr/sbin/isosize",
+ "/usr/sbin/ldattach",
+ "/usr/sbin/mkfs",
+ "/usr/sbin/mkswap",
+ "/usr/sbin/pivot_root",
+ "/usr/sbin/readprofile",
+ "/usr/sbin/rtcwake",
+ "/usr/sbin/runuser",
+ "/usr/sbin/sulogin",
+ "/usr/sbin/swaplabel",
+ "/usr/sbin/switch_root",
+ "/usr/sbin/wipefs",
+ "/usr/sbin/zramctl",
+ "/usr/share/bash-completion/completions/blkdiscard",
+ "/usr/share/bash-completion/completions/blkid",
+ "/usr/share/bash-completion/completions/blkzone",
+ "/usr/share/bash-completion/completions/blockdev",
+ "/usr/share/bash-completion/completions/chcpu",
+ "/usr/share/bash-completion/completions/chmem",
+ "/usr/share/bash-completion/completions/chrt",
+ "/usr/share/bash-completion/completions/dmesg",
+ "/usr/share/bash-completion/completions/fallocate",
+ "/usr/share/bash-completion/completions/findfs",
+ "/usr/share/bash-completion/completions/findmnt",
+ "/usr/share/bash-completion/completions/flock",
+ "/usr/share/bash-completion/completions/fsck",
+ "/usr/share/bash-completion/completions/fsfreeze",
+ "/usr/share/bash-completion/completions/fstrim",
+ "/usr/share/bash-completion/completions/getopt",
+ "/usr/share/bash-completion/completions/hardlink",
+ "/usr/share/bash-completion/completions/ionice",
+ "/usr/share/bash-completion/completions/ipcmk",
+ "/usr/share/bash-completion/completions/ipcrm",
+ "/usr/share/bash-completion/completions/ipcs",
+ "/usr/share/bash-completion/completions/isosize",
+ "/usr/share/bash-completion/completions/ldattach",
+ "/usr/share/bash-completion/completions/lsblk",
+ "/usr/share/bash-completion/completions/lscpu",
+ "/usr/share/bash-completion/completions/lsipc",
+ "/usr/share/bash-completion/completions/lslocks",
+ "/usr/share/bash-completion/completions/lslogins",
+ "/usr/share/bash-completion/completions/lsmem",
+ "/usr/share/bash-completion/completions/lsns",
+ "/usr/share/bash-completion/completions/mcookie",
+ "/usr/share/bash-completion/completions/mkfs",
+ "/usr/share/bash-completion/completions/mkswap",
+ "/usr/share/bash-completion/completions/more",
+ "/usr/share/bash-completion/completions/mountpoint",
+ "/usr/share/bash-completion/completions/namei",
+ "/usr/share/bash-completion/completions/nsenter",
+ "/usr/share/bash-completion/completions/partx",
+ "/usr/share/bash-completion/completions/pivot_root",
+ "/usr/share/bash-completion/completions/prlimit",
+ "/usr/share/bash-completion/completions/readprofile",
+ "/usr/share/bash-completion/completions/rename.ul",
+ "/usr/share/bash-completion/completions/rev",
+ "/usr/share/bash-completion/completions/rtcwake",
+ "/usr/share/bash-completion/completions/setarch",
+ "/usr/share/bash-completion/completions/setpriv",
+ "/usr/share/bash-completion/completions/setsid",
+ "/usr/share/bash-completion/completions/setterm",
+ "/usr/share/bash-completion/completions/su",
+ "/usr/share/bash-completion/completions/swaplabel",
+ "/usr/share/bash-completion/completions/taskset",
+ "/usr/share/bash-completion/completions/uclampset",
+ "/usr/share/bash-completion/completions/unshare",
+ "/usr/share/bash-completion/completions/wdctl",
+ "/usr/share/bash-completion/completions/whereis",
+ "/usr/share/bash-completion/completions/wipefs",
+ "/usr/share/bash-completion/completions/zramctl",
+ "/usr/share/doc/util-linux/00-about-docs.txt",
+ "/usr/share/doc/util-linux/AUTHORS.gz",
+ "/usr/share/doc/util-linux/NEWS.Debian.gz",
+ "/usr/share/doc/util-linux/PAM-configuration.txt",
+ "/usr/share/doc/util-linux/README.Debian",
+ "/usr/share/doc/util-linux/blkid.txt",
+ "/usr/share/doc/util-linux/cal.txt",
+ "/usr/share/doc/util-linux/changelog.Debian.gz",
+ "/usr/share/doc/util-linux/changelog.gz",
+ "/usr/share/doc/util-linux/col.txt",
+ "/usr/share/doc/util-linux/copyright",
+ "/usr/share/doc/util-linux/deprecated.txt",
+ "/usr/share/doc/util-linux/examples/getopt-example.bash",
+ "/usr/share/doc/util-linux/getopt.txt",
+ "/usr/share/doc/util-linux/getopt_changelog.txt",
+ "/usr/share/doc/util-linux/howto-build-sys.txt",
+ "/usr/share/doc/util-linux/howto-compilation.txt",
+ "/usr/share/doc/util-linux/howto-contribute.txt.gz",
+ "/usr/share/doc/util-linux/howto-debug.txt",
+ "/usr/share/doc/util-linux/howto-man-page.txt",
+ "/usr/share/doc/util-linux/howto-pull-request.txt.gz",
+ "/usr/share/doc/util-linux/howto-tests.txt",
+ "/usr/share/doc/util-linux/howto-usage-function.txt.gz",
+ "/usr/share/doc/util-linux/hwclock.txt",
+ "/usr/share/doc/util-linux/modems-with-agetty.txt",
+ "/usr/share/doc/util-linux/mount.txt",
+ "/usr/share/doc/util-linux/parse-date.txt.gz",
+ "/usr/share/doc/util-linux/pg.txt",
+ "/usr/share/doc/util-linux/poeigl.txt.gz",
+ "/usr/share/doc/util-linux/release-schedule.txt",
+ "/usr/share/doc/util-linux/releases/v2.13-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.14-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.15-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.16-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.17-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.18-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.19-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.20-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.21-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.22-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.23-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.24-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.25-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.26-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.27-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.28-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.29-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.30-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.31-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.32-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.33-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.34-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.35-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.36-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.37-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.38-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.39-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.40-ReleaseNotes.gz",
+ "/usr/share/doc/util-linux/releases/v2.41-ReleaseNotes.gz",
+ "/usr/share/lintian/overrides/util-linux",
+ "/usr/share/man/man1/choom.1.gz",
+ "/usr/share/man/man1/chrt.1.gz",
+ "/usr/share/man/man1/dmesg.1.gz",
+ "/usr/share/man/man1/fallocate.1.gz",
+ "/usr/share/man/man1/flock.1.gz",
+ "/usr/share/man/man1/getopt.1.gz",
+ "/usr/share/man/man1/hardlink.1.gz",
+ "/usr/share/man/man1/ionice.1.gz",
+ "/usr/share/man/man1/ipcmk.1.gz",
+ "/usr/share/man/man1/ipcrm.1.gz",
+ "/usr/share/man/man1/ipcs.1.gz",
+ "/usr/share/man/man1/lscpu.1.gz",
+ "/usr/share/man/man1/lsipc.1.gz",
+ "/usr/share/man/man1/lslogins.1.gz",
+ "/usr/share/man/man1/lsmem.1.gz",
+ "/usr/share/man/man1/mcookie.1.gz",
+ "/usr/share/man/man1/more.1.gz",
+ "/usr/share/man/man1/mountpoint.1.gz",
+ "/usr/share/man/man1/namei.1.gz",
+ "/usr/share/man/man1/nsenter.1.gz",
+ "/usr/share/man/man1/prlimit.1.gz",
+ "/usr/share/man/man1/rename.ul.1.gz",
+ "/usr/share/man/man1/rev.1.gz",
+ "/usr/share/man/man1/runuser.1.gz",
+ "/usr/share/man/man1/setpriv.1.gz",
+ "/usr/share/man/man1/setsid.1.gz",
+ "/usr/share/man/man1/setterm.1.gz",
+ "/usr/share/man/man1/su.1.gz",
+ "/usr/share/man/man1/taskset.1.gz",
+ "/usr/share/man/man1/uclampset.1.gz",
+ "/usr/share/man/man1/unshare.1.gz",
+ "/usr/share/man/man1/whereis.1.gz",
+ "/usr/share/man/man5/adjtime_config.5.gz",
+ "/usr/share/man/man5/scols-filter.5.gz",
+ "/usr/share/man/man5/terminal-colors.d.5.gz",
+ "/usr/share/man/man8/agetty.8.gz",
+ "/usr/share/man/man8/blkdiscard.8.gz",
+ "/usr/share/man/man8/blkid.8.gz",
+ "/usr/share/man/man8/blkzone.8.gz",
+ "/usr/share/man/man8/blockdev.8.gz",
+ "/usr/share/man/man8/chcpu.8.gz",
+ "/usr/share/man/man8/chmem.8.gz",
+ "/usr/share/man/man8/findfs.8.gz",
+ "/usr/share/man/man8/findmnt.8.gz",
+ "/usr/share/man/man8/fsck.8.gz",
+ "/usr/share/man/man8/fsfreeze.8.gz",
+ "/usr/share/man/man8/fstrim.8.gz",
+ "/usr/share/man/man8/isosize.8.gz",
+ "/usr/share/man/man8/ldattach.8.gz",
+ "/usr/share/man/man8/lsblk.8.gz",
+ "/usr/share/man/man8/lslocks.8.gz",
+ "/usr/share/man/man8/lsns.8.gz",
+ "/usr/share/man/man8/mkfs.8.gz",
+ "/usr/share/man/man8/mkswap.8.gz",
+ "/usr/share/man/man8/partx.8.gz",
+ "/usr/share/man/man8/pivot_root.8.gz",
+ "/usr/share/man/man8/readprofile.8.gz",
+ "/usr/share/man/man8/rtcwake.8.gz",
+ "/usr/share/man/man8/setarch.8.gz",
+ "/usr/share/man/man8/sulogin.8.gz",
+ "/usr/share/man/man8/swaplabel.8.gz",
+ "/usr/share/man/man8/switch_root.8.gz",
+ "/usr/share/man/man8/wdctl.8.gz",
+ "/usr/share/man/man8/wipefs.8.gz",
+ "/usr/share/man/man8/zramctl.8.gz",
+ "/usr/share/util-linux/logcheck/ignore.d.server/util-linux"
+ ]
+ },
+ {
+ "ID": "zlib1g@1:1.3.dfsg+really1.3.1-1+b1",
+ "Name": "zlib1g",
+ "Identifier": {
+ "PURL": "pkg:deb/debian/zlib1g@1.3.dfsg%2Breally1.3.1-1%2Bb1?arch=amd64\u0026distro=debian-13.6\u0026epoch=1",
+ "UID": "202a4bb3bdd0a341"
+ },
+ "Version": "1.3.dfsg+really1.3.1",
+ "Release": "1+b1",
+ "Epoch": 1,
+ "Arch": "amd64",
+ "SrcName": "zlib",
+ "SrcVersion": "1.3.dfsg+really1.3.1",
+ "SrcRelease": "1",
+ "SrcEpoch": 1,
+ "Licenses": [
+ "Zlib"
+ ],
+ "Maintainer": "Mark Brown \u003cbroonie@debian.org\u003e",
+ "DependsOn": [
+ "libc6@2.41-12+deb13u3"
+ ],
+ "Layer": {
+ "DiffID": "sha256:f2ec4de84f559f5c7be4233b589cdbdbb5507807e05621b77320edd55a1f2a0f"
+ },
+ "InstalledFiles": [
+ "/usr/lib/x86_64-linux-gnu/libz.so.1.3.1",
+ "/usr/share/doc/zlib1g/changelog.Debian.amd64.gz",
+ "/usr/share/doc/zlib1g/changelog.Debian.gz",
+ "/usr/share/doc/zlib1g/changelog.gz",
+ "/usr/share/doc/zlib1g/copyright"
+ ]
+ }
+ ]
+ },
+ {
+ "Target": "Python",
+ "Class": "lang-pkgs",
+ "Type": "python-pkg",
+ "Packages": [
+ {
+ "Name": "PyJWT",
+ "Identifier": {
+ "PURL": "pkg:pypi/pyjwt@2.13.0",
+ "UID": "5fc2d525c3bd7c1f"
+ },
+ "Version": "2.13.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pyjwt-2.13.0.dist-info/METADATA",
+ "Digest": "sha1:78125d2bb60e70bc168fd8787075ceb6a69d4f65"
+ },
+ {
+ "Name": "annotated-types",
+ "Identifier": {
+ "PURL": "pkg:pypi/annotated-types@0.7.0",
+ "UID": "c71dc606d215f927"
+ },
+ "Version": "0.7.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/METADATA",
+ "Digest": "sha1:b11011181822ac765c9f66c8aa42c26952de6a96"
+ },
+ {
+ "Name": "anthropic",
+ "Identifier": {
+ "PURL": "pkg:pypi/anthropic@0.104.1",
+ "UID": "1518a81a53566060"
+ },
+ "Version": "0.104.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/anthropic-0.104.1.dist-info/METADATA",
+ "Digest": "sha1:6a0fce5932599b482bf25ed3db3c06e9211f1358"
+ },
+ {
+ "Name": "anyio",
+ "Identifier": {
+ "PURL": "pkg:pypi/anyio@4.13.0",
+ "UID": "aeb9e8b83c448893"
+ },
+ "Version": "4.13.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/anyio-4.13.0.dist-info/METADATA",
+ "Digest": "sha1:5f30168435645daddf756ecef34992631c6e778b"
+ },
+ {
+ "Name": "attrs",
+ "Identifier": {
+ "PURL": "pkg:pypi/attrs@26.1.0",
+ "UID": "b54e7e42438eca08"
+ },
+ "Version": "26.1.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/attrs-26.1.0.dist-info/METADATA",
+ "Digest": "sha1:89068272cc1dc340d8fd910a62be241c42414339"
+ },
+ {
+ "Name": "boto3",
+ "Identifier": {
+ "PURL": "pkg:pypi/boto3@1.43.56",
+ "UID": "3423e7541c1fbba1"
+ },
+ "Version": "1.43.56",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/boto3-1.43.56.dist-info/METADATA",
+ "Digest": "sha1:f5c7842f2414d0cd2cefdb918d07c52018450ff7"
+ },
+ {
+ "Name": "botocore",
+ "Identifier": {
+ "PURL": "pkg:pypi/botocore@1.43.56",
+ "UID": "359b1819e48a292f"
+ },
+ "Version": "1.43.56",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/botocore-1.43.56.dist-info/METADATA",
+ "Digest": "sha1:b8760d1db82eba72c06ec96252b62d541a21b09e"
+ },
+ {
+ "Name": "certifi",
+ "Identifier": {
+ "PURL": "pkg:pypi/certifi@2026.5.20",
+ "UID": "fe6f01e6c112235d"
+ },
+ "Version": "2026.5.20",
+ "Licenses": [
+ "MPL-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/certifi-2026.5.20.dist-info/METADATA",
+ "Digest": "sha1:cb42a7b0ba6491d51e71ff594a39bfaf5b8f9d22"
+ },
+ {
+ "Name": "cffi",
+ "Identifier": {
+ "PURL": "pkg:pypi/cffi@2.0.0",
+ "UID": "e00042ff47d67589"
+ },
+ "Version": "2.0.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/cffi-2.0.0.dist-info/METADATA",
+ "Digest": "sha1:87e9c9d276c4f4c31f5a314d6a5472f45655674c"
+ },
+ {
+ "Name": "click",
+ "Identifier": {
+ "PURL": "pkg:pypi/click@8.4.1",
+ "UID": "fe61547eb7f8f82b"
+ },
+ "Version": "8.4.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/click-8.4.1.dist-info/METADATA",
+ "Digest": "sha1:c486957c59cc28072021bdcfe6d681e9ddafc860"
+ },
+ {
+ "Name": "cryptography",
+ "Identifier": {
+ "PURL": "pkg:pypi/cryptography@49.0.0",
+ "UID": "c2dd24349681a2e"
+ },
+ "Version": "49.0.0",
+ "Licenses": [
+ "Apache-2.0 OR BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/cryptography-49.0.0.dist-info/METADATA",
+ "Digest": "sha1:739372eb2cc71602103a206e7a42a926930cecb6"
+ },
+ {
+ "Name": "distro",
+ "Identifier": {
+ "PURL": "pkg:pypi/distro@1.9.0",
+ "UID": "c89f2e1e7521f2a8"
+ },
+ "Version": "1.9.0",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/distro-1.9.0.dist-info/METADATA",
+ "Digest": "sha1:ce14620cf14e15a64d2ff574796543f99619e7f3"
+ },
+ {
+ "Name": "docstring_parser",
+ "Identifier": {
+ "PURL": "pkg:pypi/docstring-parser@0.18.0",
+ "UID": "e4f3b6e5180465d3"
+ },
+ "Version": "0.18.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/docstring_parser-0.18.0.dist-info/METADATA",
+ "Digest": "sha1:cd475f73b404c399cf87b9fb990fc14669479d24"
+ },
+ {
+ "Name": "h11",
+ "Identifier": {
+ "PURL": "pkg:pypi/h11@0.16.0",
+ "UID": "bd2ef166e50e47c9"
+ },
+ "Version": "0.16.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/h11-0.16.0.dist-info/METADATA",
+ "Digest": "sha1:5d41eddffefef5f6e8ff383a2537e81a38a37807"
+ },
+ {
+ "Name": "httpcore",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpcore@1.0.9",
+ "UID": "7af11667b3914c00"
+ },
+ "Version": "1.0.9",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpcore-1.0.9.dist-info/METADATA",
+ "Digest": "sha1:2981d359ae33f31d339189a9680db85785339a56"
+ },
+ {
+ "Name": "httpx",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx@0.28.1",
+ "UID": "84c8e4f1cadb34f8"
+ },
+ "Version": "0.28.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/METADATA",
+ "Digest": "sha1:537da7e4f29438278e124e10e02d1a500fe33bcc"
+ },
+ {
+ "Name": "httpx-sse",
+ "Identifier": {
+ "PURL": "pkg:pypi/httpx-sse@0.4.3",
+ "UID": "5aa2ff814a843fb8"
+ },
+ "Version": "0.4.3",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/httpx_sse-0.4.3.dist-info/METADATA",
+ "Digest": "sha1:df05446be58f0a3a306e50c7ceebef24bb383a6d"
+ },
+ {
+ "Name": "idna",
+ "Identifier": {
+ "PURL": "pkg:pypi/idna@3.16",
+ "UID": "56f67b383049e92f"
+ },
+ "Version": "3.16",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/idna-3.16.dist-info/METADATA",
+ "Digest": "sha1:191a7bf1dac83b0cc997024ebb4b8da5c962ae5b"
+ },
+ {
+ "Name": "jiter",
+ "Identifier": {
+ "PURL": "pkg:pypi/jiter@0.15.0",
+ "UID": "e16e05a7b79c5a19"
+ },
+ "Version": "0.15.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jiter-0.15.0.dist-info/METADATA",
+ "Digest": "sha1:9de68ecc913d85eafa70a1252b2f5b1b2d2829f5"
+ },
+ {
+ "Name": "jmespath",
+ "Identifier": {
+ "PURL": "pkg:pypi/jmespath@1.1.0",
+ "UID": "2b038fddcf91443b"
+ },
+ "Version": "1.1.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jmespath-1.1.0.dist-info/METADATA",
+ "Digest": "sha1:d3f297922cf04b0cc127a18994ad6e6b947f0cc7"
+ },
+ {
+ "Name": "jsonschema",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema@4.26.0",
+ "UID": "86f464e67bdc7252"
+ },
+ "Version": "4.26.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jsonschema-4.26.0.dist-info/METADATA",
+ "Digest": "sha1:94b3d1a46cf55d74e42c401eaf4a4b71c76cee31"
+ },
+ {
+ "Name": "jsonschema-specifications",
+ "Identifier": {
+ "PURL": "pkg:pypi/jsonschema-specifications@2025.9.1",
+ "UID": "4ff310017540d529"
+ },
+ "Version": "2025.9.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/jsonschema_specifications-2025.9.1.dist-info/METADATA",
+ "Digest": "sha1:ac33f477be9d3336ae67bc454f68a9ff39c91cf3"
+ },
+ {
+ "Name": "mcp",
+ "Identifier": {
+ "PURL": "pkg:pypi/mcp@1.28.1",
+ "UID": "20a25e72d0904008"
+ },
+ "Version": "1.28.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/mcp-1.28.1.dist-info/METADATA",
+ "Digest": "sha1:22fedbbf2f1d94917eba0c0c156781325bd3d786"
+ },
+ {
+ "Name": "openai",
+ "Identifier": {
+ "PURL": "pkg:pypi/openai@2.38.0",
+ "UID": "e80e37eec1285c9a"
+ },
+ "Version": "2.38.0",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/openai-2.38.0.dist-info/METADATA",
+ "Digest": "sha1:ea17f685d13b1a896fb055b3bedbfcb5ed8da63a"
+ },
+ {
+ "Name": "openrath",
+ "Identifier": {
+ "PURL": "pkg:pypi/openrath@1.3.0",
+ "UID": "545d02ff18290308"
+ },
+ "Version": "1.3.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/openrath-1.3.0.dist-info/METADATA",
+ "Digest": "sha1:d04d62d29a60270300a6eefa18f542d44f8d14fc"
+ },
+ {
+ "Name": "opentelemetry-api",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-api@1.42.1",
+ "UID": "8bdf3d15c03389e4"
+ },
+ "Version": "1.42.1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_api-1.42.1.dist-info/METADATA",
+ "Digest": "sha1:a54ebbf560cfb13acfd3d7f7a5c385f03e36be08"
+ },
+ {
+ "Name": "opentelemetry-sdk",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-sdk@1.42.1",
+ "UID": "ad8ea46e0b53c209"
+ },
+ "Version": "1.42.1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_sdk-1.42.1.dist-info/METADATA",
+ "Digest": "sha1:cdfb9c90d3e4765c62ffce81a835445a8efef7c4"
+ },
+ {
+ "Name": "opentelemetry-semantic-conventions",
+ "Identifier": {
+ "PURL": "pkg:pypi/opentelemetry-semantic-conventions@0.63b1",
+ "UID": "94dfcc83b7ff01c7"
+ },
+ "Version": "0.63b1",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/opentelemetry_semantic_conventions-0.63b1.dist-info/METADATA",
+ "Digest": "sha1:5c7aaa298ae1ba489d7214ebec1427bd3f602556"
+ },
+ {
+ "Name": "pip",
+ "Identifier": {
+ "PURL": "pkg:pypi/pip@25.0.1",
+ "UID": "6c029e6e913de377"
+ },
+ "Version": "25.0.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:83fdf57f71f28b640f11d5072c284c81eadefc5ea538050fedcedba6149879bd"
+ },
+ "FilePath": "usr/local/lib/python3.12/site-packages/pip-25.0.1.dist-info/METADATA"
+ },
+ {
+ "Name": "psycopg",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg@3.3.4",
+ "UID": "6b4486e675bd7a02"
+ },
+ "Version": "3.3.4",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg-3.3.4.dist-info/METADATA",
+ "Digest": "sha1:dc38178dd59b090117f63d60bc627e6a168205c8"
+ },
+ {
+ "Name": "psycopg-binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4",
+ "UID": "e20890c2b22e7f46"
+ },
+ "Version": "3.3.4",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg_binary-3.3.4.dist-info/METADATA",
+ "Digest": "sha1:e8c69d729c969a8a81834cce24f8947ad560813d"
+ },
+ {
+ "Name": "psycopg-pool",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-pool@3.3.1",
+ "UID": "81277f710880020c"
+ },
+ "Version": "3.3.1",
+ "Licenses": [
+ "LGPL-3.0-only"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/psycopg_pool-3.3.1.dist-info/METADATA",
+ "Digest": "sha1:60d07aa411067306f5244d0481227a78a5b11135"
+ },
+ {
+ "ID": "psycopg_binary@3.3.4",
+ "Name": "psycopg_binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "UID": "56fa9b57c57faa13",
+ "BOMRef": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+ },
+ "Version": "3.3.4",
+ "DependsOn": [
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "krb5-libs@1.15.1-55.el7_9",
+ "cyrus-sasl-lib@2.1.26-24.el7_9",
+ "pcre@8.32-17.el7",
+ "libselinux@2.5-15.el7",
+ "libcom_err@1.42.9-19.el7",
+ "keyutils-libs@1.5.8-3.el7"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "ID": "psycopg_binary@3.3.4",
+ "Name": "psycopg_binary",
+ "Identifier": {
+ "PURL": "pkg:pypi/psycopg-binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
+ "UID": "76f4c37cac088f9b",
+ "BOMRef": "pkg:pypi/psycopg_binary@3.3.4?file_name=psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+ },
+ "Version": "3.3.4",
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ }
+ },
+ {
+ "Name": "pycparser",
+ "Identifier": {
+ "PURL": "pkg:pypi/pycparser@3.0",
+ "UID": "7fa26205633e9bc7"
+ },
+ "Version": "3.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pycparser-3.0.dist-info/METADATA",
+ "Digest": "sha1:ec46323dcd4dd2f7742b74b09cc0b030e330e46f"
+ },
+ {
+ "Name": "pydantic",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic@2.13.4",
+ "UID": "309395c26168aba1"
+ },
+ "Version": "2.13.4",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic-2.13.4.dist-info/METADATA",
+ "Digest": "sha1:291e482df82749c7e52c21e8275551f04de3034b"
+ },
+ {
+ "Name": "pydantic-settings",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-settings@2.14.1",
+ "UID": "b01af17e9800dc25"
+ },
+ "Version": "2.14.1",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic_settings-2.14.1.dist-info/METADATA",
+ "Digest": "sha1:b9246a1f2d8974cb71bb7ec65fb8a9f45710d89a"
+ },
+ {
+ "Name": "pydantic_core",
+ "Identifier": {
+ "PURL": "pkg:pypi/pydantic-core@2.46.4",
+ "UID": "11710354afa9f5bd"
+ },
+ "Version": "2.46.4",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/pydantic_core-2.46.4.dist-info/METADATA",
+ "Digest": "sha1:f44318e9ae79f745f1f5a7a59b43044ab6fff485"
+ },
+ {
+ "Name": "python-dateutil",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dateutil@2.9.0.post0",
+ "UID": "fd4ae8a677536c26"
+ },
+ "Version": "2.9.0.post0",
+ "Licenses": [
+ "BSD-3-Clause",
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA",
+ "Digest": "sha1:7a3c35abd86cd96034d5afb0d4b241dc9e13e6f8"
+ },
+ {
+ "Name": "python-dotenv",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-dotenv@1.2.2",
+ "UID": "460b06f33eb8af4b"
+ },
+ "Version": "1.2.2",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_dotenv-1.2.2.dist-info/METADATA",
+ "Digest": "sha1:a70b92340410dfaf8ce628e658f176278fa2e557"
+ },
+ {
+ "Name": "python-multipart",
+ "Identifier": {
+ "PURL": "pkg:pypi/python-multipart@0.0.32",
+ "UID": "d69de3c1197a3dc4"
+ },
+ "Version": "0.0.32",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/python_multipart-0.0.32.dist-info/METADATA",
+ "Digest": "sha1:9f79572b3702bdac7487183b498470341276b17e"
+ },
+ {
+ "Name": "redis",
+ "Identifier": {
+ "PURL": "pkg:pypi/redis@6.4.0",
+ "UID": "75c6670b0ecc89e1"
+ },
+ "Version": "6.4.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/redis-6.4.0.dist-info/METADATA",
+ "Digest": "sha1:9a3de9ffc83addb0d845a4f16c6a415db91a3eda"
+ },
+ {
+ "Name": "referencing",
+ "Identifier": {
+ "PURL": "pkg:pypi/referencing@0.37.0",
+ "UID": "9388367362afb6d3"
+ },
+ "Version": "0.37.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/referencing-0.37.0.dist-info/METADATA",
+ "Digest": "sha1:f6fa004340bef5d23995b09dab75ce12e3f367a7"
+ },
+ {
+ "Name": "rpds-py",
+ "Identifier": {
+ "PURL": "pkg:pypi/rpds-py@0.30.0",
+ "UID": "d63cf34ee7ba499b"
+ },
+ "Version": "0.30.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/rpds_py-0.30.0.dist-info/METADATA",
+ "Digest": "sha1:9eef46c842a0ca6229680d7bfc1272958efdcc5a"
+ },
+ {
+ "Name": "s3transfer",
+ "Identifier": {
+ "PURL": "pkg:pypi/s3transfer@0.19.2",
+ "UID": "6d71d4e81b9ba7fc"
+ },
+ "Version": "0.19.2",
+ "Licenses": [
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/s3transfer-0.19.2.dist-info/METADATA",
+ "Digest": "sha1:453d1af3240f56bb5d0bd093eb3d21a250cc5777"
+ },
+ {
+ "Name": "six",
+ "Identifier": {
+ "PURL": "pkg:pypi/six@1.17.0",
+ "UID": "a8157445993a695a"
+ },
+ "Version": "1.17.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA",
+ "Digest": "sha1:483a26554261f6c839703c0e1183f3ef33ff97f1"
+ },
+ {
+ "Name": "sniffio",
+ "Identifier": {
+ "PURL": "pkg:pypi/sniffio@1.3.1",
+ "UID": "1b1f0a25ec7db717"
+ },
+ "Version": "1.3.1",
+ "Licenses": [
+ "MIT",
+ "Apache-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/METADATA",
+ "Digest": "sha1:bc1d7aead770fe23c8d22666b84558edb3686da3"
+ },
+ {
+ "Name": "sse-starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/sse-starlette@3.4.4",
+ "UID": "f7d0373d022644e5"
+ },
+ "Version": "3.4.4",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/sse_starlette-3.4.4.dist-info/METADATA",
+ "Digest": "sha1:58e4ad3946eafb572e0219f89bb599bee2b7cca2"
+ },
+ {
+ "Name": "starlette",
+ "Identifier": {
+ "PURL": "pkg:pypi/starlette@1.3.1",
+ "UID": "5e46860cf2a27721"
+ },
+ "Version": "1.3.1",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/starlette-1.3.1.dist-info/METADATA",
+ "Digest": "sha1:9e43f99dc64bcf4498d65999f9cb36a40fa5e94c"
+ },
+ {
+ "Name": "tqdm",
+ "Identifier": {
+ "PURL": "pkg:pypi/tqdm@4.67.3",
+ "UID": "b7def43f9f2d825e"
+ },
+ "Version": "4.67.3",
+ "Licenses": [
+ "MPL-2.0 AND MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/tqdm-4.67.3.dist-info/METADATA",
+ "Digest": "sha1:0135af1981d2b0f1326020f991192d869693b873"
+ },
+ {
+ "Name": "typing-inspection",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-inspection@0.4.2",
+ "UID": "a9781e801ec5ae38"
+ },
+ "Version": "0.4.2",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/typing_inspection-0.4.2.dist-info/METADATA",
+ "Digest": "sha1:455fdb9c8e246ba02c2a28655287401b62028b60"
+ },
+ {
+ "Name": "typing_extensions",
+ "Identifier": {
+ "PURL": "pkg:pypi/typing-extensions@4.15.0",
+ "UID": "1d9a13c2bfbf6a28"
+ },
+ "Version": "4.15.0",
+ "Licenses": [
+ "PSF-2.0"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/typing_extensions-4.15.0.dist-info/METADATA",
+ "Digest": "sha1:c5c2ce18351f8f2ae0f4a6f7c84c523f342010ee"
+ },
+ {
+ "Name": "urllib3",
+ "Identifier": {
+ "PURL": "pkg:pypi/urllib3@2.7.0",
+ "UID": "f3bb6bdd35ff9f59"
+ },
+ "Version": "2.7.0",
+ "Licenses": [
+ "MIT"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/urllib3-2.7.0.dist-info/METADATA",
+ "Digest": "sha1:d20520d0598c114ced8d55ed14209a2a3bbee22c"
+ },
+ {
+ "Name": "uvicorn",
+ "Identifier": {
+ "PURL": "pkg:pypi/uvicorn@0.47.0",
+ "UID": "7ddf3857a5dc77ba"
+ },
+ "Version": "0.47.0",
+ "Licenses": [
+ "BSD-3-Clause"
+ ],
+ "Layer": {
+ "DiffID": "sha256:05d3c6ff8330670d0a9254e9754ef67a2b041da440d4d392ce11f31b80cf9fb5"
+ },
+ "FilePath": "opt/venv/lib/python3.12/site-packages/uvicorn-0.47.0.dist-info/METADATA",
+ "Digest": "sha1:f55652a6d9d6137b9be4cfc40b4c3d30b63717f8"
+ }
+ ]
+ }
+ ]
+}
diff --git a/scripts/capacity_v2.py b/scripts/capacity_v2.py
new file mode 100644
index 0000000..0e721b2
--- /dev/null
+++ b/scripts/capacity_v2.py
@@ -0,0 +1,57 @@
+"""Conservative capacity worksheet for an OpenRath v2 deployment."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import math
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--peak-runs-per-second", type=float, required=True)
+ parser.add_argument("--mean-run-seconds", type=float, required=True)
+ parser.add_argument("--events-per-run", type=float, default=10)
+ parser.add_argument("--event-kib", type=float, default=2)
+ parser.add_argument("--retention-days", type=int, default=30)
+ parser.add_argument("--worker-concurrency", type=int, default=16)
+ parser.add_argument("--headroom", type=float, default=1.5)
+ args = parser.parse_args()
+ if (
+ min(
+ args.peak_runs_per_second,
+ args.mean_run_seconds,
+ args.events_per_run,
+ args.event_kib,
+ args.worker_concurrency,
+ args.headroom,
+ )
+ <= 0
+ ):
+ parser.error("capacity inputs must be positive")
+ concurrent = args.peak_runs_per_second * args.mean_run_seconds * args.headroom
+ workers = math.ceil(concurrent / args.worker_concurrency)
+ events_per_day = args.peak_runs_per_second * 86400 * args.events_per_run
+ storage_gib = (
+ events_per_day
+ * args.retention_days
+ * args.event_kib
+ * args.headroom
+ / 1024
+ / 1024
+ )
+ report = {
+ "estimated_concurrent_runs": math.ceil(concurrent),
+ "minimum_worker_replicas": max(2, workers),
+ "suggested_postgres_connections": max(20, workers * 4 + 10),
+ "event_storage_gib_before_indexes": round(storage_gib, 2),
+ "warning": (
+ "Worksheet only; validate with the actual workflow/provider mix "
+ "and database benchmark before production."
+ ),
+ }
+ print(json.dumps(report, indent=2))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/export_openapi_v2.py b/scripts/export_openapi_v2.py
new file mode 100644
index 0000000..d338d3c
--- /dev/null
+++ b/scripts/export_openapi_v2.py
@@ -0,0 +1,35 @@
+"""Export the deterministic v2 Agent Server OpenAPI contract."""
+
+from __future__ import annotations
+
+import argparse
+import json
+from pathlib import Path
+
+from rath.server.app import _openapi_document
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "--output",
+ type=Path,
+ default=Path("deploy/docs/openapi-v2.json"),
+ )
+ parser.add_argument("--version", default="2.0.0rc1")
+ args = parser.parse_args()
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(
+ _openapi_document(args.version, store_enabled=True),
+ ensure_ascii=False,
+ indent=2,
+ sort_keys=True,
+ )
+ + "\n",
+ encoding="utf-8",
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/migrate_v1_to_v2.py b/scripts/migrate_v1_to_v2.py
new file mode 100644
index 0000000..ccc5e68
--- /dev/null
+++ b/scripts/migrate_v1_to_v2.py
@@ -0,0 +1,156 @@
+"""Inventory and import v1 JSONL Sessions as immutable v2 legacy Runs."""
+
+from __future__ import annotations
+
+import argparse
+import json
+from pathlib import Path
+from uuid import NAMESPACE_URL, UUID, uuid5
+
+from rath.artifacts import LocalArtifactStore
+from rath.runtime import PostgresRunStore, Run, RunStatus
+from rath.server import PostgresResourceStore, SessionRecord
+from rath.session.persistence.loader import load_session
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--source", type=Path, required=True)
+ parser.add_argument("--report", type=Path, required=True)
+ parser.add_argument("--tenant", required=True)
+ parser.add_argument("--apply", action="store_true")
+ parser.add_argument("--postgres-dsn")
+ parser.add_argument("--schema", default="openrath")
+ parser.add_argument("--artifact-root", type=Path)
+ args = parser.parse_args()
+ source = args.source.expanduser().resolve()
+ if not source.is_dir():
+ parser.error("--source must be an existing v1 sessions directory")
+ if args.apply and (not args.postgres_dsn or not args.artifact_root):
+ parser.error("--apply requires --postgres-dsn and --artifact-root")
+
+ candidates = sorted(
+ [
+ *source.glob("*.jsonl"),
+ *source.glob("*.jsonl.__partial__"),
+ ]
+ )
+ rows: list[dict[str, object]] = []
+ if args.apply:
+ PostgresRunStore.migrate(args.postgres_dsn, schema=args.schema)
+ runtime = (
+ PostgresRunStore(args.postgres_dsn, schema=args.schema) if args.apply else None
+ )
+ resources = PostgresResourceStore(runtime) if runtime is not None else None
+ artifacts = (
+ LocalArtifactStore(args.artifact_root, max_bytes=1024 * 1024 * 1024)
+ if args.apply
+ else None
+ )
+ try:
+ for path in candidates:
+ session_id: UUID | None = None
+ try:
+ session_id = UUID(path.name.split(".jsonl", 1)[0])
+ legacy = load_session(session_id, path=path)
+ row: dict[str, object] = {
+ "session_id": str(session_id),
+ "path": str(path),
+ "closed": legacy.closed,
+ "created_at": legacy.header.created_at.isoformat(),
+ "chunks": len(legacy.chunk_table.rows),
+ "status": "ready",
+ }
+ if (
+ runtime is not None
+ and resources is not None
+ and artifacts is not None
+ ):
+ with path.open("rb") as source_file:
+ artifact = artifacts.put(
+ args.tenant,
+ source_file,
+ media_type="application/x-ndjson",
+ metadata={
+ "provenance": "legacy-import",
+ "legacy_session_id": str(session_id),
+ },
+ )
+ resources.ensure_session(
+ SessionRecord(
+ id=session_id,
+ tenant_id=args.tenant,
+ created_at=legacy.header.created_at,
+ )
+ )
+ run = Run.create(
+ id=uuid5(NAMESPACE_URL, f"openrath:v1:{session_id}"),
+ plan_id=uuid5(NAMESPACE_URL, "openrath:v1:transcript-import"),
+ revision_id=uuid5(NAMESPACE_URL, "openrath:v1.3.0"),
+ session_id=session_id,
+ tenant_id=args.tenant,
+ status=(
+ RunStatus.SUCCEEDED
+ if legacy.closed
+ else RunStatus.NEEDS_REVIEW
+ ),
+ state={
+ "legacy": True,
+ "resumable": False,
+ "artifact_uri": artifact.uri,
+ "chunk_count": len(legacy.chunk_table.rows),
+ "trust": "untrusted",
+ "provenance": "legacy-import",
+ },
+ idempotency_key=f"legacy-session:{session_id}",
+ context={
+ "migration": "v1-to-v2",
+ "provenance": "legacy-import",
+ },
+ )
+ runtime.create_run(run)
+ row["status"] = "imported"
+ row["run_id"] = str(run.id)
+ row["artifact_uri"] = artifact.uri
+ rows.append(row)
+ except Exception as exc:
+ rows.append(
+ {
+ "session_id": (
+ str(session_id) if session_id is not None else None
+ ),
+ "path": str(path),
+ "status": "invalid",
+ "error_code": (
+ "invalid_session_id"
+ if session_id is None
+ else "invalid_session"
+ ),
+ "error": f"{type(exc).__name__}: {exc}",
+ }
+ )
+ finally:
+ if runtime is not None:
+ runtime.close()
+
+ report = {
+ "schema": "openrath.v2.migration-report/1",
+ "mode": "apply" if args.apply else "inventory",
+ "source": str(source),
+ "tenant": args.tenant,
+ "summary": {
+ "total": len(rows),
+ "ready": sum(item["status"] == "ready" for item in rows),
+ "imported": sum(item["status"] == "imported" for item in rows),
+ "invalid": sum(item["status"] == "invalid" for item in rows),
+ },
+ "sessions": rows,
+ }
+ args.report.parent.mkdir(parents=True, exist_ok=True)
+ args.report.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8"
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/build_drill_report.py b/scripts/release/build_drill_report.py
new file mode 100644
index 0000000..a330877
--- /dev/null
+++ b/scripts/release/build_drill_report.py
@@ -0,0 +1,143 @@
+"""Build the OpenRath GA drill gate from operator-controlled target exercises."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import re
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+
+try:
+ from .record_gate import build_report as build_gate_report
+except ImportError: # pragma: no cover - direct script execution
+ from record_gate import build_report as build_gate_report
+
+FAULT_DRILLS = frozenset(
+ {
+ "postgresql_failure",
+ "redis_failure",
+ "s3_failure",
+ "api_failure",
+ "worker_failure",
+ }
+)
+REQUIRED_DRILLS = FAULT_DRILLS | {"backup_restore", "rollout_rollback"}
+
+
+def _object(path: Path) -> dict[str, Any]:
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, dict):
+ raise ValueError(f"drill results must be a JSON object: {path}")
+ return value
+
+
+def _timestamp(value: object, *, field: str, drill: str) -> datetime:
+ if not isinstance(value, str) or not value:
+ raise ValueError(f"drill {drill} requires {field}")
+ try:
+ parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
+ except ValueError as error:
+ raise ValueError(f"drill {drill} has invalid {field}") from error
+ if parsed.tzinfo is None:
+ raise ValueError(f"drill {drill} {field} requires a timezone")
+ return parsed
+
+
+def _validate_drill(name: str, value: object) -> None:
+ if not isinstance(value, dict):
+ raise ValueError(f"drill result must be an object: {name}")
+ if value.get("status") != "passed":
+ raise ValueError(f"drill did not pass: {name}")
+ for field in ("operator", "observed"):
+ if not isinstance(value.get(field), str) or not value[field]:
+ raise ValueError(f"drill {name} requires {field}")
+ started = _timestamp(value.get("started_at"), field="started_at", drill=name)
+ completed = _timestamp(value.get("completed_at"), field="completed_at", drill=name)
+ if completed < started:
+ raise ValueError(f"drill {name} completion precedes its start")
+ recovery = value.get("recovery_seconds")
+ if (
+ isinstance(recovery, bool)
+ or not isinstance(recovery, (int, float))
+ or recovery < 0
+ ):
+ raise ValueError(f"drill {name} requires non-negative recovery_seconds")
+ if value.get("data_loss_records") != 0:
+ raise ValueError(f"drill {name} reports data loss")
+ if name == "backup_restore" and recovery > 3600:
+ raise ValueError("backup_restore recovery_seconds must not exceed 3600")
+
+
+def build_report(
+ *,
+ results_path: Path,
+ evidence_paths: list[Path],
+ evidence_root: Path,
+ generated_at: str | None = None,
+) -> dict[str, Any]:
+ """Validate the complete target drill matrix and bind its logs."""
+ results = _object(results_path)
+ if results.get("schema") != "openrath.v2.drill-results/1":
+ raise ValueError("unsupported drill results schema")
+ source_commit = results.get("source_commit")
+ if (
+ not isinstance(source_commit, str)
+ or re.fullmatch(r"[0-9a-f]{40}", source_commit) is None
+ ):
+ raise ValueError("drill results require a valid source_commit")
+ profile = results.get("environment_profile")
+ if not isinstance(profile, str) or not profile:
+ raise ValueError("drill results require an environment_profile")
+ drills = results.get("drills")
+ if not isinstance(drills, dict):
+ raise ValueError("drill results require a drills object")
+ missing = sorted(REQUIRED_DRILLS - set(drills))
+ if missing:
+ raise ValueError("missing drills: " + ", ".join(missing))
+ for name in sorted(REQUIRED_DRILLS):
+ _validate_drill(name, drills[name])
+
+ return build_gate_report(
+ gate="drills",
+ source_commit=source_commit,
+ environment={"profile": profile, "target_like": True},
+ details={
+ "fault_matrix": "passed",
+ "backup_restore": "passed",
+ "rollout_rollback": "passed",
+ },
+ evidence_root=evidence_root,
+ evidence_files=[results_path, *evidence_paths],
+ open_risks=[],
+ generated_at=generated_at
+ or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
+ )
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--results", type=Path, required=True)
+ parser.add_argument("--evidence-root", type=Path, required=True)
+ parser.add_argument("--evidence-file", type=Path, action="append", default=[])
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ try:
+ report = build_report(
+ results_path=args.results,
+ evidence_paths=args.evidence_file,
+ evidence_root=args.evidence_root,
+ )
+ except (OSError, ValueError, json.JSONDecodeError) as error:
+ raise SystemExit(str(error)) from error
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+ print(f"recorded drills Gate C report at {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/build_evidence.py b/scripts/release/build_evidence.py
new file mode 100644
index 0000000..be5bdf5
--- /dev/null
+++ b/scripts/release/build_evidence.py
@@ -0,0 +1,328 @@
+"""Build a SHA-bound OpenRath RC or GA evidence manifest."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import os
+import re
+import subprocess
+from datetime import datetime, timezone
+from pathlib import Path
+
+RELEASE_SCHEMA = "openrath.release-evidence/2"
+RC_BLOCKING_GATES = (
+ "approved live LLM/provider lifecycle",
+ "approved live OpenViking lifecycle",
+ "target-like capacity and one-to-four worker scaling",
+ "eight-hour target-like soak",
+ "target-cluster backup/restore and rollout/rollback drills",
+ "final API stability, v1 maintenance window, and GA owner approval",
+)
+GA_RELEASE_ACTIONS = frozenset(
+ {
+ "pypi",
+ "ghcr",
+ "github_release",
+ }
+)
+GA_REQUIRED_ARTIFACTS = frozenset(
+ {
+ "approval",
+ "tests",
+ "live_adapters",
+ "performance",
+ "soak",
+ "drills",
+ "compatibility",
+ "sbom",
+ "image_scan",
+ "secret_scan",
+ "dependency_audit_production",
+ "dependency_audit_all",
+ "kubernetes",
+ }
+)
+
+
+def infer_release_stage(version: str) -> str:
+ """Return the only supported release stage for a v2.0.0 version."""
+ if re.fullmatch(r"2\.0\.0rc[1-9][0-9]*", version):
+ return "rc"
+ if version == "2.0.0":
+ return "ga"
+ raise ValueError(f"unsupported release version: {version!r}")
+
+
+def load_ga_approval(
+ path: Path,
+ *,
+ version: str,
+ commit: str,
+ repository: str | None = None,
+ workflow_run_id: str | None = None,
+) -> dict[str, object]:
+ """Load and validate an explicit owner approval bound to the GA SHA."""
+ approval = json.loads(path.read_text(encoding="utf-8"))
+ if approval.get("schema") != "openrath.ga-approval/1":
+ raise ValueError("GA approval schema must be openrath.ga-approval/1")
+ if approval.get("version") != version:
+ raise ValueError("GA approval version does not match the release")
+ if approval.get("source_commit") != commit:
+ raise ValueError("GA approval source_commit does not match HEAD")
+ if approval.get("approved") is not True:
+ raise ValueError("GA approval must set approved=true")
+ if approval.get("environment") != "ga-release":
+ raise ValueError("GA approval environment must be ga-release")
+ approval_repository = approval.get("repository")
+ if (
+ not isinstance(approval_repository, str)
+ or re.fullmatch(r"[^/\s]+/[^/\s]+", approval_repository) is None
+ ):
+ raise ValueError("GA approval repository must be owner/name")
+ if repository is not None and approval.get("repository") != repository:
+ raise ValueError("GA approval repository does not match the workflow")
+ approval_run_id = approval.get("workflow_run_id")
+ if re.fullmatch(r"[1-9][0-9]*", str(approval_run_id or "")) is None:
+ raise ValueError("GA approval workflow_run_id must be a positive integer")
+ if (
+ workflow_run_id is not None
+ and approval.get("workflow_run_id") != workflow_run_id
+ ):
+ raise ValueError("GA approval workflow_run_id does not match the workflow")
+ requested_by = approval.get("requested_by")
+ if not isinstance(requested_by, str) or not requested_by.strip():
+ raise ValueError("GA approval requires requested_by")
+ approvers = approval.get("approvers")
+ if (
+ not isinstance(approvers, list)
+ or not approvers
+ or any(not isinstance(item, str) or not item.strip() for item in approvers)
+ or len(set(approvers)) != len(approvers)
+ ):
+ raise ValueError("GA approval requires unique non-empty approvers")
+ environment_reviews = approval.get("environment_reviews")
+ if not isinstance(environment_reviews, list) or not environment_reviews:
+ raise ValueError("GA approval requires environment reviews")
+ review_approvers: set[str] = set()
+ review_ids: set[str] = set()
+ review_times: list[datetime] = []
+ for review in environment_reviews:
+ if not isinstance(review, dict):
+ raise ValueError("GA approval environment review must be an object")
+ review_id = str(review.get("review_id", ""))
+ if re.fullmatch(r"[1-9][0-9]*", review_id) is None:
+ raise ValueError("GA approval review_id must be a positive integer")
+ if review_id in review_ids:
+ raise ValueError("GA approval review ids must be unique")
+ review_ids.add(review_id)
+ reviewer = review.get("reviewer")
+ if not isinstance(reviewer, str) or not reviewer.strip():
+ raise ValueError("GA approval environment review requires reviewer")
+ review_approvers.add(reviewer)
+ review_approved_at = review.get("approved_at")
+ if not isinstance(review_approved_at, str):
+ raise ValueError("GA approval environment review requires approved_at")
+ try:
+ parsed_review_time = datetime.fromisoformat(
+ review_approved_at.replace("Z", "+00:00")
+ )
+ except ValueError as error:
+ raise ValueError(
+ "GA approval environment review approved_at must be ISO 8601"
+ ) from error
+ if parsed_review_time.tzinfo is None:
+ raise ValueError(
+ "GA approval environment review approved_at requires a timezone"
+ )
+ review_times.append(parsed_review_time)
+ if review_approvers != set(approvers):
+ raise ValueError("GA approval approvers do not match environment reviews")
+ approved_at = approval.get("approved_at")
+ if not isinstance(approved_at, str):
+ raise ValueError("GA approval requires approved_at")
+ try:
+ parsed_approved_at = datetime.fromisoformat(approved_at.replace("Z", "+00:00"))
+ except ValueError as error:
+ raise ValueError("GA approval approved_at must be ISO 8601") from error
+ if parsed_approved_at.tzinfo is None:
+ raise ValueError("GA approval approved_at must include a timezone")
+ if parsed_approved_at != max(review_times):
+ raise ValueError("GA approval approved_at must match the latest review")
+ actions = approval.get("actions")
+ if not isinstance(actions, dict):
+ raise ValueError("GA approval requires release actions")
+ missing_actions = sorted(
+ action for action in GA_RELEASE_ACTIONS if actions.get(action) is not True
+ )
+ if missing_actions:
+ raise ValueError(
+ "GA approval is missing affirmative actions: " + ", ".join(missing_actions)
+ )
+ unexpected_actions = sorted(set(actions) - GA_RELEASE_ACTIONS)
+ if unexpected_actions:
+ raise ValueError(
+ "GA approval contains unsupported actions: " + ", ".join(unexpected_actions)
+ )
+ return approval
+
+
+def require_ga_artifacts(names: set[str]) -> None:
+ """Fail unless every GA evidence category is present."""
+ missing = sorted(GA_REQUIRED_ARTIFACTS - names)
+ if missing:
+ raise ValueError("GA evidence is missing artifacts: " + ", ".join(missing))
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def _project_version() -> str:
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ match = re.search(r'^version = "([^"]+)"$', text, flags=re.MULTILINE)
+ if match is None:
+ raise RuntimeError("project version is missing from pyproject.toml")
+ return match.group(1)
+
+
+def _git(*arguments: str) -> str:
+ return subprocess.check_output(
+ ["git", *arguments],
+ text=True,
+ encoding="utf-8",
+ ).strip()
+
+
+def _artifact(path: Path) -> dict[str, object]:
+ if not path.is_file():
+ raise FileNotFoundError(path)
+ return {
+ "path": path.as_posix(),
+ "size": path.stat().st_size,
+ "sha256": _sha256(path),
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--tag", required=True)
+ parser.add_argument("--stage", choices=("rc", "ga"))
+ parser.add_argument("--approval", type=Path)
+ parser.add_argument("--image-ref", required=True)
+ parser.add_argument("--image-digest", required=True)
+ parser.add_argument("--output", type=Path, required=True)
+ parser.add_argument(
+ "--artifact",
+ action="append",
+ default=[],
+ metavar="NAME=PATH",
+ help="additional report or artifact to hash",
+ )
+ args = parser.parse_args()
+
+ version = _project_version()
+ if args.tag != f"v{version}":
+ raise SystemExit(f"tag {args.tag!r} does not match project version {version!r}")
+ try:
+ release_stage = infer_release_stage(version)
+ except ValueError as error:
+ raise SystemExit(str(error)) from error
+ if args.stage is not None and args.stage != release_stage:
+ raise SystemExit(
+ f"stage {args.stage!r} does not match release version {version!r}"
+ )
+ if re.fullmatch(r"sha256:[0-9a-f]{64}", args.image_digest) is None:
+ raise SystemExit("image digest must be sha256 followed by 64 lowercase hex")
+
+ commit = _git("rev-parse", "HEAD")
+ wheel = next(Path("dist").glob(f"openrath-{version}-*.whl"))
+ sdist = Path("dist") / f"openrath-{version}.tar.gz"
+ artifacts: dict[str, object] = {
+ "wheel": _artifact(wheel),
+ "sdist": _artifact(sdist),
+ "openapi": _artifact(Path("deploy/docs/openapi-v2.json")),
+ "image": {
+ "reference": args.image_ref,
+ "digest": args.image_digest,
+ },
+ }
+ for item in args.artifact:
+ name, separator, raw_path = item.partition("=")
+ if not separator or not name or not raw_path:
+ raise SystemExit(f"invalid --artifact value: {item!r}")
+ if name in artifacts:
+ raise SystemExit(f"duplicate artifact name: {name}")
+ artifacts[name] = _artifact(Path(raw_path))
+
+ approval_summary: dict[str, object] | None = None
+ if release_stage == "ga":
+ if args.approval is None:
+ raise SystemExit("GA evidence requires --approval")
+ try:
+ approval = load_ga_approval(
+ args.approval,
+ version=version,
+ commit=commit,
+ repository=os.getenv("GITHUB_REPOSITORY"),
+ workflow_run_id=os.getenv("GITHUB_RUN_ID"),
+ )
+ except (OSError, ValueError, json.JSONDecodeError) as error:
+ raise SystemExit(f"invalid GA approval: {error}") from error
+ if "approval" in artifacts:
+ raise SystemExit("approval artifact is reserved for --approval")
+ artifacts["approval"] = _artifact(args.approval)
+ try:
+ require_ga_artifacts(set(artifacts))
+ except ValueError as error:
+ raise SystemExit(str(error)) from error
+ approval_summary = {
+ "approvers": approval["approvers"],
+ "requested_by": approval["requested_by"],
+ "approved_at": approval["approved_at"],
+ "environment": approval["environment"],
+ "workflow_run_id": approval["workflow_run_id"],
+ "source_commit": approval["source_commit"],
+ "actions": approval["actions"],
+ }
+ blocking_gates: list[str] = []
+ else:
+ if args.approval is not None:
+ raise SystemExit("--approval is only valid for a GA release")
+ blocking_gates = list(RC_BLOCKING_GATES)
+
+ tracked_status = _git("status", "--porcelain", "--untracked-files=no")
+ manifest = {
+ "schema": RELEASE_SCHEMA,
+ "generated_at": datetime.now(timezone.utc).isoformat(),
+ "release_stage": release_stage,
+ "version": version,
+ "tag": args.tag,
+ "source_commit": commit,
+ "source_tree_clean": not tracked_status,
+ "base_commit": _git("merge-base", "HEAD", "origin/main"),
+ "ga_approved": release_stage == "ga",
+ "workflow": {
+ "repository": os.getenv("GITHUB_REPOSITORY"),
+ "run_id": os.getenv("GITHUB_RUN_ID"),
+ "run_attempt": os.getenv("GITHUB_RUN_ATTEMPT"),
+ },
+ "artifacts": artifacts,
+ "blocking_gates": blocking_gates,
+ }
+ if approval_summary is not None:
+ manifest["approval"] = approval_summary
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/build_performance_report.py b/scripts/release/build_performance_report.py
new file mode 100644
index 0000000..e932431
--- /dev/null
+++ b/scripts/release/build_performance_report.py
@@ -0,0 +1,164 @@
+"""Combine target load samples into the OpenRath GA performance gate report."""
+
+from __future__ import annotations
+
+import argparse
+import json
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+
+try:
+ from .record_gate import build_report as build_gate_report
+except ImportError: # pragma: no cover - direct script execution
+ from record_gate import build_report as build_gate_report
+
+REQUIRED_PROFILES = {
+ ("single_host", 1),
+ ("split", 1),
+ ("split", 2),
+ ("split", 4),
+}
+
+
+def _load_sample(path: Path) -> dict[str, Any]:
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, dict):
+ raise ValueError(f"load sample must be a JSON object: {path}")
+ if value.get("schema") != "openrath.v2.load-sample/1":
+ raise ValueError(f"unsupported load sample schema: {path}")
+ return value
+
+
+def build_report(
+ *,
+ sample_paths: list[Path],
+ evidence_root: Path,
+ environment_profile: str,
+ minimum_sample_seconds: float = 300,
+ generated_at: str | None = None,
+) -> dict[str, Any]:
+ """Build a passing report from single-host and 1/2/4-worker split samples."""
+ if len(sample_paths) != 4:
+ raise ValueError("exactly four load samples are required")
+ samples: dict[tuple[str, int], dict[str, Any]] = {}
+ commits: set[str] = set()
+ for path in sample_paths:
+ sample = _load_sample(path)
+ profile = sample.get("profile")
+ replicas = sample.get("worker_replicas")
+ if (
+ not isinstance(profile, str)
+ or isinstance(replicas, bool)
+ or not isinstance(replicas, int)
+ ):
+ raise ValueError(f"invalid profile or worker count: {path}")
+ key = (profile, replicas)
+ if key in samples:
+ raise ValueError(f"duplicate load profile: {profile}/{replicas}")
+ samples[key] = sample
+ commit = sample.get("source_commit")
+ if not isinstance(commit, str):
+ raise ValueError(f"load sample source_commit is missing: {path}")
+ commits.add(commit)
+ if sample.get("target_like") is not True:
+ raise ValueError(f"load sample is not target-like: {path}")
+ if sample.get("errors") != 0:
+ raise ValueError("performance samples must contain zero errors")
+ completed = sample.get("completed_runs")
+ if (
+ isinstance(completed, bool)
+ or not isinstance(completed, int)
+ or completed < 1
+ ):
+ raise ValueError("performance samples require at least one completed run")
+ duration = sample.get("duration_seconds")
+ if (
+ isinstance(duration, bool)
+ or not isinstance(duration, (int, float))
+ or duration < minimum_sample_seconds
+ ):
+ raise ValueError(
+ f"performance sample must run at least {minimum_sample_seconds} seconds"
+ )
+ throughput = sample.get("throughput_runs_per_second")
+ if (
+ isinstance(throughput, bool)
+ or not isinstance(throughput, (int, float))
+ or throughput <= 0
+ ):
+ raise ValueError(f"load sample throughput is missing: {path}")
+ if set(samples) != REQUIRED_PROFILES:
+ raise ValueError("samples must cover single-host and split 1/2/4 workers")
+ if len(commits) != 1:
+ raise ValueError("all performance samples must use the same source commit")
+
+ split_one = float(samples[("split", 1)]["throughput_runs_per_second"])
+ split_two = float(samples[("split", 2)]["throughput_runs_per_second"])
+ split_four = float(samples[("split", 4)]["throughput_runs_per_second"])
+ if split_one <= 0:
+ raise ValueError("one-worker throughput must be positive")
+ two_efficiency = split_two / (split_one * 2)
+ four_efficiency = split_four / (split_one * 4)
+ if four_efficiency < 0.70:
+ raise ValueError("four-worker scaling efficiency must be at least 0.70")
+
+ details: dict[str, object] = {
+ "single_host": "passed",
+ "split_profile": "passed",
+ "worker_scaling_efficiency": four_efficiency,
+ "two_worker_scaling_efficiency": two_efficiency,
+ "throughput_runs_per_second": {
+ f"{profile}_{replicas}": sample["throughput_runs_per_second"]
+ for (profile, replicas), sample in sorted(samples.items())
+ },
+ }
+ source_commit = commits.pop()
+ return build_gate_report(
+ gate="performance",
+ source_commit=source_commit,
+ environment={"profile": environment_profile, "target_like": True},
+ details=details,
+ evidence_root=evidence_root,
+ evidence_files=sample_paths,
+ open_risks=[],
+ generated_at=generated_at
+ or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
+ )
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--single-host", type=Path, required=True)
+ parser.add_argument("--split-one", type=Path, required=True)
+ parser.add_argument("--split-two", type=Path, required=True)
+ parser.add_argument("--split-four", type=Path, required=True)
+ parser.add_argument("--evidence-root", type=Path, required=True)
+ parser.add_argument("--environment-profile", required=True)
+ parser.add_argument("--minimum-sample-seconds", type=float, default=300)
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ try:
+ report = build_report(
+ sample_paths=[
+ args.single_host,
+ args.split_one,
+ args.split_two,
+ args.split_four,
+ ],
+ evidence_root=args.evidence_root,
+ environment_profile=args.environment_profile,
+ minimum_sample_seconds=args.minimum_sample_seconds,
+ )
+ except (OSError, ValueError, json.JSONDecodeError) as error:
+ raise SystemExit(str(error)) from error
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+ print(f"recorded performance Gate C report at {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/build_soak_report.py b/scripts/release/build_soak_report.py
new file mode 100644
index 0000000..7c8eead
--- /dev/null
+++ b/scripts/release/build_soak_report.py
@@ -0,0 +1,148 @@
+"""Build the OpenRath GA soak gate from target load and resource evidence."""
+
+from __future__ import annotations
+
+import argparse
+import json
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+
+try:
+ from .record_gate import build_report as build_gate_report
+except ImportError: # pragma: no cover - direct script execution
+ from record_gate import build_report as build_gate_report
+
+
+def _object(path: Path) -> dict[str, Any]:
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, dict):
+ raise ValueError(f"evidence must be a JSON object: {path}")
+ return value
+
+
+def _same_commit(source_commit: object, *values: dict[str, Any]) -> str:
+ if not isinstance(source_commit, str):
+ raise ValueError("soak sample source_commit is missing")
+ if any(value.get("source_commit") != source_commit for value in values):
+ raise ValueError("all soak evidence must use the same source commit")
+ return source_commit
+
+
+def build_report(
+ *,
+ sample_path: Path,
+ before_snapshot_path: Path,
+ after_snapshot_path: Path,
+ assessment_path: Path,
+ evidence_root: Path,
+ environment_profile: str,
+ generated_at: str | None = None,
+) -> dict[str, Any]:
+ """Require an eight-hour error-free target run and an explained resource delta."""
+ sample = _object(sample_path)
+ before = _object(before_snapshot_path)
+ after = _object(after_snapshot_path)
+ assessment = _object(assessment_path)
+ if sample.get("schema") != "openrath.v2.load-sample/1":
+ raise ValueError("unsupported soak load sample schema")
+ if sample.get("target_like") is not True or sample.get("profile") != "split":
+ raise ValueError("soak sample must use the target-like split profile")
+ source_commit = _same_commit(
+ sample.get("source_commit"),
+ before,
+ after,
+ assessment,
+ )
+ snapshot_components: list[set[str]] = []
+ for snapshot, phase in ((before, "before"), (after, "after")):
+ if snapshot.get("schema") != "openrath.v2.resource-snapshot/1":
+ raise ValueError(f"unsupported {phase} resource snapshot schema")
+ if snapshot.get("phase") != phase:
+ raise ValueError(f"resource snapshot phase must be {phase}")
+ components = snapshot.get("components")
+ if not isinstance(components, dict) or not components:
+ raise ValueError(f"{phase} resource snapshot requires components")
+ if any(not isinstance(value, dict) for value in components.values()):
+ raise ValueError(f"{phase} resource snapshot components must be objects")
+ snapshot_components.append(set(components))
+ if snapshot_components[0] != snapshot_components[1]:
+ raise ValueError("resource snapshots must contain the same components")
+ if assessment.get("schema") != "openrath.v2.resource-assessment/1":
+ raise ValueError("unsupported resource assessment schema")
+ if (
+ not isinstance(assessment.get("assessor"), str)
+ or not assessment["assessor"]
+ or not isinstance(assessment.get("rationale"), str)
+ or not assessment["rationale"]
+ ):
+ raise ValueError("resource assessment requires an assessor and rationale")
+ if assessment.get("unexplained_resource_growth") is not False:
+ raise ValueError("soak evidence contains unexplained resource growth")
+ duration = sample.get("duration_seconds")
+ if (
+ isinstance(duration, bool)
+ or not isinstance(duration, (int, float))
+ or duration < 28800
+ ):
+ raise ValueError("soak duration_seconds must be at least 28800")
+ if sample.get("errors") != 0:
+ raise ValueError("soak sample must contain zero errors")
+
+ details: dict[str, object] = {
+ "duration_seconds": duration,
+ "errors": 0,
+ "unexplained_resource_growth": False,
+ "completed_runs": sample.get("completed_runs"),
+ "resource_assessor": assessment["assessor"],
+ "resource_rationale": assessment["rationale"],
+ }
+ return build_gate_report(
+ gate="soak",
+ source_commit=source_commit,
+ environment={"profile": environment_profile, "target_like": True},
+ details=details,
+ evidence_root=evidence_root,
+ evidence_files=[
+ sample_path,
+ before_snapshot_path,
+ after_snapshot_path,
+ assessment_path,
+ ],
+ open_risks=[],
+ generated_at=generated_at
+ or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
+ )
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--sample", type=Path, required=True)
+ parser.add_argument("--before-snapshot", type=Path, required=True)
+ parser.add_argument("--after-snapshot", type=Path, required=True)
+ parser.add_argument("--assessment", type=Path, required=True)
+ parser.add_argument("--evidence-root", type=Path, required=True)
+ parser.add_argument("--environment-profile", required=True)
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ try:
+ report = build_report(
+ sample_path=args.sample,
+ before_snapshot_path=args.before_snapshot,
+ after_snapshot_path=args.after_snapshot,
+ assessment_path=args.assessment,
+ evidence_root=args.evidence_root,
+ environment_profile=args.environment_profile,
+ )
+ except (OSError, ValueError, json.JSONDecodeError) as error:
+ raise SystemExit(str(error)) from error
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+ print(f"recorded soak Gate C report at {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/create_ga_approval.py b/scripts/release/create_ga_approval.py
new file mode 100644
index 0000000..93645ad
--- /dev/null
+++ b/scripts/release/create_ga_approval.py
@@ -0,0 +1,131 @@
+"""Create a workflow-bound GA approval record after environment approval."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import re
+from datetime import datetime
+from pathlib import Path
+
+GA_ACTIONS = {
+ "pypi": True,
+ "ghcr": True,
+ "github_release": True,
+}
+GA_ENVIRONMENT = "ga-release"
+
+
+def _environment_reviews(path: Path) -> list[dict[str, str]]:
+ """Extract approved GA environment reviews from GitHub's run history."""
+ history = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(history, list):
+ raise ValueError("review history must be a JSON array")
+
+ reviews: list[dict[str, str]] = []
+ for review in history:
+ if not isinstance(review, dict) or review.get("state") != "approved":
+ continue
+ environments = review.get("environments")
+ if not isinstance(environments, list) or not any(
+ isinstance(environment, dict) and environment.get("name") == GA_ENVIRONMENT
+ for environment in environments
+ ):
+ continue
+ review_id = review.get("id")
+ user = review.get("user")
+ created_at = review.get("created_at")
+ reviewer = user.get("login") if isinstance(user, dict) else None
+ if not isinstance(review_id, int) or review_id < 1:
+ raise ValueError("approved review requires a positive integer id")
+ if not isinstance(reviewer, str) or not reviewer.strip():
+ raise ValueError("approved review requires user.login")
+ if not isinstance(created_at, str):
+ raise ValueError("approved review requires created_at")
+ try:
+ parsed = datetime.fromisoformat(created_at.replace("Z", "+00:00"))
+ except ValueError as error:
+ raise ValueError("approved review created_at must be ISO 8601") from error
+ if parsed.tzinfo is None:
+ raise ValueError("approved review created_at must include a timezone")
+ reviews.append(
+ {
+ "review_id": str(review_id),
+ "reviewer": reviewer,
+ "approved_at": created_at,
+ }
+ )
+
+ if not reviews:
+ raise ValueError(f"no approved {GA_ENVIRONMENT} environment review found")
+ review_ids = [review["review_id"] for review in reviews]
+ if len(set(review_ids)) != len(review_ids):
+ raise ValueError("approved environment review ids must be unique")
+ return sorted(reviews, key=lambda item: (item["approved_at"], item["review_id"]))
+
+
+def build_approval(
+ *,
+ version: str,
+ source_commit: str,
+ requested_by: str,
+ repository: str,
+ workflow_run_id: str,
+ review_history: Path,
+) -> dict[str, object]:
+ """Build an approval record bound to one protected workflow run."""
+ if version != "2.0.0":
+ raise ValueError("GA approval version must be 2.0.0")
+ if re.fullmatch(r"[0-9a-f]{40}", source_commit) is None:
+ raise ValueError("source_commit must be 40 lowercase hexadecimal characters")
+ if not requested_by.strip():
+ raise ValueError("requested_by is required")
+ if not repository.strip():
+ raise ValueError("repository is required")
+ if re.fullmatch(r"[1-9][0-9]*", workflow_run_id) is None:
+ raise ValueError("workflow_run_id must be a positive integer")
+ environment_reviews = _environment_reviews(review_history)
+ approvers = sorted({review["reviewer"] for review in environment_reviews})
+ return {
+ "schema": "openrath.ga-approval/1",
+ "version": version,
+ "source_commit": source_commit,
+ "approved": True,
+ "approved_at": environment_reviews[-1]["approved_at"],
+ "approvers": approvers,
+ "requested_by": requested_by,
+ "environment": GA_ENVIRONMENT,
+ "environment_reviews": environment_reviews,
+ "repository": repository,
+ "workflow_run_id": workflow_run_id,
+ "actions": dict(GA_ACTIONS),
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--version", required=True)
+ parser.add_argument("--source-commit", required=True)
+ parser.add_argument("--requested-by", required=True)
+ parser.add_argument("--repository", required=True)
+ parser.add_argument("--workflow-run-id", required=True)
+ parser.add_argument("--review-history", type=Path, required=True)
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ approval = build_approval(
+ version=args.version,
+ source_commit=args.source_commit,
+ requested_by=args.requested_by,
+ repository=args.repository,
+ workflow_run_id=args.workflow_run_id,
+ review_history=args.review_history,
+ )
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(approval, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/load_v2.py b/scripts/release/load_v2.py
new file mode 100644
index 0000000..3c1da5a
--- /dev/null
+++ b/scripts/release/load_v2.py
@@ -0,0 +1,259 @@
+"""Run bounded authenticated lifecycle load against a deployed OpenRath API."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import math
+import os
+import re
+import threading
+import time
+from concurrent.futures import ThreadPoolExecutor
+from dataclasses import dataclass
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+from urllib.parse import urlsplit
+from uuid import uuid4
+
+import httpx
+
+
+@dataclass(frozen=True)
+class LoadConfig:
+ """Inputs for one immutable target load sample."""
+
+ base_url: str
+ token: str
+ source_commit: str
+ profile: str
+ worker_replicas: int
+ concurrency: int
+ duration_seconds: float
+ max_runs: int | None
+ poll_interval_seconds: float
+ request_timeout_seconds: float
+ run_timeout_seconds: float
+ target_like: bool
+
+
+def _origin(value: str) -> str:
+ parsed = urlsplit(value)
+ if (
+ parsed.scheme not in {"http", "https"}
+ or not parsed.hostname
+ or parsed.username
+ or parsed.password
+ or parsed.query
+ or parsed.fragment
+ ):
+ raise ValueError("base URL must be an HTTP(S) origin without credentials")
+ port = f":{parsed.port}" if parsed.port is not None else ""
+ return f"{parsed.scheme}://{parsed.hostname}{port}"
+
+
+def _percentile(values: list[float], percentile: float) -> float:
+ if not values:
+ return 0.0
+ ordered = sorted(values)
+ index = max(0, math.ceil(percentile * len(ordered)) - 1)
+ return ordered[index]
+
+
+def _lifecycle(
+ client: httpx.Client,
+ *,
+ poll_interval_seconds: float,
+ run_timeout_seconds: float,
+) -> tuple[bool, str | None, float]:
+ started = time.perf_counter()
+ try:
+ session = client.post("/v1/sessions")
+ session.raise_for_status()
+ session_id = session.json()["id"]
+ run = client.post(
+ "/v1/runs",
+ headers={"Idempotency-Key": f"ga-load-{uuid4()}"},
+ json={
+ "assistant_id": "echo",
+ "session_id": session_id,
+ "state": {"gate_c": True},
+ },
+ )
+ run.raise_for_status()
+ run_id = run.json()["id"]
+ deadline = time.monotonic() + run_timeout_seconds
+ while True:
+ response = client.get(f"/v1/runs/{run_id}")
+ response.raise_for_status()
+ status = response.json().get("status")
+ if status == "succeeded":
+ return True, None, time.perf_counter() - started
+ if status in {"failed", "cancelled", "needs_review"}:
+ return False, f"run_{status}", time.perf_counter() - started
+ if time.monotonic() >= deadline:
+ return False, "run_timeout", time.perf_counter() - started
+ time.sleep(poll_interval_seconds)
+ except httpx.HTTPStatusError as error:
+ return (
+ False,
+ f"http_{error.response.status_code}",
+ time.perf_counter() - started,
+ )
+ except httpx.TimeoutException:
+ return False, "request_timeout", time.perf_counter() - started
+ except (httpx.HTTPError, KeyError, TypeError, ValueError) as error:
+ return False, type(error).__name__, time.perf_counter() - started
+
+
+def _validate(config: LoadConfig) -> str:
+ if re.fullmatch(r"[0-9a-f]{40}", config.source_commit) is None:
+ raise ValueError("source_commit must be 40 lowercase hexadecimal characters")
+ if config.profile not in {"single_host", "split"}:
+ raise ValueError("profile must be single_host or split")
+ if config.worker_replicas < 1 or config.concurrency < 1:
+ raise ValueError("worker replicas and concurrency must be positive")
+ if config.duration_seconds <= 0:
+ raise ValueError("duration_seconds must be positive")
+ if config.max_runs is not None and config.max_runs < 1:
+ raise ValueError("max_runs must be positive")
+ if config.poll_interval_seconds < 0:
+ raise ValueError("poll_interval_seconds must be non-negative")
+ if config.request_timeout_seconds <= 0 or config.run_timeout_seconds <= 0:
+ raise ValueError("request and run timeouts must be positive")
+ if not config.token:
+ raise ValueError("an authentication token is required")
+ origin = _origin(config.base_url)
+ if config.target_like and not origin.startswith("https://"):
+ raise ValueError("target-like load requires an HTTPS base URL")
+ return origin
+
+
+def run_sample(
+ config: LoadConfig,
+ *,
+ transport: httpx.BaseTransport | None = None,
+) -> dict[str, Any]:
+ """Execute lifecycles until the duration or maximum run count is reached."""
+ target_origin = _validate(config)
+ started = time.perf_counter()
+ deadline = started + config.duration_seconds
+ lock = threading.Lock()
+ reserved = 0
+ completed = 0
+ errors: dict[str, int] = {}
+ latencies: list[float] = []
+
+ def worker() -> None:
+ nonlocal reserved, completed
+ with httpx.Client(
+ base_url=target_origin,
+ headers={"Authorization": f"Bearer {config.token}"},
+ timeout=config.request_timeout_seconds,
+ transport=transport,
+ trust_env=False,
+ ) as client:
+ while True:
+ with lock:
+ if time.perf_counter() >= deadline or (
+ config.max_runs is not None and reserved >= config.max_runs
+ ):
+ return
+ reserved += 1
+ success, error, latency = _lifecycle(
+ client,
+ poll_interval_seconds=config.poll_interval_seconds,
+ run_timeout_seconds=config.run_timeout_seconds,
+ )
+ with lock:
+ latencies.append(latency)
+ if success:
+ completed += 1
+ else:
+ key = error or "unknown"
+ errors[key] = errors.get(key, 0) + 1
+
+ with ThreadPoolExecutor(max_workers=config.concurrency) as executor:
+ futures = [executor.submit(worker) for _ in range(config.concurrency)]
+ for future in futures:
+ future.result()
+ duration = time.perf_counter() - started
+ return {
+ "schema": "openrath.v2.load-sample/1",
+ "source_commit": config.source_commit,
+ "profile": config.profile,
+ "target_like": config.target_like,
+ "worker_replicas": config.worker_replicas,
+ "concurrency": config.concurrency,
+ "duration_seconds": duration,
+ "attempted_runs": reserved,
+ "completed_runs": completed,
+ "errors": reserved - completed,
+ "error_kinds": dict(sorted(errors.items())),
+ "throughput_runs_per_second": completed / duration if duration else 0,
+ "latency_seconds": {
+ "p50": _percentile(latencies, 0.50),
+ "p95": _percentile(latencies, 0.95),
+ "p99": _percentile(latencies, 0.99),
+ },
+ "generated_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
+ "target_origin": target_origin,
+ }
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--base-url", required=True)
+ parser.add_argument("--token-env", default="OPENRATH_TOKEN")
+ parser.add_argument("--source-commit", required=True)
+ parser.add_argument("--profile", choices=["single_host", "split"], required=True)
+ parser.add_argument("--worker-replicas", type=int, required=True)
+ parser.add_argument("--concurrency", type=int, default=16)
+ parser.add_argument("--duration-seconds", type=float, default=300)
+ parser.add_argument("--max-runs", type=int)
+ parser.add_argument("--poll-interval-seconds", type=float, default=0.2)
+ parser.add_argument("--request-timeout-seconds", type=float, default=20)
+ parser.add_argument("--run-timeout-seconds", type=float, default=120)
+ parser.add_argument("--target-like", action="store_true")
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ token = os.environ.get(args.token_env, "")
+ if not token:
+ raise SystemExit(
+ f"required token environment variable is absent: {args.token_env}"
+ )
+ try:
+ report = run_sample(
+ LoadConfig(
+ base_url=args.base_url,
+ token=token,
+ source_commit=args.source_commit,
+ profile=args.profile,
+ worker_replicas=args.worker_replicas,
+ concurrency=args.concurrency,
+ duration_seconds=args.duration_seconds,
+ max_runs=args.max_runs,
+ poll_interval_seconds=args.poll_interval_seconds,
+ request_timeout_seconds=args.request_timeout_seconds,
+ run_timeout_seconds=args.run_timeout_seconds,
+ target_like=args.target_like,
+ )
+ )
+ except ValueError as error:
+ raise SystemExit(str(error)) from error
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+ print(
+ f"completed {report['completed_runs']}/{report['attempted_runs']} "
+ f"lifecycles; report: {args.output}"
+ )
+ if report["errors"]:
+ raise SystemExit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/publish_pypi_manual.py b/scripts/release/publish_pypi_manual.py
new file mode 100644
index 0000000..03533a8
--- /dev/null
+++ b/scripts/release/publish_pypi_manual.py
@@ -0,0 +1,110 @@
+"""Publish the verified OpenRath GA bundle with an interactive PyPI token."""
+
+from __future__ import annotations
+
+import argparse
+import os
+import subprocess
+import sys
+from pathlib import Path
+
+CONFIRMATION = "publish openrath 2.0.0 to pypi"
+TWINE_VERSION = "6.2.0"
+
+
+def _run(*arguments: str, env: dict[str, str] | None = None) -> None:
+ subprocess.run(arguments, check=True, env=env)
+
+
+def twine_environment(source: dict[str, str]) -> dict[str, str]:
+ """Return an environment that cannot reuse stored Twine credentials."""
+ clean = dict(source)
+ for name in (
+ "TWINE_PASSWORD",
+ "TWINE_USERNAME",
+ "TWINE_REPOSITORY",
+ "TWINE_REPOSITORY_URL",
+ ):
+ clean.pop(name, None)
+ clean["PYTHON_KEYRING_BACKEND"] = "keyring.backends.null.Keyring"
+ return clean
+
+
+def twine_upload_command(distributions: list[str]) -> list[str]:
+ """Build the interactive upload command without embedding a token."""
+ return [
+ "uvx",
+ "--from",
+ f"twine=={TWINE_VERSION}",
+ "twine",
+ "upload",
+ "--repository-url",
+ "https://upload.pypi.org/legacy/",
+ "--username",
+ "__token__",
+ "--skip-existing",
+ *distributions,
+ ]
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--bundle-dir", type=Path, required=True)
+ args = parser.parse_args()
+
+ bundle = args.bundle_dir.resolve()
+ repository_root = Path(__file__).resolve().parents[2]
+ manifest = bundle / "release/evidence/2.0.0/manifest.json"
+ packages_dir = bundle / "dist"
+ wheel = next(packages_dir.glob("openrath-2.0.0-*.whl"), None)
+ sdist = packages_dir / "openrath-2.0.0.tar.gz"
+ if wheel is None or not sdist.is_file() or not manifest.is_file():
+ raise SystemExit("bundle must contain the 2.0.0 wheel, sdist, and manifest")
+
+ _run(
+ sys.executable,
+ str(repository_root / "scripts/release/verify_evidence.py"),
+ str(manifest),
+ "--artifact-root",
+ str(bundle),
+ )
+ _run(
+ sys.executable,
+ str(repository_root / "scripts/release/verify_pypi_files.py"),
+ "--packages-dir",
+ str(packages_dir),
+ "--version",
+ "2.0.0",
+ )
+ distributions = [str(sdist), str(wheel)]
+ _run(
+ "uvx",
+ "--from",
+ f"twine=={TWINE_VERSION}",
+ "twine",
+ "check",
+ *distributions,
+ )
+
+ print("The token will be requested by Twine and will not be stored by this script.")
+ if input(f'Type "{CONFIRMATION}" to continue: ') != CONFIRMATION:
+ raise SystemExit("publication cancelled")
+
+ _run(*twine_upload_command(distributions), env=twine_environment(os.environ))
+ _run(
+ sys.executable,
+ str(repository_root / "scripts/release/verify_pypi_files.py"),
+ "--packages-dir",
+ str(packages_dir),
+ "--version",
+ "2.0.0",
+ "--require-complete",
+ "--attempts",
+ "12",
+ "--delay-seconds",
+ "10",
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/record_gate.py b/scripts/release/record_gate.py
new file mode 100644
index 0000000..b022f54
--- /dev/null
+++ b/scripts/release/record_gate.py
@@ -0,0 +1,145 @@
+"""Create one hash-bound OpenRath GA Gate C report."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import re
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any
+
+GATES = frozenset(
+ {
+ "tests",
+ "live_adapters",
+ "performance",
+ "soak",
+ "drills",
+ "compatibility",
+ }
+)
+CONFIRMATION = "record v2.0.0 gate c"
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def _contained_file(root: Path, path: Path) -> tuple[Path, str]:
+ resolved_root = root.resolve(strict=True)
+ candidate = path if path.is_absolute() else resolved_root / path
+ relative = candidate.resolve(strict=True).relative_to(resolved_root)
+ cursor = resolved_root
+ for part in relative.parts:
+ cursor /= part
+ if cursor.is_symlink():
+ raise ValueError(f"evidence path must not contain a symlink: {path}")
+ if not candidate.is_file():
+ raise ValueError(f"evidence path is not a file: {path}")
+ return candidate, relative.as_posix()
+
+
+def build_report(
+ *,
+ gate: str,
+ source_commit: str,
+ environment: dict[str, object],
+ details: dict[str, object],
+ evidence_root: Path,
+ evidence_files: list[Path],
+ open_risks: list[object],
+ generated_at: str | None = None,
+) -> dict[str, Any]:
+ """Build a report that binds every evidence file by relative path and hash."""
+ if gate not in GATES:
+ raise ValueError(f"unsupported GA gate: {gate}")
+ if re.fullmatch(r"[0-9a-f]{40}", source_commit) is None:
+ raise ValueError("source_commit must be 40 lowercase hexadecimal characters")
+ if not evidence_files:
+ raise ValueError("at least one evidence file is required")
+ entries: list[dict[str, object]] = []
+ seen: set[str] = set()
+ for item in evidence_files:
+ path, relative = _contained_file(evidence_root, item)
+ if relative in seen:
+ raise ValueError(f"duplicate evidence path: {relative}")
+ seen.add(relative)
+ entries.append(
+ {
+ "path": relative,
+ "sha256": _sha256(path),
+ "size": path.stat().st_size,
+ }
+ )
+ return {
+ "schema": "openrath.ga-gate-report/1",
+ "gate": gate,
+ "source_commit": source_commit,
+ "result": "passed",
+ "generated_at": generated_at
+ or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
+ "environment": environment,
+ "evidence": entries,
+ "open_risks": open_risks,
+ "details": details,
+ }
+
+
+def _object(path: Path, *, name: str) -> dict[str, object]:
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, dict):
+ raise ValueError(f"{name} must contain a JSON object")
+ return value
+
+
+def _array(path: Path, *, name: str) -> list[object]:
+ value = json.loads(path.read_text(encoding="utf-8"))
+ if not isinstance(value, list):
+ raise ValueError(f"{name} must contain a JSON array")
+ return value
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--gate", choices=sorted(GATES), required=True)
+ parser.add_argument("--source-commit", required=True)
+ parser.add_argument("--profile", required=True)
+ parser.add_argument("--details", type=Path, required=True)
+ parser.add_argument("--evidence-root", type=Path, required=True)
+ parser.add_argument("--evidence-file", type=Path, action="append", required=True)
+ parser.add_argument("--open-risks", type=Path)
+ parser.add_argument("--target-like", action="store_true")
+ parser.add_argument("--confirmation", required=True)
+ parser.add_argument("--output", type=Path, required=True)
+ args = parser.parse_args()
+ if args.confirmation != CONFIRMATION:
+ raise SystemExit(f'--confirmation must be exactly "{CONFIRMATION}"')
+ report = build_report(
+ gate=args.gate,
+ source_commit=args.source_commit,
+ environment={"profile": args.profile, "target_like": args.target_like},
+ details=_object(args.details, name="details"),
+ evidence_root=args.evidence_root,
+ evidence_files=args.evidence_file,
+ open_risks=(
+ _array(args.open_risks, name="open risks")
+ if args.open_risks is not None
+ else []
+ ),
+ )
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(
+ json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
+ encoding="utf-8",
+ )
+ print(f"recorded {args.gate} Gate C report at {args.output}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/verify_evidence.py b/scripts/release/verify_evidence.py
new file mode 100644
index 0000000..16674a5
--- /dev/null
+++ b/scripts/release/verify_evidence.py
@@ -0,0 +1,185 @@
+"""Verify an OpenRath RC or GA evidence manifest."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import re
+import subprocess
+from pathlib import Path
+
+try:
+ from .build_evidence import load_ga_approval
+except ImportError: # pragma: no cover - direct script execution
+ from build_evidence import load_ga_approval
+
+LEGACY_RC_SCHEMA = "openrath.rc-evidence/1"
+RELEASE_SCHEMA = "openrath.release-evidence/2"
+GA_RELEASE_ACTIONS = frozenset(
+ {
+ "pypi",
+ "ghcr",
+ "github_release",
+ }
+)
+GA_REQUIRED_ARTIFACTS = frozenset(
+ {
+ "approval",
+ "tests",
+ "live_adapters",
+ "performance",
+ "soak",
+ "drills",
+ "compatibility",
+ "sbom",
+ "image_scan",
+ "secret_scan",
+ "dependency_audit_production",
+ "dependency_audit_all",
+ "kubernetes",
+ }
+)
+
+
+def validate_release_state(
+ manifest: dict[str, object],
+ *,
+ version: str,
+ commit: str,
+) -> None:
+ """Validate stage, version, approval, and blocker invariants."""
+ assert manifest["version"] == version
+ assert manifest["tag"] == f"v{version}"
+ assert manifest["source_commit"] == commit
+ assert manifest["source_tree_clean"] is True
+
+ schema = manifest["schema"]
+ stage = manifest["release_stage"]
+ if schema == LEGACY_RC_SCHEMA:
+ assert stage == "rc"
+ assert re.fullmatch(r"2\.0\.0rc[1-9][0-9]*", version)
+ assert manifest["ga_approved"] is False
+ assert manifest["blocking_gates"], "legacy RC requires blocking gates"
+ return
+
+ assert schema == RELEASE_SCHEMA
+ if stage == "rc":
+ assert re.fullmatch(r"2\.0\.0rc[1-9][0-9]*", version)
+ assert manifest["ga_approved"] is False
+ assert manifest["blocking_gates"], "RC requires blocking gates"
+ assert "approval" not in manifest
+ return
+
+ assert stage == "ga"
+ assert version == "2.0.0"
+ assert manifest["ga_approved"] is True
+ assert not manifest["blocking_gates"], "GA cannot contain blocking gates"
+ artifacts = manifest["artifacts"]
+ assert isinstance(artifacts, dict)
+ missing_artifacts = sorted(GA_REQUIRED_ARTIFACTS - set(artifacts))
+ assert not missing_artifacts, "GA evidence is missing artifacts: " + ", ".join(
+ missing_artifacts
+ )
+ approval = manifest.get("approval")
+ assert isinstance(approval, dict), "GA requires approval metadata"
+ assert approval.get("source_commit") == commit
+ assert approval.get("environment") == "ga-release"
+ assert isinstance(approval.get("requested_by"), str) and approval["requested_by"]
+ approvers = approval.get("approvers")
+ assert isinstance(approvers, list) and approvers
+ assert all(isinstance(approver, str) and approver for approver in approvers)
+ assert len(set(approvers)) == len(approvers)
+ assert re.fullmatch(r"[1-9][0-9]*", str(approval.get("workflow_run_id", "")))
+ assert approval.get("approved_at")
+ actions = approval.get("actions")
+ assert isinstance(actions, dict)
+ missing_actions = sorted(
+ action for action in GA_RELEASE_ACTIONS if actions.get(action) is not True
+ )
+ assert not missing_actions, "GA approval is missing actions: " + ", ".join(
+ missing_actions
+ )
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def _project_version() -> str:
+ text = Path("pyproject.toml").read_text(encoding="utf-8")
+ match = re.search(r'^version = "([^"]+)"$', text, flags=re.MULTILINE)
+ if match is None:
+ raise RuntimeError("project version is missing from pyproject.toml")
+ return match.group(1)
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("manifest", type=Path)
+ parser.add_argument(
+ "--artifact-root",
+ type=Path,
+ default=Path("."),
+ help="root directory used to resolve artifact paths from the manifest",
+ )
+ args = parser.parse_args()
+
+ manifest = json.loads(args.manifest.read_text(encoding="utf-8"))
+ version = _project_version()
+ commit = subprocess.check_output(
+ ["git", "rev-parse", "HEAD"],
+ text=True,
+ encoding="utf-8",
+ ).strip()
+
+ validate_release_state(manifest, version=version, commit=commit)
+
+ openapi = json.loads(
+ Path("deploy/docs/openapi-v2.json").read_text(encoding="utf-8")
+ )
+ assert openapi["info"]["version"] == version
+
+ for name, artifact in manifest["artifacts"].items():
+ if name == "image":
+ assert re.fullmatch(r"sha256:[0-9a-f]{64}", artifact["digest"])
+ continue
+ path = args.artifact_root / artifact["path"]
+ assert path.is_file(), path
+ assert path.stat().st_size == artifact["size"], path
+ assert _sha256(path) == artifact["sha256"], path
+
+ if manifest["release_stage"] == "ga":
+ approval_path = args.artifact_root / manifest["artifacts"]["approval"]["path"]
+ workflow = manifest.get("workflow")
+ assert isinstance(workflow, dict)
+ workflow_repository = workflow.get("repository")
+ workflow_run_id = workflow.get("run_id")
+ assert isinstance(workflow_repository, str) and workflow_repository
+ assert isinstance(workflow_run_id, str) and workflow_run_id
+ approval = load_ga_approval(
+ approval_path,
+ version=version,
+ commit=commit,
+ repository=workflow_repository,
+ workflow_run_id=workflow_run_id,
+ )
+ assert approval["approvers"] == manifest["approval"]["approvers"]
+ assert approval["requested_by"] == manifest["approval"]["requested_by"]
+ assert approval["approved_at"] == manifest["approval"]["approved_at"]
+ assert approval["environment"] == manifest["approval"]["environment"]
+ assert approval["workflow_run_id"] == manifest["approval"]["workflow_run_id"]
+ assert approval["actions"] == manifest["approval"]["actions"]
+
+ print(
+ f"verified {manifest['tag']} evidence for "
+ f"{manifest['source_commit']} ({len(manifest['artifacts'])} artifacts)"
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/verify_gate_bundle.py b/scripts/release/verify_gate_bundle.py
new file mode 100644
index 0000000..f49a158
--- /dev/null
+++ b/scripts/release/verify_gate_bundle.py
@@ -0,0 +1,89 @@
+"""Reject unsafe files and likely credentials before Gate C artifact upload."""
+
+from __future__ import annotations
+
+import argparse
+import re
+from pathlib import Path
+
+ALLOWED_SUFFIXES = frozenset({".csv", ".json", ".log", ".txt", ".xml"})
+SENSITIVE_NAMES = frozenset(
+ {
+ ".env",
+ ".pypirc",
+ "credentials",
+ "credentials.json",
+ "kubeconfig",
+ }
+)
+MAX_FILE_BYTES = 50 * 1024 * 1024
+MAX_BUNDLE_BYTES = 2 * 1024 * 1024 * 1024
+SECRET_PATTERNS = (
+ re.compile(r"Authorization\s*:\s*Bearer\s+\S+", re.IGNORECASE),
+ re.compile(r"pypi-[A-Za-z0-9_-]{20,}"),
+ re.compile(r"github_pat_[A-Za-z0-9_]{20,}"),
+ re.compile(r"gh[pousr]_[A-Za-z0-9]{20,}"),
+ re.compile(r"sk-[A-Za-z0-9_-]{20,}"),
+ re.compile(r"AKIA[0-9A-Z]{16}"),
+ re.compile(r"-----BEGIN (?:[A-Z]+ )?PRIVATE KEY-----"),
+ re.compile(
+ r"""["']?(?:api[_-]?key|access[_-]?token|secret[_-]?key|password)"""
+ r"""["']?\s*[:=]\s*["'][^"'\r\n]{8,}["']""",
+ re.IGNORECASE,
+ ),
+)
+
+
+def verify_bundle(root: Path) -> dict[str, int]:
+ """Return bundle size metadata after validating every file."""
+ resolved_root = root.resolve(strict=True)
+ if root.is_symlink() or not resolved_root.is_dir():
+ raise ValueError("Gate C bundle root must be a real directory")
+ files = 0
+ total = 0
+ for path in resolved_root.rglob("*"):
+ if path.is_symlink():
+ raise ValueError(f"Gate C bundle contains a symbolic link: {path}")
+ if not path.is_file():
+ continue
+ if path.name.lower() in SENSITIVE_NAMES:
+ raise ValueError(
+ f"Gate C bundle contains a sensitive filename: {path.name}"
+ )
+ if path.suffix.lower() not in ALLOWED_SUFFIXES:
+ raise ValueError(f"Gate C bundle contains an unsupported extension: {path}")
+ size = path.stat().st_size
+ if size > MAX_FILE_BYTES:
+ raise ValueError(f"Gate C evidence file exceeds 50 MiB: {path}")
+ total += size
+ if total > MAX_BUNDLE_BYTES:
+ raise ValueError("Gate C bundle exceeds 2 GiB")
+ try:
+ text = path.read_text(encoding="utf-8")
+ except UnicodeDecodeError as error:
+ raise ValueError(f"Gate C evidence must be UTF-8 text: {path}") from error
+ for pattern in SECRET_PATTERNS:
+ if pattern.search(text):
+ raise ValueError(f"Gate C evidence contains a likely secret: {path}")
+ files += 1
+ if files == 0:
+ raise ValueError("Gate C bundle contains no evidence files")
+ return {"files": files, "bytes": total}
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("bundle", type=Path)
+ args = parser.parse_args()
+ try:
+ summary = verify_bundle(args.bundle)
+ except (OSError, ValueError) as error:
+ raise SystemExit(str(error)) from error
+ print(
+ f"verified Gate C bundle safety: "
+ f"{summary['files']} files, {summary['bytes']} bytes"
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/verify_gate_reports.py b/scripts/release/verify_gate_reports.py
new file mode 100644
index 0000000..0cc7c8f
--- /dev/null
+++ b/scripts/release/verify_gate_reports.py
@@ -0,0 +1,238 @@
+"""Verify target-environment evidence before an OpenRath GA release."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import re
+from datetime import datetime
+from pathlib import Path
+
+GATE_REPORT_FILES = {
+ "tests": "tests.json",
+ "live_adapters": "live-adapters.json",
+ "performance": "performance.json",
+ "soak": "soak.json",
+ "drills": "drills.json",
+ "compatibility": "compatibility.json",
+}
+
+
+def _require_passed(details: dict[str, object], *names: str) -> None:
+ failed = sorted(name for name in names if details.get(name) != "passed")
+ if failed:
+ raise ValueError("required checks did not pass: " + ", ".join(failed))
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def _validate_evidence(
+ evidence: object,
+ *,
+ gate: str,
+ artifact_root: Path,
+) -> None:
+ if not isinstance(evidence, list) or not evidence:
+ raise ValueError(f"{gate}: at least one evidence reference is required")
+ root = artifact_root.resolve(strict=True)
+ seen: set[str] = set()
+ for item in evidence:
+ if not isinstance(item, dict):
+ raise ValueError(f"{gate}: evidence entry must be an object")
+ relative = item.get("path")
+ expected_hash = item.get("sha256")
+ expected_size = item.get("size")
+ if (
+ not isinstance(relative, str)
+ or not relative
+ or "\\" in relative
+ or ":" in relative
+ or Path(relative).is_absolute()
+ or ".." in Path(relative).parts
+ ):
+ raise ValueError(f"{gate}: evidence path must be a safe relative path")
+ if relative in seen:
+ raise ValueError(f"{gate}: duplicate evidence path: {relative}")
+ seen.add(relative)
+ if re.fullmatch(r"[0-9a-f]{64}", str(expected_hash or "")) is None:
+ raise ValueError(f"{gate}: evidence hash must be a SHA-256")
+ if (
+ isinstance(expected_size, bool)
+ or not isinstance(expected_size, int)
+ or expected_size < 0
+ ):
+ raise ValueError(f"{gate}: evidence size must be a non-negative integer")
+ candidate = root / relative
+ cursor = root
+ for part in Path(relative).parts:
+ cursor /= part
+ if cursor.is_symlink():
+ raise ValueError(f"{gate}: evidence path must not contain a symlink")
+ try:
+ resolved = candidate.resolve(strict=True)
+ resolved.relative_to(root)
+ except (FileNotFoundError, ValueError) as error:
+ raise ValueError(
+ f"{gate}: evidence file is missing or outside the artifact root"
+ ) from error
+ if not resolved.is_file():
+ raise ValueError(f"{gate}: evidence path is not a file: {relative}")
+ if resolved.stat().st_size != expected_size:
+ raise ValueError(f"{gate}: evidence size mismatch: {relative}")
+ if _sha256(resolved) != expected_hash:
+ raise ValueError(f"{gate}: evidence hash mismatch: {relative}")
+
+
+def _validate_common(
+ report: dict[str, object],
+ *,
+ gate: str,
+ source_commit: str,
+ artifact_root: Path,
+) -> dict[str, object]:
+ if report.get("schema") != "openrath.ga-gate-report/1":
+ raise ValueError(f"{gate}: unsupported report schema")
+ if report.get("gate") != gate:
+ raise ValueError(f"{gate}: gate name does not match the filename")
+ if report.get("source_commit") != source_commit:
+ raise ValueError(f"{gate}: source_commit does not match the GA candidate")
+ if report.get("result") != "passed":
+ raise ValueError(f"{gate}: result must be passed")
+ generated_at = report.get("generated_at")
+ if not isinstance(generated_at, str):
+ raise ValueError(f"{gate}: generated_at is required")
+ try:
+ generated = datetime.fromisoformat(generated_at.replace("Z", "+00:00"))
+ except ValueError as error:
+ raise ValueError(f"{gate}: generated_at must be ISO 8601") from error
+ if generated.tzinfo is None:
+ raise ValueError(f"{gate}: generated_at must include a timezone")
+ environment = report.get("environment")
+ if not isinstance(environment, dict):
+ raise ValueError(f"{gate}: environment profile is required")
+ if (
+ not isinstance(environment.get("profile"), str)
+ or not environment["profile"]
+ ):
+ raise ValueError(f"{gate}: environment profile name is required")
+ if environment.get("target_like") is not True:
+ raise ValueError(f"{gate}: environment target_like must be true")
+ _validate_evidence(
+ report.get("evidence"),
+ gate=gate,
+ artifact_root=artifact_root,
+ )
+ if not isinstance(report.get("open_risks"), list):
+ raise ValueError(f"{gate}: open_risks must be a list")
+ details = report.get("details")
+ if not isinstance(details, dict):
+ raise ValueError(f"{gate}: details must be an object")
+ return details
+
+
+def _validate_gate(gate: str, details: dict[str, object]) -> None:
+ if gate == "tests":
+ _require_passed(details, "required_ci")
+ if details.get("open_p0") != 0:
+ raise ValueError("tests: open_p0 must be zero")
+ return
+ if gate == "live_adapters":
+ _require_passed(details, "provider", "opensandbox", "openviking")
+ return
+ if gate == "performance":
+ _require_passed(details, "single_host", "split_profile")
+ efficiency = details.get("worker_scaling_efficiency")
+ if (
+ isinstance(efficiency, bool)
+ or not isinstance(efficiency, (int, float))
+ or efficiency < 0.70
+ ):
+ raise ValueError(
+ "performance: worker_scaling_efficiency must be at least 0.70"
+ )
+ return
+ if gate == "soak":
+ duration = details.get("duration_seconds")
+ if isinstance(duration, bool) or not isinstance(duration, (int, float)):
+ raise ValueError("soak: duration_seconds must be numeric")
+ if duration < 28800:
+ raise ValueError("soak: duration_seconds must be at least 28800")
+ if details.get("errors") != 0:
+ raise ValueError("soak: errors must be zero")
+ if details.get("unexplained_resource_growth") is not False:
+ raise ValueError("soak: unexplained_resource_growth must be false")
+ return
+ if gate == "drills":
+ _require_passed(
+ details,
+ "fault_matrix",
+ "backup_restore",
+ "rollout_rollback",
+ )
+ return
+ if gate == "compatibility":
+ _require_passed(
+ details,
+ "api_review",
+ "v1_maintenance_window",
+ "migration",
+ )
+ return
+ raise ValueError(f"unsupported GA gate: {gate}")
+
+
+def verify_directory(
+ directory: Path,
+ *,
+ source_commit: str,
+ artifact_root: Path | None = None,
+) -> dict[str, Path]:
+ """Verify all Gate C report files and return their paths by gate name."""
+ if re.fullmatch(r"[0-9a-f]{40}", source_commit) is None:
+ raise ValueError("source_commit must be 40 lowercase hexadecimal characters")
+ root = artifact_root if artifact_root is not None else directory
+ validated: dict[str, Path] = {}
+ for gate, filename in GATE_REPORT_FILES.items():
+ path = directory / filename
+ if not path.is_file():
+ raise ValueError(f"missing GA gate report: {filename}")
+ try:
+ report = json.loads(path.read_text(encoding="utf-8"))
+ except json.JSONDecodeError as error:
+ raise ValueError(f"{filename}: invalid JSON") from error
+ if not isinstance(report, dict):
+ raise ValueError(f"{filename}: report must be an object")
+ details = _validate_common(
+ report,
+ gate=gate,
+ source_commit=source_commit,
+ artifact_root=root,
+ )
+ _validate_gate(gate, details)
+ validated[gate] = path
+ return validated
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("directory", type=Path)
+ parser.add_argument("--source-commit", required=True)
+ parser.add_argument("--artifact-root", type=Path)
+ args = parser.parse_args()
+ reports = verify_directory(
+ args.directory,
+ source_commit=args.source_commit,
+ artifact_root=args.artifact_root,
+ )
+ print(f"verified {len(reports)} GA gate reports for {args.source_commit}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/release/verify_pypi_files.py b/scripts/release/verify_pypi_files.py
new file mode 100644
index 0000000..fe2954b
--- /dev/null
+++ b/scripts/release/verify_pypi_files.py
@@ -0,0 +1,119 @@
+"""Verify that existing PyPI files are identical to local release artifacts."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import time
+import urllib.error
+import urllib.request
+from pathlib import Path
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def local_distributions(packages_dir: Path, *, version: str) -> dict[str, str]:
+ """Return the exact wheel and sdist hashes expected for one version."""
+ sdist = packages_dir / f"openrath-{version}.tar.gz"
+ wheels = sorted(packages_dir.glob(f"openrath-{version}-*.whl"))
+ if not sdist.is_file() or len(wheels) != 1:
+ raise ValueError("expected exactly one OpenRath wheel and one sdist")
+ paths = [sdist, wheels[0]]
+ return {path.name: _sha256(path) for path in paths}
+
+
+def verify_remote_files(
+ local: dict[str, str],
+ payload: dict[str, object] | None,
+ *,
+ version: str,
+ require_complete: bool,
+) -> bool:
+ """Reject conflicting files and return whether PyPI is complete."""
+ if payload is None:
+ if require_complete:
+ raise ValueError(f"OpenRath {version} is not visible on PyPI")
+ return False
+
+ info = payload.get("info")
+ if not isinstance(info, dict) or info.get("version") != version:
+ raise ValueError("PyPI response version does not match the release")
+ urls = payload.get("urls")
+ if not isinstance(urls, list) or not urls:
+ raise ValueError("PyPI response contains no distribution files")
+
+ remote: dict[str, str] = {}
+ for item in urls:
+ if not isinstance(item, dict):
+ raise ValueError("PyPI distribution entry must be an object")
+ filename = item.get("filename")
+ digests = item.get("digests")
+ sha256 = digests.get("sha256") if isinstance(digests, dict) else None
+ if not isinstance(filename, str) or not isinstance(sha256, str):
+ raise ValueError("PyPI distribution entry is missing its SHA-256")
+ remote[filename] = sha256
+
+ unexpected = sorted(set(remote) - set(local))
+ if unexpected:
+ raise ValueError("PyPI contains unexpected files: " + ", ".join(unexpected))
+ conflicts = sorted(
+ filename for filename, digest in remote.items() if local.get(filename) != digest
+ )
+ if conflicts:
+ raise ValueError("PyPI file hash mismatch: " + ", ".join(conflicts))
+
+ missing = sorted(set(local) - set(remote))
+ if require_complete and missing:
+ raise ValueError("PyPI is missing release files: " + ", ".join(missing))
+ return not missing
+
+
+def _pypi_payload(*, version: str) -> dict[str, object] | None:
+ url = f"https://pypi.org/pypi/openrath/{version}/json"
+ try:
+ with urllib.request.urlopen(url, timeout=20) as response:
+ return json.load(response)
+ except urllib.error.HTTPError as error:
+ if error.code == 404:
+ return None
+ raise
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--packages-dir", type=Path, required=True)
+ parser.add_argument("--version", required=True)
+ parser.add_argument("--require-complete", action="store_true")
+ parser.add_argument("--attempts", type=int, default=1)
+ parser.add_argument("--delay-seconds", type=float, default=5)
+ args = parser.parse_args()
+ if args.attempts < 1:
+ raise SystemExit("--attempts must be positive")
+
+ local = local_distributions(args.packages_dir, version=args.version)
+ last_error: ValueError | None = None
+ for attempt in range(1, args.attempts + 1):
+ try:
+ complete = verify_remote_files(
+ local,
+ _pypi_payload(version=args.version),
+ version=args.version,
+ require_complete=args.require_complete,
+ )
+ except ValueError as error:
+ last_error = error
+ if attempt == args.attempts:
+ raise SystemExit(str(error)) from error
+ else:
+ state = "complete and identical" if complete else "absent or partial"
+ print(f"PyPI OpenRath {args.version}: {state}")
+ return
+ time.sleep(args.delay_seconds)
+ raise SystemExit(str(last_error))
diff --git a/scripts/release/verify_release_assets.py b/scripts/release/verify_release_assets.py
new file mode 100644
index 0000000..071d9b9
--- /dev/null
+++ b/scripts/release/verify_release_assets.py
@@ -0,0 +1,55 @@
+"""Verify an existing GitHub Release has the exact expected assets."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+from pathlib import Path
+
+
+def _sha256(path: Path) -> str:
+ digest = hashlib.sha256()
+ with path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def verify_assets(actual_directory: Path, expected_paths: list[Path]) -> None:
+ """Reject duplicate names, missing assets, extra assets, or hash mismatches."""
+ expected: dict[str, Path] = {}
+ for path in expected_paths:
+ if not path.is_file():
+ raise ValueError(f"expected release asset is missing: {path}")
+ if path.name in expected:
+ raise ValueError(f"duplicate expected release asset name: {path.name}")
+ expected[path.name] = path
+
+ actual = {path.name: path for path in actual_directory.iterdir() if path.is_file()}
+ missing = sorted(set(expected) - set(actual))
+ extra = sorted(set(actual) - set(expected))
+ if missing:
+ raise ValueError("GitHub Release is missing assets: " + ", ".join(missing))
+ if extra:
+ raise ValueError("GitHub Release has unexpected assets: " + ", ".join(extra))
+ mismatched = sorted(
+ name for name in expected if _sha256(expected[name]) != _sha256(actual[name])
+ )
+ if mismatched:
+ raise ValueError("GitHub Release asset hash mismatch: " + ", ".join(mismatched))
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("actual_directory", type=Path)
+ parser.add_argument("expected", type=Path, nargs="+")
+ args = parser.parse_args()
+ try:
+ verify_assets(args.actual_directory, args.expected)
+ except (OSError, ValueError) as error:
+ raise SystemExit(str(error)) from error
+ print(f"verified {len(args.expected)} existing GitHub Release assets")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/soak_v2.py b/scripts/soak_v2.py
new file mode 100644
index 0000000..3a76ae4
--- /dev/null
+++ b/scripts/soak_v2.py
@@ -0,0 +1,106 @@
+"""Run a bounded local soak profile and report resource growth."""
+
+from __future__ import annotations
+
+import argparse
+import json
+import platform
+import tempfile
+import threading
+import time
+import tracemalloc
+from pathlib import Path
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import LocalRuntime, RunStatus, SQLiteRunStore
+from rath.session import Session
+
+
+class SoakWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def execute(self, state, context): # type: ignore[no-untyped-def]
+ return {"value": int(state["value"]) + 1}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--duration-seconds", type=float, default=300)
+ parser.add_argument("--max-runs", type=int)
+ parser.add_argument("--output", type=Path)
+ args = parser.parse_args()
+ if args.duration_seconds <= 0:
+ parser.error("--duration-seconds must be positive")
+ if args.max_runs is not None and args.max_runs < 1:
+ parser.error("--max-runs must be positive")
+
+ started = time.perf_counter()
+ deadline = started + args.duration_seconds
+ completed = 0
+ failures = 0
+ threads_before = threading.active_count()
+ tracemalloc.start()
+ memory_before, _ = tracemalloc.get_traced_memory()
+ with tempfile.TemporaryDirectory(prefix="openrath-soak-") as directory:
+ store = SQLiteRunStore(Path(directory) / "runtime.db")
+ runtime = LocalRuntime(store)
+ context = RunContext.local(revision_id=uuid4())
+ workflow = SoakWorkflow()
+ while time.perf_counter() < deadline and (
+ args.max_runs is None or completed + failures < args.max_runs
+ ):
+ runtime.submit(
+ workflow,
+ session_id=uuid4(),
+ context=context,
+ state={"value": completed + failures},
+ )
+ run = runtime.work_once(worker_id="soak")
+ if run is not None and run.status is RunStatus.SUCCEEDED:
+ completed += 1
+ else:
+ failures += 1
+ store.close()
+ memory_after, memory_peak = tracemalloc.get_traced_memory()
+ tracemalloc.stop()
+ duration = time.perf_counter() - started
+ report = {
+ "schema": "openrath.v2.soak/1",
+ "profile": "sqlite-single-worker-one-step",
+ "duration_seconds": duration,
+ "completed_runs": completed,
+ "failed_runs": failures,
+ "throughput_runs_per_second": completed / duration,
+ "resource_delta": {
+ "threads": threading.active_count() - threads_before,
+ "traced_memory_bytes": memory_after - memory_before,
+ "peak_traced_memory_bytes": memory_peak,
+ },
+ "environment": {
+ "python": platform.python_version(),
+ "platform": platform.platform(),
+ "processor": platform.processor(),
+ },
+ "scope": (
+ "Review profile only; repeat for the approved 8h/24h duration "
+ "on target hardware before production rollout."
+ ),
+ }
+ value = json.dumps(report, indent=2)
+ if args.output is not None:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(value, encoding="utf-8")
+ print(value)
+ if failures:
+ raise SystemExit(1)
+ if report["resource_delta"]["threads"] != 0:
+ raise SystemExit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/rath/__init__.py b/src/rath/__init__.py
index ffaa334..8bf8064 100644
--- a/src/rath/__init__.py
+++ b/src/rath/__init__.py
@@ -18,12 +18,33 @@
from typing import Any
from rath import (
+ adapters,
+ artifacts,
backend,
+ definition,
+ deployment,
+ eval,
flow,
memory,
+ observability,
+ runtime,
+ security,
)
-__all__ = ["backend", "flow", "memory", "session"]
+__all__ = [
+ "backend",
+ "adapters",
+ "artifacts",
+ "definition",
+ "deployment",
+ "eval",
+ "flow",
+ "memory",
+ "observability",
+ "runtime",
+ "security",
+ "session",
+]
def __getattr__(name: str) -> Any:
diff --git a/src/rath/_async/runtime.py b/src/rath/_async/runtime.py
index b7d40e1..aec8ede 100644
--- a/src/rath/_async/runtime.py
+++ b/src/rath/_async/runtime.py
@@ -117,6 +117,10 @@ def run(self, coro: Coroutine[Any, Any, T]) -> T:
except RuntimeError:
running = None
if running is not None:
+ # The caller already created the coroutine object. Close it before
+ # rejecting the blocking call so Python does not emit an
+ # un-awaited-coroutine warning or retain captured resources.
+ coro.close()
raise RuntimeError(
"OpenRathRuntime.run() called from inside an asyncio loop; "
"OpenRath's public API is synchronous and must be called from "
diff --git a/src/rath/_json.py b/src/rath/_json.py
new file mode 100644
index 0000000..bb62f27
--- /dev/null
+++ b/src/rath/_json.py
@@ -0,0 +1,49 @@
+"""Small immutable JSON helpers shared by public v2 contracts."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from types import MappingProxyType
+from typing import TypeAlias
+
+JSONScalar: TypeAlias = None | bool | int | float | str
+JSONValue: TypeAlias = JSONScalar | tuple["JSONValue", ...] | Mapping[str, "JSONValue"]
+
+
+def freeze_json(value: object, *, field: str = "value") -> JSONValue:
+ """Return an immutable, detached representation of a JSON-compatible value."""
+ if value is None or isinstance(value, (bool, int, float, str)):
+ return value
+ if isinstance(value, Mapping):
+ frozen: dict[str, JSONValue] = {}
+ for key, item in value.items():
+ if not isinstance(key, str):
+ raise TypeError(f"{field} mapping keys must be strings")
+ frozen[key] = freeze_json(item, field=f"{field}.{key}")
+ return MappingProxyType(frozen)
+ if isinstance(value, (list, tuple)):
+ return tuple(
+ freeze_json(item, field=f"{field}[{index}]")
+ for index, item in enumerate(value)
+ )
+ raise TypeError(f"{field} must be JSON-compatible, got {type(value).__name__}")
+
+
+def freeze_mapping(
+ value: Mapping[str, object] | None,
+ *,
+ field: str,
+) -> Mapping[str, JSONValue]:
+ """Freeze a JSON object and return an immutable mapping."""
+ frozen = freeze_json(value or {}, field=field)
+ assert isinstance(frozen, Mapping)
+ return frozen
+
+
+def thaw_json(value: JSONValue) -> object:
+ """Return a mutable JSON-compatible copy suitable for serialization."""
+ if isinstance(value, Mapping):
+ return {key: thaw_json(item) for key, item in value.items()}
+ if isinstance(value, tuple):
+ return [thaw_json(item) for item in value]
+ return value
diff --git a/src/rath/adapters/__init__.py b/src/rath/adapters/__init__.py
new file mode 100644
index 0000000..3cff076
--- /dev/null
+++ b/src/rath/adapters/__init__.py
@@ -0,0 +1,51 @@
+"""Shared v2 adapter contracts."""
+
+from rath.adapters.context import (
+ AdapterRequestContext,
+ merge_policy_constraints,
+ with_policy_constraints,
+)
+from rath.adapters.memory import MemoryExecutor, MemoryHandler
+from rath.adapters.provider import ProviderExecutor, ProviderHandler
+from rath.adapters.sandbox import SandboxExecutor, SandboxHandler
+from rath.adapters.schema import SchemaValidationError, validate_json
+from rath.adapters.specs import (
+ MemoryNamespace,
+ ProviderCapability,
+ ProviderSpec,
+ SandboxIsolation,
+ SandboxSpec,
+ ToolSpec,
+)
+from rath.adapters.tool import (
+ ApprovalGrant,
+ ApprovalValidator,
+ ToolExecutor,
+ ToolHandler,
+ ToolOutputTooLarge,
+)
+
+__all__ = [
+ "AdapterRequestContext",
+ "ApprovalGrant",
+ "ApprovalValidator",
+ "MemoryNamespace",
+ "MemoryExecutor",
+ "MemoryHandler",
+ "merge_policy_constraints",
+ "ProviderCapability",
+ "ProviderExecutor",
+ "ProviderHandler",
+ "ProviderSpec",
+ "SandboxIsolation",
+ "SandboxExecutor",
+ "SandboxHandler",
+ "SandboxSpec",
+ "SchemaValidationError",
+ "ToolExecutor",
+ "ToolHandler",
+ "ToolOutputTooLarge",
+ "ToolSpec",
+ "validate_json",
+ "with_policy_constraints",
+]
diff --git a/src/rath/adapters/context.py b/src/rath/adapters/context.py
new file mode 100644
index 0000000..e741757
--- /dev/null
+++ b/src/rath/adapters/context.py
@@ -0,0 +1,108 @@
+"""Uniform request context propagated to every external adapter."""
+
+from __future__ import annotations
+
+from dataclasses import dataclass, replace
+from datetime import datetime, timezone
+from uuid import UUID
+
+from rath.context import TraceContext
+from rath.security import PolicyConstraints
+
+__all__ = [
+ "AdapterRequestContext",
+ "effective_timeout_seconds",
+ "merge_policy_constraints",
+ "with_policy_constraints",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class AdapterRequestContext:
+ run_id: UUID
+ node_id: str
+ tenant_id: str
+ deadline: datetime | None
+ trace_context: TraceContext
+ idempotency_key: str | None
+ policy_constraints: PolicyConstraints
+ checkpoint_sequence: int | None = None
+
+ def __post_init__(self) -> None:
+ if not self.node_id.strip():
+ raise ValueError("adapter node_id must not be empty")
+ if not self.tenant_id.strip():
+ raise ValueError("adapter tenant_id must not be empty")
+ if self.deadline is not None and self.deadline.tzinfo is None:
+ raise ValueError("adapter deadline must be timezone-aware")
+ if self.checkpoint_sequence is not None and self.checkpoint_sequence < 1:
+ raise ValueError("checkpoint_sequence must be positive")
+
+
+def effective_timeout_seconds(
+ requested: float,
+ *,
+ adapter_context: AdapterRequestContext,
+ run_remaining_seconds: float | None,
+) -> float:
+ """Resolve the strictest positive timeout from spec, policy and deadlines."""
+
+ candidates = [requested]
+ policy_timeout = adapter_context.policy_constraints.timeout_seconds
+ if policy_timeout is not None:
+ candidates.append(policy_timeout)
+ if run_remaining_seconds is not None:
+ candidates.append(run_remaining_seconds)
+ if adapter_context.deadline is not None:
+ candidates.append(
+ max(
+ 0.0,
+ (adapter_context.deadline - datetime.now(timezone.utc)).total_seconds(),
+ )
+ )
+ return min(candidates)
+
+
+def merge_policy_constraints(
+ declared: PolicyConstraints,
+ decided: PolicyConstraints,
+) -> PolicyConstraints:
+ """Combine caller and policy limits without weakening either side."""
+
+ timeouts = [
+ value
+ for value in (declared.timeout_seconds, decided.timeout_seconds)
+ if value is not None
+ ]
+ output_limits = [
+ value
+ for value in (declared.max_output_bytes, decided.max_output_bytes)
+ if value is not None
+ ]
+ if declared.allowed_network_hosts and decided.allowed_network_hosts:
+ allowed_hosts = declared.allowed_network_hosts & decided.allowed_network_hosts
+ else:
+ allowed_hosts = declared.allowed_network_hosts or decided.allowed_network_hosts
+ return PolicyConstraints(
+ timeout_seconds=min(timeouts) if timeouts else None,
+ max_output_bytes=min(output_limits) if output_limits else None,
+ allowed_network_hosts=allowed_hosts,
+ filesystem_root=decided.filesystem_root or declared.filesystem_root,
+ read_only=declared.read_only or decided.read_only,
+ redactions=declared.redactions | decided.redactions,
+ )
+
+
+def with_policy_constraints(
+ context: AdapterRequestContext,
+ constraints: PolicyConstraints,
+) -> AdapterRequestContext:
+ """Return the adapter context carrying the evaluated policy constraints."""
+
+ return replace(
+ context,
+ policy_constraints=merge_policy_constraints(
+ context.policy_constraints,
+ constraints,
+ ),
+ )
diff --git a/src/rath/adapters/memory.py b/src/rath/adapters/memory.py
new file mode 100644
index 0000000..b5d8c44
--- /dev/null
+++ b/src/rath/adapters/memory.py
@@ -0,0 +1,90 @@
+"""Governed tenant-scoped Memory v2 execution boundary."""
+
+from __future__ import annotations
+
+import asyncio
+import inspect
+import time
+from collections.abc import Awaitable, Mapping
+from typing import Literal, Protocol, cast
+
+from rath.adapters.context import (
+ AdapterRequestContext,
+ effective_timeout_seconds,
+ with_policy_constraints,
+)
+from rath.adapters.specs import MemoryNamespace
+from rath.context import RunContext
+from rath.security import Action, PolicyEngine, ResourceRef, authorize
+
+__all__ = ["MemoryExecutor", "MemoryHandler"]
+
+
+class MemoryHandler(Protocol):
+ def __call__(
+ self,
+ operation: Literal["put", "search", "delete"],
+ namespace: MemoryNamespace,
+ payload: Mapping[str, object],
+ context: AdapterRequestContext,
+ ) -> object | Awaitable[object]: ...
+
+
+class MemoryExecutor:
+ def __init__(self, policy: PolicyEngine) -> None:
+ self.policy = policy
+
+ async def execute(
+ self,
+ handler: MemoryHandler,
+ operation: Literal["put", "search", "delete"],
+ namespace: MemoryNamespace,
+ payload: Mapping[str, object],
+ *,
+ adapter_context: AdapterRequestContext,
+ run_context: RunContext,
+ timeout_seconds: float = 30,
+ ) -> object:
+ if timeout_seconds <= 0:
+ raise ValueError("memory timeout must be positive")
+ tenant_id = run_context.security.tenant_id
+ if namespace.tenant_id != tenant_id or adapter_context.tenant_id != tenant_id:
+ raise PermissionError("memory namespace tenant mismatch")
+ decision = await authorize(
+ self.policy,
+ action=Action(f"memory.{operation}"),
+ resource=ResourceRef(
+ kind="memory_namespace",
+ id=":".join(
+ item
+ for item in (
+ namespace.tenant_id,
+ namespace.user_id,
+ namespace.agent_id,
+ namespace.session_id,
+ )
+ if item is not None
+ ),
+ tenant_id=tenant_id,
+ attributes={"trust": namespace.trust.value},
+ ),
+ context=run_context,
+ )
+ adapter_context = with_policy_constraints(
+ adapter_context,
+ decision.constraints,
+ )
+ timeout = effective_timeout_seconds(
+ timeout_seconds,
+ adapter_context=adapter_context,
+ run_remaining_seconds=run_context.remaining_seconds(),
+ )
+ started = time.monotonic()
+ result = handler(operation, namespace, payload, adapter_context)
+ if inspect.isawaitable(result):
+ return await asyncio.wait_for(
+ cast(Awaitable[object], result), timeout=timeout
+ )
+ if time.monotonic() - started > timeout:
+ raise TimeoutError("memory operation exceeded timeout")
+ return result
diff --git a/src/rath/adapters/provider.py b/src/rath/adapters/provider.py
new file mode 100644
index 0000000..3405203
--- /dev/null
+++ b/src/rath/adapters/provider.py
@@ -0,0 +1,90 @@
+"""Governed Provider v2 execution boundary."""
+
+from __future__ import annotations
+
+import asyncio
+import inspect
+import time
+from collections.abc import Awaitable, Mapping
+from typing import Protocol, cast
+
+from rath.adapters.context import (
+ AdapterRequestContext,
+ effective_timeout_seconds,
+ with_policy_constraints,
+)
+from rath.adapters.specs import ProviderCapability, ProviderSpec
+from rath.context import RunContext
+from rath.security import Action, PolicyEngine, ResourceRef, authorize
+
+__all__ = ["ProviderExecutor", "ProviderHandler"]
+
+
+class ProviderHandler(Protocol):
+ def __call__(
+ self,
+ request: Mapping[str, object],
+ spec: ProviderSpec,
+ context: AdapterRequestContext,
+ ) -> object | Awaitable[object]: ...
+
+
+class ProviderExecutor:
+ def __init__(self, policy: PolicyEngine) -> None:
+ self.policy = policy
+ self._semaphores: dict[str, asyncio.Semaphore] = {}
+
+ async def execute(
+ self,
+ spec: ProviderSpec,
+ handler: ProviderHandler,
+ request: Mapping[str, object],
+ *,
+ capability: ProviderCapability,
+ adapter_context: AdapterRequestContext,
+ run_context: RunContext,
+ ) -> object:
+ if capability not in spec.capabilities:
+ raise ValueError(
+ f"provider {spec.id!r} does not declare {capability.value!r}"
+ )
+ if adapter_context.tenant_id != run_context.security.tenant_id:
+ raise PermissionError("adapter and run tenant mismatch")
+ decision = await authorize(
+ self.policy,
+ action=Action("provider.invoke"),
+ resource=ResourceRef(
+ kind="provider",
+ id=spec.id,
+ tenant_id=adapter_context.tenant_id,
+ attributes={
+ "kind": spec.kind,
+ "model": spec.model,
+ "capability": capability.value,
+ },
+ ),
+ context=run_context,
+ )
+ adapter_context = with_policy_constraints(
+ adapter_context,
+ decision.constraints,
+ )
+ semaphore = self._semaphores.setdefault(
+ spec.id, asyncio.Semaphore(spec.max_concurrency)
+ )
+ timeout = effective_timeout_seconds(
+ spec.total_timeout_seconds,
+ adapter_context=adapter_context,
+ run_remaining_seconds=run_context.remaining_seconds(),
+ )
+ async with semaphore:
+ started = time.monotonic()
+ result = handler(request, spec, adapter_context)
+ if inspect.isawaitable(result):
+ return await asyncio.wait_for(
+ cast(Awaitable[object], result),
+ timeout=timeout,
+ )
+ if time.monotonic() - started > timeout:
+ raise TimeoutError(f"provider {spec.id!r} exceeded timeout")
+ return result
diff --git a/src/rath/adapters/sandbox.py b/src/rath/adapters/sandbox.py
new file mode 100644
index 0000000..a06d213
--- /dev/null
+++ b/src/rath/adapters/sandbox.py
@@ -0,0 +1,86 @@
+"""Governed Sandbox v2 execution boundary."""
+
+from __future__ import annotations
+
+import asyncio
+import inspect
+import time
+from collections.abc import Awaitable, Mapping
+from typing import Protocol, cast
+
+from rath.adapters.context import (
+ AdapterRequestContext,
+ effective_timeout_seconds,
+ with_policy_constraints,
+)
+from rath.adapters.specs import SandboxSpec
+from rath.context import RunContext
+from rath.security import Action, PolicyEngine, ResourceRef, authorize
+
+__all__ = ["SandboxExecutor", "SandboxHandler"]
+
+
+class SandboxHandler(Protocol):
+ def __call__(
+ self,
+ operation: str,
+ payload: Mapping[str, object],
+ spec: SandboxSpec,
+ context: AdapterRequestContext,
+ ) -> object | Awaitable[object]: ...
+
+
+class SandboxExecutor:
+ def __init__(self, policy: PolicyEngine) -> None:
+ self.policy = policy
+
+ async def execute(
+ self,
+ spec: SandboxSpec,
+ handler: SandboxHandler,
+ operation: str,
+ payload: Mapping[str, object],
+ *,
+ adapter_context: AdapterRequestContext,
+ run_context: RunContext,
+ timeout_seconds: float = 60,
+ ) -> object:
+ if not operation:
+ raise ValueError("sandbox operation is required")
+ if timeout_seconds <= 0:
+ raise ValueError("sandbox timeout must be positive")
+ if adapter_context.tenant_id != run_context.security.tenant_id:
+ raise PermissionError("adapter and run tenant mismatch")
+ decision = await authorize(
+ self.policy,
+ action=Action("sandbox.execute"),
+ resource=ResourceRef(
+ kind="sandbox",
+ id=spec.id,
+ tenant_id=adapter_context.tenant_id,
+ attributes={
+ "isolation": spec.isolation.value,
+ "network": spec.network,
+ "operation": operation,
+ },
+ ),
+ context=run_context,
+ )
+ adapter_context = with_policy_constraints(
+ adapter_context,
+ decision.constraints,
+ )
+ timeout = effective_timeout_seconds(
+ timeout_seconds,
+ adapter_context=adapter_context,
+ run_remaining_seconds=run_context.remaining_seconds(),
+ )
+ started = time.monotonic()
+ result = handler(operation, payload, spec, adapter_context)
+ if inspect.isawaitable(result):
+ return await asyncio.wait_for(
+ cast(Awaitable[object], result), timeout=timeout
+ )
+ if time.monotonic() - started > timeout:
+ raise TimeoutError(f"sandbox {spec.id!r} exceeded timeout")
+ return result
diff --git a/src/rath/adapters/schema.py b/src/rath/adapters/schema.py
new file mode 100644
index 0000000..44fc375
--- /dev/null
+++ b/src/rath/adapters/schema.py
@@ -0,0 +1,70 @@
+"""Small fail-closed JSON Schema subset used for Tool runtime validation."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping, Sequence
+
+__all__ = ["SchemaValidationError", "validate_json"]
+
+
+class SchemaValidationError(ValueError):
+ pass
+
+
+def validate_json(
+ value: object, schema: Mapping[str, object], *, path: str = "$"
+) -> None:
+ expected = schema.get("type")
+ if expected == "object":
+ if not isinstance(value, Mapping):
+ raise SchemaValidationError(f"{path} must be an object")
+ required = schema.get("required", ())
+ if isinstance(required, Sequence) and not isinstance(required, str):
+ for key in required:
+ if str(key) not in value:
+ raise SchemaValidationError(f"{path}.{key} is required")
+ properties = schema.get("properties", {})
+ if isinstance(properties, Mapping):
+ for key, item in value.items():
+ child_schema = properties.get(key)
+ if isinstance(child_schema, Mapping):
+ validate_json(item, child_schema, path=f"{path}.{key}")
+ elif schema.get("additionalProperties") is False:
+ raise SchemaValidationError(f"{path}.{key} is not allowed")
+ elif expected == "array":
+ if not isinstance(value, Sequence) or isinstance(value, (str, bytes)):
+ raise SchemaValidationError(f"{path} must be an array")
+ items = schema.get("items")
+ if isinstance(items, Mapping):
+ for index, item in enumerate(value):
+ validate_json(item, items, path=f"{path}[{index}]")
+ elif expected == "string":
+ if not isinstance(value, str):
+ raise SchemaValidationError(f"{path} must be a string")
+ max_length = schema.get("maxLength")
+ if isinstance(max_length, int) and len(value) > max_length:
+ raise SchemaValidationError(f"{path} exceeds maxLength")
+ elif expected == "integer":
+ if not isinstance(value, int) or isinstance(value, bool):
+ raise SchemaValidationError(f"{path} must be an integer")
+ elif expected == "number":
+ if not isinstance(value, (int, float)) or isinstance(value, bool):
+ raise SchemaValidationError(f"{path} must be a number")
+ elif expected == "boolean" and not isinstance(value, bool):
+ raise SchemaValidationError(f"{path} must be a boolean")
+ elif expected == "null" and value is not None:
+ raise SchemaValidationError(f"{path} must be null")
+ elif expected not in (
+ None,
+ "object",
+ "array",
+ "string",
+ "integer",
+ "number",
+ "boolean",
+ "null",
+ ):
+ raise SchemaValidationError(f"{path} uses unsupported schema type {expected!r}")
+ enum = schema.get("enum")
+ if isinstance(enum, Sequence) and value not in enum:
+ raise SchemaValidationError(f"{path} is not an allowed enum value")
diff --git a/src/rath/adapters/specs.py b/src/rath/adapters/specs.py
new file mode 100644
index 0000000..e985e01
--- /dev/null
+++ b/src/rath/adapters/specs.py
@@ -0,0 +1,126 @@
+"""Versioned external adapter specifications without resolved credentials."""
+
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from enum import Enum
+from typing import Literal
+
+from rath.definition import EffectClass
+from rath.security import SecretRef, TrustLevel
+
+__all__ = [
+ "MemoryNamespace",
+ "ProviderCapability",
+ "ProviderSpec",
+ "SandboxIsolation",
+ "SandboxSpec",
+ "ToolSpec",
+]
+
+
+class ProviderCapability(str, Enum):
+ CHAT = "chat"
+ STREAM = "stream"
+ TOOLS = "tools"
+ STRUCTURED_OUTPUT = "structured_output"
+ EMBEDDING = "embedding"
+ VISION = "vision"
+
+
+@dataclass(frozen=True, slots=True)
+class ProviderSpec:
+ id: str
+ kind: str
+ model: str
+ credential: SecretRef | None = None
+ capabilities: frozenset[ProviderCapability] = field(default_factory=frozenset)
+ connect_timeout_seconds: float = 10.0
+ read_timeout_seconds: float = 60.0
+ total_timeout_seconds: float = 120.0
+ max_concurrency: int = 16
+
+ def __post_init__(self) -> None:
+ if not self.id or not self.kind or not self.model:
+ raise ValueError("provider id, kind, and model are required")
+ if (
+ min(
+ self.connect_timeout_seconds,
+ self.read_timeout_seconds,
+ self.total_timeout_seconds,
+ )
+ <= 0
+ ):
+ raise ValueError("provider timeouts must be positive")
+ if self.max_concurrency < 1:
+ raise ValueError("provider max_concurrency must be positive")
+
+
+@dataclass(frozen=True, slots=True)
+class ToolSpec:
+ name: str
+ version: str
+ input_schema: dict[str, object]
+ output_schema: dict[str, object] | None = None
+ effects: EffectClass = EffectClass.NON_IDEMPOTENT
+ risk: Literal["low", "medium", "high", "critical"] = "high"
+ timeout_seconds: float = 30.0
+ max_output_bytes: int = 1024 * 1024
+ requires_approval: bool = False
+
+ def __post_init__(self) -> None:
+ if not self.name or not self.version:
+ raise ValueError("tool name and version are required")
+ if self.timeout_seconds <= 0 or self.max_output_bytes <= 0:
+ raise ValueError("tool budgets must be positive")
+ if self.effects is EffectClass.NON_IDEMPOTENT and self.risk in {
+ "high",
+ "critical",
+ }:
+ object.__setattr__(self, "requires_approval", True)
+
+
+class SandboxIsolation(str, Enum):
+ TRUSTED_HOST = "trusted_host"
+ LOCAL_CONTAINER = "local_container"
+ REMOTE_CONTAINER = "remote_container"
+
+
+@dataclass(frozen=True, slots=True)
+class SandboxSpec:
+ id: str
+ isolation: SandboxIsolation
+ image_digest: str | None = None
+ cpu_limit: float | None = None
+ memory_bytes: int | None = None
+ disk_bytes: int | None = None
+ process_limit: int | None = None
+ network: Literal["deny", "allowlist", "unrestricted"] = "deny"
+ allowed_hosts: frozenset[str] = field(default_factory=frozenset)
+ ttl_seconds: int = 900
+
+ def __post_init__(self) -> None:
+ if not self.id:
+ raise ValueError("sandbox id is required")
+ if self.ttl_seconds <= 0:
+ raise ValueError("sandbox ttl_seconds must be positive")
+ if (
+ self.isolation is not SandboxIsolation.TRUSTED_HOST
+ and not self.image_digest
+ ):
+ raise ValueError("container sandboxes require an immutable image_digest")
+ if self.network == "allowlist" and not self.allowed_hosts:
+ raise ValueError("network allowlist requires at least one host")
+
+
+@dataclass(frozen=True, slots=True)
+class MemoryNamespace:
+ tenant_id: str
+ user_id: str | None = None
+ agent_id: str | None = None
+ session_id: str | None = None
+ trust: TrustLevel = TrustLevel.UNTRUSTED
+
+ def __post_init__(self) -> None:
+ if not self.tenant_id:
+ raise ValueError("memory namespace tenant_id is required")
diff --git a/src/rath/adapters/tool.py b/src/rath/adapters/tool.py
new file mode 100644
index 0000000..20975eb
--- /dev/null
+++ b/src/rath/adapters/tool.py
@@ -0,0 +1,242 @@
+"""Policy-governed Tool v2 execution boundary."""
+
+from __future__ import annotations
+
+import asyncio
+import inspect
+import json
+import time
+from collections.abc import Awaitable, Mapping
+from dataclasses import dataclass
+from typing import Protocol, cast
+from uuid import UUID
+
+from rath.adapters.context import (
+ AdapterRequestContext,
+ effective_timeout_seconds,
+ with_policy_constraints,
+)
+from rath.adapters.schema import validate_json
+from rath.adapters.specs import ToolSpec
+from rath.artifacts import ArtifactStore
+from rath.context import RunContext
+from rath.definition import EffectClass
+from rath.runtime.effects import (
+ EffectLedger,
+ InvocationStatus,
+ arguments_digest,
+)
+from rath.security import (
+ Action,
+ ApprovalRequiredError,
+ PolicyDecision,
+ PolicyEffect,
+ PolicyEngine,
+ ResourceRef,
+ authorize,
+)
+
+__all__ = [
+ "ApprovalGrant",
+ "ApprovalValidator",
+ "ToolExecutor",
+ "ToolHandler",
+ "ToolOutputTooLarge",
+]
+
+
+class ToolOutputTooLarge(RuntimeError):
+ pass
+
+
+@dataclass(frozen=True, slots=True)
+class ApprovalGrant:
+ decision_id: UUID
+ run_id: UUID
+ node_id: str
+ tenant_id: str
+ tool_id: str
+ arguments_digest: str
+ actor_id: str
+
+
+class ApprovalValidator(Protocol):
+ def __call__(self, grant: ApprovalGrant) -> bool | Awaitable[bool]: ...
+
+
+class ToolHandler(Protocol):
+ def __call__(
+ self,
+ arguments: Mapping[str, object],
+ context: AdapterRequestContext,
+ ) -> object | Awaitable[object]: ...
+
+
+class ToolExecutor:
+ def __init__(
+ self,
+ policy: PolicyEngine,
+ *,
+ effect_ledger: EffectLedger | None = None,
+ artifact_store: ArtifactStore | None = None,
+ approval_validator: ApprovalValidator | None = None,
+ ) -> None:
+ self.policy = policy
+ self.effect_ledger = effect_ledger
+ self.artifact_store = artifact_store
+ self.approval_validator = approval_validator
+
+ async def execute(
+ self,
+ spec: ToolSpec,
+ handler: ToolHandler,
+ arguments: Mapping[str, object],
+ *,
+ adapter_context: AdapterRequestContext,
+ run_context: RunContext,
+ approval: ApprovalGrant | None = None,
+ run_id: UUID | None = None,
+ idempotency_key: str | None = None,
+ ) -> object:
+ validate_json(arguments, spec.input_schema)
+ if adapter_context.tenant_id != run_context.security.tenant_id:
+ raise PermissionError("adapter and run tenant mismatch")
+ digest = arguments_digest(arguments)
+ approval_valid = False
+ if approval is not None:
+ if (
+ approval.run_id != adapter_context.run_id
+ or approval.node_id != adapter_context.node_id
+ or approval.tenant_id != adapter_context.tenant_id
+ or approval.tool_id != f"{spec.name}@{spec.version}"
+ or approval.arguments_digest != digest
+ ):
+ raise PermissionError("approval grant does not match tool invocation")
+ if self.approval_validator is None:
+ raise PermissionError("approval grant cannot be verified")
+ validated = self.approval_validator(approval)
+ approval_valid = (
+ await validated if inspect.isawaitable(validated) else bool(validated)
+ )
+ if not approval_valid:
+ raise PermissionError("approval grant is not valid")
+ try:
+ decision = await authorize(
+ self.policy,
+ action=Action("tool.execute"),
+ resource=ResourceRef(
+ kind="tool",
+ id=f"{spec.name}@{spec.version}",
+ tenant_id=adapter_context.tenant_id,
+ attributes={"risk": spec.risk, "effects": spec.effects.value},
+ ),
+ context=run_context,
+ )
+ except ApprovalRequiredError as exc:
+ if not approval_valid:
+ raise
+ decision = exc.decision
+ adapter_context = with_policy_constraints(
+ adapter_context,
+ decision.constraints,
+ )
+ if spec.requires_approval and not approval_valid:
+ raise ApprovalRequiredError(
+ PolicyDecision(
+ effect=PolicyEffect.REQUIRE_APPROVAL,
+ reason=f"tool {spec.name} requires approval",
+ policy_id="tool-spec",
+ )
+ )
+ invocation = None
+ ledger = self.effect_ledger
+ effective_idempotency_key = (
+ idempotency_key
+ if idempotency_key is not None
+ else adapter_context.idempotency_key
+ )
+ if ledger is not None:
+ if run_id is None:
+ raise ValueError("run_id is required when effect ledger is enabled")
+ invocation = ledger.prepare(
+ run_id=run_id,
+ tool_name=f"{spec.name}@{spec.version}",
+ effect_class=spec.effects,
+ arguments_digest=digest,
+ idempotency_key=effective_idempotency_key,
+ node_id=adapter_context.node_id,
+ checkpoint_sequence=adapter_context.checkpoint_sequence,
+ )
+ if invocation.status is InvocationStatus.SUCCEEDED:
+ return invocation.result
+ if invocation.status in {
+ InvocationStatus.AMBIGUOUS,
+ InvocationStatus.DISPATCHED,
+ }:
+ raise RuntimeError(
+ "tool invocation outcome is ambiguous and requires reconciliation"
+ )
+ invocation = ledger.mark_dispatched(invocation.id)
+ effective_timeout = effective_timeout_seconds(
+ spec.timeout_seconds,
+ adapter_context=adapter_context,
+ run_remaining_seconds=run_context.remaining_seconds(),
+ )
+ started = time.monotonic()
+ try:
+ result = handler(arguments, adapter_context)
+ if inspect.isawaitable(result):
+ result = await asyncio.wait_for(
+ cast(Awaitable[object], result),
+ timeout=effective_timeout,
+ )
+ elif time.monotonic() - started > effective_timeout:
+ raise TimeoutError(f"tool {spec.name}@{spec.version} exceeded timeout")
+ except BaseException as exc:
+ if (
+ invocation is not None
+ and ledger is not None
+ and spec.effects is not EffectClass.NON_IDEMPOTENT
+ and not isinstance(exc, (TimeoutError, asyncio.TimeoutError))
+ ):
+ ledger.fail(invocation.id, f"{type(exc).__name__}: {exc}")
+ raise
+ if spec.output_schema is not None:
+ validate_json(result, spec.output_schema)
+ encoded = json.dumps(result, ensure_ascii=False, default=str).encode("utf-8")
+ limit = min(
+ spec.max_output_bytes,
+ adapter_context.policy_constraints.max_output_bytes
+ or spec.max_output_bytes,
+ )
+ if len(encoded) > limit:
+ if self.artifact_store is not None:
+ artifact = self.artifact_store.put(
+ adapter_context.tenant_id,
+ encoded,
+ media_type="application/json",
+ metadata={
+ "tool": f"{spec.name}@{spec.version}",
+ "run_id": str(run_id) if run_id is not None else None,
+ },
+ )
+ reference = {
+ "artifact_uri": artifact.uri,
+ "digest": artifact.digest,
+ "size": artifact.size,
+ "media_type": artifact.media_type,
+ }
+ if invocation is not None and ledger is not None:
+ ledger.complete(invocation.id, reference)
+ return reference
+ if invocation is not None and ledger is not None:
+ ledger.fail(
+ invocation.id,
+ f"tool output exceeded {limit} bytes",
+ )
+ raise ToolOutputTooLarge(
+ f"tool output is {len(encoded)} bytes; maximum is {limit}"
+ )
+ if invocation is not None and ledger is not None:
+ ledger.complete(invocation.id, result)
+ return result
diff --git a/src/rath/artifacts/__init__.py b/src/rath/artifacts/__init__.py
new file mode 100644
index 0000000..937dc56
--- /dev/null
+++ b/src/rath/artifacts/__init__.py
@@ -0,0 +1,17 @@
+"""Content-addressed artifact storage."""
+
+from rath.artifacts.store import (
+ Artifact,
+ ArtifactNotFound,
+ ArtifactStore,
+ LocalArtifactStore,
+ S3ArtifactStore,
+)
+
+__all__ = [
+ "Artifact",
+ "ArtifactNotFound",
+ "ArtifactStore",
+ "LocalArtifactStore",
+ "S3ArtifactStore",
+]
diff --git a/src/rath/artifacts/store.py b/src/rath/artifacts/store.py
new file mode 100644
index 0000000..3ca6b84
--- /dev/null
+++ b/src/rath/artifacts/store.py
@@ -0,0 +1,387 @@
+"""Tenant-scoped, content-addressed artifact stores."""
+
+from __future__ import annotations
+
+import hashlib
+import json
+import os
+import re
+import tempfile
+from collections.abc import Iterator, Mapping
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from pathlib import Path
+from typing import Any, BinaryIO, Protocol, cast, runtime_checkable
+
+from rath._json import JSONValue, freeze_mapping, thaw_json
+
+__all__ = [
+ "Artifact",
+ "ArtifactNotFound",
+ "ArtifactStore",
+ "LocalArtifactStore",
+ "S3ArtifactStore",
+]
+
+_SCOPE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$")
+_SHA256 = re.compile(r"^[0-9a-f]{64}$")
+
+
+class ArtifactNotFound(KeyError):
+ """Raised when an artifact does not exist in the requested tenant."""
+
+
+@dataclass(frozen=True, slots=True)
+class Artifact:
+ tenant_id: str
+ digest: str
+ size: int
+ media_type: str
+ created_at: datetime
+ metadata: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ _validate_scope(self.tenant_id, field_name="tenant_id")
+ if not _SHA256.fullmatch(self.digest):
+ raise ValueError("digest must be a lowercase SHA-256 digest")
+ if self.size < 0:
+ raise ValueError("size must not be negative")
+ if not self.media_type.strip():
+ raise ValueError("media_type must not be empty")
+ if self.created_at.tzinfo is None:
+ raise ValueError("created_at must be timezone-aware")
+ object.__setattr__(
+ self, "metadata", freeze_mapping(self.metadata, field="artifact.metadata")
+ )
+
+ @property
+ def uri(self) -> str:
+ return f"artifact://{self.tenant_id}/{self.digest}"
+
+
+@runtime_checkable
+class ArtifactStore(Protocol):
+ def put(
+ self,
+ tenant_id: str,
+ content: bytes | BinaryIO,
+ *,
+ media_type: str = "application/octet-stream",
+ metadata: Mapping[str, object] | None = None,
+ ) -> Artifact: ...
+
+ def get(self, tenant_id: str, digest: str) -> bytes: ...
+
+ def stat(self, tenant_id: str, digest: str) -> Artifact: ...
+
+ def delete(self, tenant_id: str, digest: str) -> bool: ...
+
+
+class _S3Client(Protocol):
+ def put_object(self, **kwargs: object) -> object: ...
+
+ def get_object(self, **kwargs: object) -> Mapping[str, Any]: ...
+
+ def delete_objects(self, **kwargs: object) -> object: ...
+
+
+def _validate_scope(value: str, *, field_name: str) -> None:
+ if not _SCOPE.fullmatch(value):
+ raise ValueError(f"{field_name} contains unsafe characters")
+
+
+def _validate_digest(digest: str) -> None:
+ if not _SHA256.fullmatch(digest):
+ raise ValueError("digest must be a lowercase SHA-256 digest")
+
+
+def _chunks(content: bytes | BinaryIO, size: int = 1024 * 1024) -> Iterator[bytes]:
+ if isinstance(content, bytes):
+ yield content
+ return
+ while chunk := content.read(size):
+ yield chunk
+
+
+def _read_response_bounded(body: object, maximum: int) -> bytes:
+ reader = getattr(body, "read", None)
+ if not callable(reader):
+ raise TypeError("artifact response body is not readable")
+ value = bytearray()
+ while True:
+ chunk = reader(min(1024 * 1024, maximum - len(value) + 1))
+ if not isinstance(chunk, bytes):
+ raise TypeError("artifact response body did not return bytes")
+ if not chunk:
+ return bytes(value)
+ value.extend(chunk)
+ if len(value) > maximum:
+ raise ValueError("artifact exceeds configured size limit")
+
+
+def _manifest(artifact: Artifact) -> bytes:
+ value = {
+ "tenant_id": artifact.tenant_id,
+ "digest": artifact.digest,
+ "size": artifact.size,
+ "media_type": artifact.media_type,
+ "created_at": artifact.created_at.isoformat(),
+ "metadata": thaw_json(artifact.metadata),
+ }
+ return json.dumps(value, sort_keys=True, ensure_ascii=False).encode()
+
+
+def _parse_manifest(value: bytes) -> Artifact:
+ data = json.loads(value)
+ return Artifact(
+ tenant_id=data["tenant_id"],
+ digest=data["digest"],
+ size=data["size"],
+ media_type=data["media_type"],
+ created_at=datetime.fromisoformat(data["created_at"]),
+ metadata=data["metadata"],
+ )
+
+
+class LocalArtifactStore:
+ """Atomic filesystem store intended for embedded and single-node operation."""
+
+ def __init__(self, root: str | Path, *, max_bytes: int = 128 * 1024 * 1024):
+ if max_bytes < 1:
+ raise ValueError("max_bytes must be positive")
+ self.root = Path(root).expanduser().resolve(strict=False)
+ self.root.mkdir(parents=True, exist_ok=True)
+ self.max_bytes = max_bytes
+
+ def _paths(self, tenant_id: str, digest: str) -> tuple[Path, Path]:
+ _validate_scope(tenant_id, field_name="tenant_id")
+ _validate_digest(digest)
+ directory = self.root / tenant_id / digest[:2]
+ payload = directory / digest
+ manifest = directory / f"{digest}.json"
+ for path in (directory, payload, manifest):
+ if not path.resolve(strict=False).is_relative_to(self.root):
+ raise ValueError("artifact path escapes the configured root")
+ return payload, manifest
+
+ def put(
+ self,
+ tenant_id: str,
+ content: bytes | BinaryIO,
+ *,
+ media_type: str = "application/octet-stream",
+ metadata: Mapping[str, object] | None = None,
+ ) -> Artifact:
+ _validate_scope(tenant_id, field_name="tenant_id")
+ digest = hashlib.sha256()
+ total = 0
+ temporary: Path | None = None
+ try:
+ with tempfile.NamedTemporaryFile(
+ dir=self.root, prefix=".upload-", delete=False
+ ) as target:
+ temporary = Path(target.name)
+ for chunk in _chunks(content):
+ total += len(chunk)
+ if total > self.max_bytes:
+ raise ValueError("artifact exceeds configured size limit")
+ digest.update(chunk)
+ target.write(chunk)
+ target.flush()
+ os.fsync(target.fileno())
+ artifact = Artifact(
+ tenant_id=tenant_id,
+ digest=digest.hexdigest(),
+ size=total,
+ media_type=media_type,
+ created_at=datetime.now(timezone.utc),
+ metadata=freeze_mapping(metadata, field="artifact.metadata"),
+ )
+ payload, manifest = self._paths(tenant_id, artifact.digest)
+ payload.parent.mkdir(parents=True, exist_ok=True)
+ if payload.exists():
+ temporary.unlink(missing_ok=True)
+ else:
+ temporary.replace(payload)
+ temporary = None
+ self._atomic_write(manifest, _manifest(artifact))
+ return self.stat(tenant_id, artifact.digest)
+ finally:
+ if temporary is not None:
+ temporary.unlink(missing_ok=True)
+
+ def get(self, tenant_id: str, digest: str) -> bytes:
+ payload, _ = self._paths(tenant_id, digest)
+ try:
+ value = payload.read_bytes()
+ except FileNotFoundError as exc:
+ raise ArtifactNotFound(digest) from exc
+ if not hashlib.sha256(value).hexdigest() == digest:
+ raise IOError("artifact digest verification failed")
+ return value
+
+ def stat(self, tenant_id: str, digest: str) -> Artifact:
+ _, manifest = self._paths(tenant_id, digest)
+ try:
+ artifact = _parse_manifest(manifest.read_bytes())
+ except FileNotFoundError as exc:
+ raise ArtifactNotFound(digest) from exc
+ if artifact.tenant_id != tenant_id or artifact.digest != digest:
+ raise IOError("artifact manifest identity mismatch")
+ return artifact
+
+ def delete(self, tenant_id: str, digest: str) -> bool:
+ payload, manifest = self._paths(tenant_id, digest)
+ existed = payload.exists() or manifest.exists()
+ payload.unlink(missing_ok=True)
+ manifest.unlink(missing_ok=True)
+ return existed
+
+ @staticmethod
+ def _atomic_write(path: Path, value: bytes) -> None:
+ descriptor, name = tempfile.mkstemp(dir=path.parent, prefix=".manifest-")
+ temporary = Path(name)
+ try:
+ with os.fdopen(descriptor, "wb") as target:
+ target.write(value)
+ target.flush()
+ os.fsync(target.fileno())
+ temporary.replace(path)
+ finally:
+ temporary.unlink(missing_ok=True)
+
+
+class S3ArtifactStore:
+ """S3-compatible store; durable identity is the SHA-256 object key."""
+
+ def __init__(
+ self,
+ bucket: str,
+ *,
+ prefix: str = "openrath",
+ client: object | None = None,
+ max_bytes: int = 128 * 1024 * 1024,
+ **client_options: object,
+ ) -> None:
+ _validate_scope(bucket, field_name="bucket")
+ if not prefix or prefix.startswith("/") or ".." in prefix.split("/"):
+ raise ValueError("prefix must be a safe relative object prefix")
+ if max_bytes < 1:
+ raise ValueError("max_bytes must be positive")
+ if client is None:
+ try:
+ import boto3 # type: ignore
+ except ImportError as exc:
+ raise RuntimeError(
+ "S3 support requires `pip install openrath[s3]`"
+ ) from exc
+ client = boto3.client("s3", **client_options)
+ self.bucket = bucket
+ self.prefix = prefix.rstrip("/")
+ self.client = cast(_S3Client, client)
+ self.max_bytes = max_bytes
+
+ def _keys(self, tenant_id: str, digest: str) -> tuple[str, str]:
+ _validate_scope(tenant_id, field_name="tenant_id")
+ _validate_digest(digest)
+ base = f"{self.prefix}/{tenant_id}/{digest[:2]}/{digest}"
+ return base, f"{base}.json"
+
+ def put(
+ self,
+ tenant_id: str,
+ content: bytes | BinaryIO,
+ *,
+ media_type: str = "application/octet-stream",
+ metadata: Mapping[str, object] | None = None,
+ ) -> Artifact:
+ digest = hashlib.sha256()
+ total = 0
+ with tempfile.TemporaryFile() as staged:
+ for chunk in _chunks(content):
+ total += len(chunk)
+ if total > self.max_bytes:
+ raise ValueError("artifact exceeds configured size limit")
+ digest.update(chunk)
+ staged.write(chunk)
+ artifact = Artifact(
+ tenant_id=tenant_id,
+ digest=digest.hexdigest(),
+ size=total,
+ media_type=media_type,
+ created_at=datetime.now(timezone.utc),
+ metadata=freeze_mapping(metadata, field="artifact.metadata"),
+ )
+ payload_key, manifest_key = self._keys(tenant_id, artifact.digest)
+ staged.seek(0)
+ self.client.put_object(
+ Bucket=self.bucket,
+ Key=payload_key,
+ Body=staged,
+ ContentLength=total,
+ ContentType=media_type,
+ Metadata={"sha256": artifact.digest},
+ )
+ try:
+ self.client.put_object(
+ Bucket=self.bucket,
+ Key=manifest_key,
+ Body=_manifest(artifact),
+ ContentType="application/json",
+ )
+ except BaseException:
+ self.client.delete_objects(
+ Bucket=self.bucket,
+ Delete={"Objects": [{"Key": payload_key}], "Quiet": True},
+ )
+ raise
+ return artifact
+
+ def get(self, tenant_id: str, digest: str) -> bytes:
+ payload_key, _ = self._keys(tenant_id, digest)
+ try:
+ response = self.client.get_object(Bucket=self.bucket, Key=payload_key)
+ except Exception as exc:
+ if _not_found(exc):
+ raise ArtifactNotFound(digest) from exc
+ raise
+ content_length = response.get("ContentLength")
+ if content_length is not None and int(content_length) > self.max_bytes:
+ raise ValueError("artifact exceeds configured size limit")
+ value = _read_response_bounded(response["Body"], self.max_bytes)
+ if hashlib.sha256(value).hexdigest() != digest:
+ raise IOError("artifact digest verification failed")
+ return value
+
+ def stat(self, tenant_id: str, digest: str) -> Artifact:
+ _, manifest_key = self._keys(tenant_id, digest)
+ try:
+ response = self.client.get_object(Bucket=self.bucket, Key=manifest_key)
+ except Exception as exc:
+ if _not_found(exc):
+ raise ArtifactNotFound(digest) from exc
+ raise
+ artifact = _parse_manifest(
+ _read_response_bounded(response["Body"], 1024 * 1024)
+ )
+ if artifact.tenant_id != tenant_id or artifact.digest != digest:
+ raise IOError("artifact manifest identity mismatch")
+ return artifact
+
+ def delete(self, tenant_id: str, digest: str) -> bool:
+ try:
+ self.stat(tenant_id, digest)
+ except ArtifactNotFound:
+ return False
+ payload_key, manifest_key = self._keys(tenant_id, digest)
+ self.client.delete_objects(
+ Bucket=self.bucket,
+ Delete={"Objects": [{"Key": payload_key}, {"Key": manifest_key}]},
+ )
+ return True
+
+
+def _not_found(exc: Exception) -> bool:
+ response = getattr(exc, "response", {})
+ code = response.get("Error", {}).get("Code") if isinstance(response, dict) else None
+ return str(code) in {"404", "NoSuchKey", "NotFound"}
diff --git a/src/rath/backend/__init__.py b/src/rath/backend/__init__.py
index aad2141..e737263 100644
--- a/src/rath/backend/__init__.py
+++ b/src/rath/backend/__init__.py
@@ -11,6 +11,7 @@
BackendSandboxClosed,
UnsupportedBackendTool,
)
+from rath.backend.local import LocalBackend, TrustedHostBackend
from rath.backend.registry import (
current,
get,
@@ -49,6 +50,8 @@
__all__ = [
"Backend",
+ "LocalBackend",
+ "TrustedHostBackend",
"BackendSandbox",
"BackendSandboxSpec",
"BackendTool",
diff --git a/src/rath/backend/local.py b/src/rath/backend/local.py
index 4cea93c..d8e5992 100644
--- a/src/rath/backend/local.py
+++ b/src/rath/backend/local.py
@@ -1,7 +1,10 @@
-"""Host-process backend: subprocesses and filesystem under a temp working directory.
+"""Trusted-host backend: subprocesses and filesystem under a working directory.
-Always available. Relative paths in tool calls are resolved against the sandbox
-working directory; absolute paths pass through unchanged.
+Always available, but **not an isolation boundary**. Filesystem tool paths and
+command working directories are contained under the configured workspace;
+executed code still inherits the host process privileges and may access the
+host through normal language or shell APIs. Service deployments must reject
+this backend unless an explicit trusted-host policy allows it.
The implementation is async-internal: ``_aopen`` / ``_aclose`` / ``_adispatch``
are the canonical entry points. Each blocking primitive (``subprocess.run``,
@@ -63,11 +66,15 @@
from rath.utils.decoding import decode_subprocess_output
-@register("local")
-class LocalBackend(Backend):
- """Run tool calls as host-side subprocesses with a per-sandbox working dir."""
+class _PathViolation(ValueError):
+ """A filesystem operation escaped the configured workspace."""
- name: ClassVar[str] = "local"
+
+@register("trusted-host")
+class TrustedHostBackend(Backend):
+ """Run tool calls on the host under an explicitly trusted policy."""
+
+ name: ClassVar[str] = "trusted-host"
_CAPABILITIES: ClassVar[Capabilities] = Capabilities(
isolation=IsolationLevel.PROCESS,
@@ -117,9 +124,9 @@ async def _aopen(self, spec: BackendSandboxSpec | None = None) -> BackendSandbox
else:
owns_working_dir = False
working_dir = spec.working_dir
- await asyncio.to_thread(
- lambda: Path(working_dir).mkdir(parents=True, exist_ok=True)
- )
+ working_path = Path(working_dir).expanduser()
+ await asyncio.to_thread(working_path.mkdir, parents=True, exist_ok=True)
+ working_dir = str(await asyncio.to_thread(working_path.resolve))
sandbox = BackendSandbox(backend=self, handle=working_dir, spec=spec)
# Mutate handle sets only on the runtime loop thread.
self._open_handles.add(working_dir)
@@ -168,15 +175,30 @@ async def _adispatch(
)
def _resolve(self, sandbox: BackendSandbox, path: str) -> Path:
- p = Path(path)
- if p.is_absolute():
- return p
- return Path(sandbox.handle) / path
+ root = Path(sandbox.handle).resolve(strict=False)
+ candidate = Path(path).expanduser()
+ if not candidate.is_absolute():
+ candidate = root / candidate
+ resolved = candidate.resolve(strict=False)
+ try:
+ resolved.relative_to(root)
+ except ValueError as exc:
+ raise _PathViolation(
+ f"path {path!r} is outside sandbox workspace {str(root)!r}"
+ ) from exc
+ return resolved
def _command_run(
self, sandbox: BackendSandbox, call: BackendToolCommandRun
) -> CommandResult | ToolExecutionFailure:
- cwd = self._resolve(sandbox, call.cwd) if call.cwd else Path(sandbox.handle)
+ try:
+ cwd = (
+ self._resolve(sandbox, call.cwd)
+ if call.cwd
+ else Path(sandbox.handle).resolve(strict=False)
+ )
+ except _PathViolation as exc:
+ return tool_failure_from("path_violation", exc)
env_arg: dict[str, str] | None = None
if call.env is not None:
env_arg = {**os.environ, **call.env}
@@ -221,11 +243,13 @@ def _command_run(
def _files_read(
self, sandbox: BackendSandbox, call: BackendToolFilesRead
) -> FileContent | ToolExecutionFailure:
- p = self._resolve(sandbox, call.path)
try:
+ p = self._resolve(sandbox, call.path)
if call.encoding is None:
return FileContent(data=p.read_bytes())
return FileContent(data=p.read_text(encoding=call.encoding))
+ except _PathViolation as exc:
+ return tool_failure_from("path_violation", exc)
except FileNotFoundError as exc:
return tool_failure_from("file_not_found", exc, detail=str(p))
except OSError as exc:
@@ -234,13 +258,15 @@ def _files_read(
def _files_write(
self, sandbox: BackendSandbox, call: BackendToolFilesWrite
) -> FileWriteResult | ToolExecutionFailure:
- p = self._resolve(sandbox, call.path)
payload_bytes = (
call.data.encode("utf-8") if isinstance(call.data, str) else call.data
)
try:
+ p = self._resolve(sandbox, call.path)
p.parent.mkdir(parents=True, exist_ok=True)
p.write_bytes(payload_bytes)
+ except _PathViolation as exc:
+ return tool_failure_from("path_violation", exc)
except OSError as exc:
return tool_failure_from("os_error", exc)
with contextlib.suppress(OSError):
@@ -250,8 +276,8 @@ def _files_write(
def _files_list(
self, sandbox: BackendSandbox, call: BackendToolFilesList
) -> FileEntries | ToolExecutionFailure:
- p = self._resolve(sandbox, call.path)
try:
+ p = self._resolve(sandbox, call.path)
entries = [
FileEntry(
name=child.name,
@@ -260,6 +286,8 @@ def _files_list(
)
for child in p.iterdir()
]
+ except _PathViolation as exc:
+ return tool_failure_from("path_violation", exc)
except OSError as exc:
return tool_failure_from("os_error", exc)
entries.sort(key=lambda e: e.name)
@@ -270,7 +298,7 @@ def _files_exists(
) -> bool:
try:
return self._resolve(sandbox, call.path).exists()
- except OSError:
+ except (OSError, _PathViolation):
# Treat permission errors / unreadable parent dirs as "not present"
# rather than raising into the loop; matches POSIX stat() semantics
# from the caller's perspective.
@@ -310,3 +338,14 @@ def _code_run(
stderr=proc.stderr if proc.stderr is not None else b"",
error=error,
)
+
+
+@register("local")
+class LocalBackend(TrustedHostBackend):
+ """Compatibility alias for :class:`TrustedHostBackend`.
+
+ The ``local`` name remains available for v1 compatibility. New code should
+ request ``trusted-host`` so the lack of process isolation is explicit.
+ """
+
+ name: ClassVar[str] = "local"
diff --git a/src/rath/backend/opensandbox.py b/src/rath/backend/opensandbox.py
index 3b347fb..9140da3 100644
--- a/src/rath/backend/opensandbox.py
+++ b/src/rath/backend/opensandbox.py
@@ -301,6 +301,7 @@ async def _run_code_with_retry(
effective = call_timeout if call_timeout is not None else _DEFAULT_TOOL_TIMEOUT_S
last_execution: Any = None
+ saw_client_timeout = False
for attempt in range(_CODE_RUN_ATTEMPTS):
ci = await CodeInterpreter.create(native)
try:
@@ -309,6 +310,7 @@ async def _run_code_with_retry(
effective,
)
except TimeoutError:
+ saw_client_timeout = True
if attempt + 1 >= _CODE_RUN_ATTEMPTS:
raise
logger.debug("OpenSandbox code.run timed out; retrying once")
@@ -318,6 +320,10 @@ async def _run_code_with_retry(
last_execution = execution
if _is_transient_code_run_result(execution):
if attempt + 1 >= _CODE_RUN_ATTEMPTS:
+ if saw_client_timeout:
+ raise TimeoutError(
+ "OpenSandbox code execution remained busy after timeout"
+ )
break
logger.debug(
"OpenSandbox code.run returned transient busy state; "
diff --git a/src/rath/backend/persistence/paths.py b/src/rath/backend/persistence/paths.py
index c11f4f9..f4a64a2 100644
--- a/src/rath/backend/persistence/paths.py
+++ b/src/rath/backend/persistence/paths.py
@@ -15,6 +15,7 @@
from uuid import UUID
from rath.config.paths import resolve_config_dir
+from rath.utils.ids import coerce_uuid_str
__all__ = [
"SANDBOXES_DIR_NAME",
@@ -48,7 +49,7 @@ def local_root() -> Path:
def local_sandbox_dir(sandbox_id: UUID | str) -> Path:
"""``/`` — the stable working_dir for a Local sandbox."""
- return local_root() / str(sandbox_id)
+ return local_root() / coerce_uuid_str(sandbox_id, field="sandbox_id")
def opensandbox_root() -> Path:
@@ -58,7 +59,8 @@ def opensandbox_root() -> Path:
def opensandbox_index_path(sandbox_id: UUID | str) -> Path:
"""``/.json`` — registry entry for a remote sandbox."""
- return opensandbox_root() / f"{sandbox_id}{OPENSANDBOX_INDEX_SUFFIX}"
+ sid = coerce_uuid_str(sandbox_id, field="sandbox_id")
+ return opensandbox_root() / f"{sid}{OPENSANDBOX_INDEX_SUFFIX}"
def ensure_local_root() -> Path:
diff --git a/src/rath/client/__init__.py b/src/rath/client/__init__.py
new file mode 100644
index 0000000..8a6b7b4
--- /dev/null
+++ b/src/rath/client/__init__.py
@@ -0,0 +1,3 @@
+from rath.client.remote import AsyncRemoteClient, RemoteClient
+
+__all__ = ["AsyncRemoteClient", "RemoteClient"]
diff --git a/src/rath/client/remote.py b/src/rath/client/remote.py
new file mode 100644
index 0000000..130a4c1
--- /dev/null
+++ b/src/rath/client/remote.py
@@ -0,0 +1,316 @@
+"""Sync and native-async clients for the Agent Server resource API."""
+
+from __future__ import annotations
+
+from collections.abc import AsyncIterator
+from typing import Any, cast
+
+import httpx
+
+__all__ = ["AsyncRemoteClient", "RemoteClient"]
+
+
+class RemoteClient:
+ def __init__(self, base_url: str, *, token: str, timeout: float = 30.0) -> None:
+ self._client = httpx.Client(
+ base_url=base_url,
+ headers={"Authorization": f"Bearer {token}"},
+ timeout=timeout,
+ )
+
+ def create_run(
+ self,
+ *,
+ assistant_id: str,
+ session_id: str,
+ state: dict[str, object] | None = None,
+ idempotency_key: str | None = None,
+ ) -> dict[str, Any]:
+ headers = {"Idempotency-Key": idempotency_key} if idempotency_key else {}
+ response = self._client.post(
+ "/v1/runs",
+ json={
+ "assistant_id": assistant_id,
+ "session_id": session_id,
+ "state": state or {},
+ },
+ headers=headers,
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def get_run(self, run_id: str) -> dict[str, Any]:
+ response = self._client.get(f"/v1/runs/{run_id}")
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def create_session(self) -> dict[str, Any]:
+ response = self._client.post("/v1/sessions", json={})
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def create_assistant(
+ self, *, assistant_id: str, template_id: str
+ ) -> dict[str, Any]:
+ response = self._client.post(
+ "/v1/assistants",
+ json={"id": assistant_id, "template_id": template_id},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def list_assistants(self) -> tuple[dict[str, Any], ...]:
+ response = self._client.get("/v1/assistants")
+ response.raise_for_status()
+ return tuple(cast(list[dict[str, Any]], response.json()["items"]))
+
+ def store(
+ self,
+ operation: str,
+ payload: dict[str, object],
+ *,
+ user_id: str | None = None,
+ agent_id: str | None = None,
+ session_id: str | None = None,
+ ) -> dict[str, Any]:
+ if operation not in {"put", "search", "delete"}:
+ raise ValueError("store operation must be put, search, or delete")
+ body = {
+ "payload": payload,
+ "user_id": user_id,
+ "agent_id": agent_id,
+ "session_id": session_id,
+ }
+ if operation == "search":
+ response = self._client.post("/v1/store/search", json=body)
+ elif operation == "put":
+ response = self._client.post("/v1/store/items", json=body)
+ else:
+ response = self._client.request("DELETE", "/v1/store/items", json=body)
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def list_runs(self, *, limit: int = 50, after: str | None = None) -> dict[str, Any]:
+ response = self._client.get("/v1/runs", params={"limit": limit, "after": after})
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def cancel_run(self, run_id: str) -> dict[str, Any]:
+ response = self._client.post(f"/v1/runs/{run_id}/cancel")
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def resume_run(self, run_id: str) -> dict[str, Any]:
+ response = self._client.post(
+ f"/v1/runs/{run_id}/resume", json={"confirm": True}
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def list_interrupts(
+ self, *, pending_only: bool = True, limit: int = 50
+ ) -> tuple[dict[str, Any], ...]:
+ response = self._client.get(
+ "/v1/interrupts",
+ params={"pending": str(pending_only).lower(), "limit": limit},
+ )
+ response.raise_for_status()
+ return tuple(cast(list[dict[str, Any]], response.json()["items"]))
+
+ def decide_interrupt(
+ self,
+ interrupt_id: str,
+ *,
+ kind: str,
+ reason: str,
+ payload: dict[str, object] | None = None,
+ ) -> dict[str, Any]:
+ response = self._client.post(
+ f"/v1/interrupts/{interrupt_id}/decision",
+ json={"kind": kind, "reason": reason, "payload": payload or {}},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def events(self, run_id: str, *, after: int = 0) -> tuple[dict[str, Any], ...]:
+ response = self._client.get(
+ f"/v1/runs/{run_id}/events", params={"after": after}
+ )
+ response.raise_for_status()
+ return tuple(cast(list[dict[str, Any]], response.json()["items"]))
+
+ def create_feedback(
+ self,
+ run_id: str,
+ *,
+ key: str,
+ score: float | None = None,
+ value: str | None = None,
+ ) -> dict[str, Any]:
+ response = self._client.post(
+ "/v1/feedback",
+ json={"run_id": run_id, "key": key, "score": score, "value": value},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ def close(self) -> None:
+ self._client.close()
+
+
+class AsyncRemoteClient:
+ def __init__(self, base_url: str, *, token: str, timeout: float = 30.0) -> None:
+ self._client = httpx.AsyncClient(
+ base_url=base_url,
+ headers={"Authorization": f"Bearer {token}"},
+ timeout=timeout,
+ )
+
+ async def create_run(
+ self,
+ *,
+ assistant_id: str,
+ session_id: str,
+ state: dict[str, object] | None = None,
+ idempotency_key: str | None = None,
+ ) -> dict[str, Any]:
+ headers = {"Idempotency-Key": idempotency_key} if idempotency_key else {}
+ response = await self._client.post(
+ "/v1/runs",
+ json={
+ "assistant_id": assistant_id,
+ "session_id": session_id,
+ "state": state or {},
+ },
+ headers=headers,
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def get_run(self, run_id: str) -> dict[str, Any]:
+ response = await self._client.get(f"/v1/runs/{run_id}")
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def create_session(self) -> dict[str, Any]:
+ response = await self._client.post("/v1/sessions", json={})
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def create_assistant(
+ self, *, assistant_id: str, template_id: str
+ ) -> dict[str, Any]:
+ response = await self._client.post(
+ "/v1/assistants",
+ json={"id": assistant_id, "template_id": template_id},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def list_assistants(self) -> tuple[dict[str, Any], ...]:
+ response = await self._client.get("/v1/assistants")
+ response.raise_for_status()
+ return tuple(cast(list[dict[str, Any]], response.json()["items"]))
+
+ async def store(
+ self,
+ operation: str,
+ payload: dict[str, object],
+ *,
+ user_id: str | None = None,
+ agent_id: str | None = None,
+ session_id: str | None = None,
+ ) -> dict[str, Any]:
+ if operation not in {"put", "search", "delete"}:
+ raise ValueError("store operation must be put, search, or delete")
+ body = {
+ "payload": payload,
+ "user_id": user_id,
+ "agent_id": agent_id,
+ "session_id": session_id,
+ }
+ if operation == "search":
+ response = await self._client.post("/v1/store/search", json=body)
+ elif operation == "put":
+ response = await self._client.post("/v1/store/items", json=body)
+ else:
+ response = await self._client.request(
+ "DELETE", "/v1/store/items", json=body
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def list_runs(
+ self, *, limit: int = 50, after: str | None = None
+ ) -> dict[str, Any]:
+ response = await self._client.get(
+ "/v1/runs", params={"limit": limit, "after": after}
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def cancel_run(self, run_id: str) -> dict[str, Any]:
+ response = await self._client.post(f"/v1/runs/{run_id}/cancel")
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def resume_run(self, run_id: str) -> dict[str, Any]:
+ response = await self._client.post(
+ f"/v1/runs/{run_id}/resume", json={"confirm": True}
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def list_interrupts(
+ self, *, pending_only: bool = True, limit: int = 50
+ ) -> tuple[dict[str, Any], ...]:
+ response = await self._client.get(
+ "/v1/interrupts",
+ params={"pending": str(pending_only).lower(), "limit": limit},
+ )
+ response.raise_for_status()
+ return tuple(cast(list[dict[str, Any]], response.json()["items"]))
+
+ async def decide_interrupt(
+ self,
+ interrupt_id: str,
+ *,
+ kind: str,
+ reason: str,
+ payload: dict[str, object] | None = None,
+ ) -> dict[str, Any]:
+ response = await self._client.post(
+ f"/v1/interrupts/{interrupt_id}/decision",
+ json={"kind": kind, "reason": reason, "payload": payload or {}},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def create_feedback(
+ self,
+ run_id: str,
+ *,
+ key: str,
+ score: float | None = None,
+ value: str | None = None,
+ ) -> dict[str, Any]:
+ response = await self._client.post(
+ "/v1/feedback",
+ json={"run_id": run_id, "key": key, "score": score, "value": value},
+ )
+ response.raise_for_status()
+ return cast(dict[str, Any], response.json())
+
+ async def events(
+ self, run_id: str, *, after: int = 0
+ ) -> AsyncIterator[dict[str, Any]]:
+ response = await self._client.get(
+ f"/v1/runs/{run_id}/events",
+ params={"after": after},
+ )
+ response.raise_for_status()
+ for item in response.json()["items"]:
+ yield item
+
+ async def aclose(self) -> None:
+ await self._client.aclose()
diff --git a/src/rath/config/store.py b/src/rath/config/store.py
index 3b268c5..fcefc9c 100644
--- a/src/rath/config/store.py
+++ b/src/rath/config/store.py
@@ -185,6 +185,10 @@ def save(self) -> None:
creds_payload["version"] = SCHEMA_VERSION
atomic_write_json(creds_path, creds_payload, mode=0o600)
chmod_user_only(creds_path)
+ else:
+ # Prevent a removed last key from being restored on the next
+ # load from an obsolete credentials sidecar.
+ creds_path.unlink(missing_ok=True)
# Record/refresh the root layout manifest at the data root.
try:
diff --git a/src/rath/context.py b/src/rath/context.py
new file mode 100644
index 0000000..cf36d4f
--- /dev/null
+++ b/src/rath/context.py
@@ -0,0 +1,107 @@
+"""Request, trace, and durable run context contracts."""
+
+from __future__ import annotations
+
+import secrets
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from uuid import UUID, uuid4
+
+from rath.errors import ErrorCode, RathError
+from rath.security.context import SecurityContext
+
+__all__ = [
+ "DeadlineExceededError",
+ "RunContext",
+ "TraceContext",
+]
+
+
+def _validate_hex(value: str, *, length: int, field_name: str) -> str:
+ normalized = value.lower()
+ if len(normalized) != length:
+ raise ValueError(f"{field_name} must contain {length} hexadecimal characters")
+ try:
+ int(normalized, 16)
+ except ValueError as exc:
+ raise ValueError(f"{field_name} must be hexadecimal") from exc
+ return normalized
+
+
+@dataclass(frozen=True, slots=True)
+class TraceContext:
+ """Minimal W3C-compatible trace correlation identifiers."""
+
+ trace_id: str
+ span_id: str
+ sampled: bool = True
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "trace_id",
+ _validate_hex(self.trace_id, length=32, field_name="trace_id"),
+ )
+ object.__setattr__(
+ self,
+ "span_id",
+ _validate_hex(self.span_id, length=16, field_name="span_id"),
+ )
+
+ @classmethod
+ def new(cls, *, sampled: bool = True) -> "TraceContext":
+ return cls(
+ trace_id=secrets.token_hex(16),
+ span_id=secrets.token_hex(8),
+ sampled=sampled,
+ )
+
+
+class DeadlineExceededError(RathError):
+ def __init__(self) -> None:
+ super().__init__(
+ ErrorCode.DEADLINE_EXCEEDED,
+ "run deadline has been exceeded",
+ retryable=False,
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class RunContext:
+ """Explicit context propagated through runtime and adapter calls."""
+
+ security: SecurityContext
+ revision_id: UUID
+ request_id: UUID = field(default_factory=uuid4)
+ trace_context: TraceContext = field(default_factory=TraceContext.new)
+ deadline: datetime | None = None
+
+ def __post_init__(self) -> None:
+ if self.deadline is not None and self.deadline.tzinfo is None:
+ raise ValueError("deadline must be timezone-aware")
+
+ @classmethod
+ def local(
+ cls,
+ *,
+ revision_id: UUID,
+ deadline: datetime | None = None,
+ ) -> "RunContext":
+ return cls(
+ security=SecurityContext.local(),
+ revision_id=revision_id,
+ deadline=deadline,
+ )
+
+ def remaining_seconds(self, *, now: datetime | None = None) -> float | None:
+ if self.deadline is None:
+ return None
+ current = now or datetime.now(timezone.utc)
+ if current.tzinfo is None:
+ raise ValueError("now must be timezone-aware")
+ return max(0.0, (self.deadline - current).total_seconds())
+
+ def ensure_active(self, *, now: datetime | None = None) -> None:
+ remaining = self.remaining_seconds(now=now)
+ if remaining is not None and remaining <= 0:
+ raise DeadlineExceededError()
diff --git a/src/rath/definition/__init__.py b/src/rath/definition/__init__.py
new file mode 100644
index 0000000..38f1c9e
--- /dev/null
+++ b/src/rath/definition/__init__.py
@@ -0,0 +1,31 @@
+"""Public workflow definition, compiler, and execution-plan contracts."""
+
+from rath.definition.compiler import DefinitionError, WorkflowCompiler
+from rath.definition.decorators import router, step
+from rath.definition.model import (
+ EdgeSpec,
+ EffectClass,
+ ExecutionPlan,
+ NodeKind,
+ NodeSpec,
+ ProviderResource,
+ ResourceManifestV2,
+ RetryPolicy,
+ WorkflowDefinition,
+)
+
+__all__ = [
+ "DefinitionError",
+ "EdgeSpec",
+ "EffectClass",
+ "ExecutionPlan",
+ "NodeKind",
+ "NodeSpec",
+ "ProviderResource",
+ "ResourceManifestV2",
+ "RetryPolicy",
+ "router",
+ "step",
+ "WorkflowCompiler",
+ "WorkflowDefinition",
+]
diff --git a/src/rath/definition/compiler.py b/src/rath/definition/compiler.py
new file mode 100644
index 0000000..03efba0
--- /dev/null
+++ b/src/rath/definition/compiler.py
@@ -0,0 +1,247 @@
+"""Deterministic compiler from Python Workflow declarations to ExecutionPlan."""
+
+from __future__ import annotations
+
+import hashlib
+import inspect
+import json
+import textwrap
+from collections.abc import Callable, Mapping
+from uuid import NAMESPACE_URL, UUID, uuid5
+
+from rath._json import JSONValue, thaw_json
+from rath.definition.decorators import _metadata
+from rath.definition.model import (
+ EdgeSpec,
+ EffectClass,
+ ExecutionPlan,
+ NodeKind,
+ NodeSpec,
+ ProviderResource,
+ ResourceManifestV2,
+ RetryPolicy,
+ WorkflowDefinition,
+)
+
+__all__ = ["DefinitionError", "WorkflowCompiler"]
+
+
+class DefinitionError(ValueError):
+ """Workflow declaration cannot produce a safe deterministic plan."""
+
+
+class WorkflowCompiler:
+ """Compile explicit Python step boundaries without executing workflow code."""
+
+ def compile(
+ self,
+ workflow: object,
+ *,
+ revision_id: UUID,
+ production_durable: bool = False,
+ input_schema: Mapping[str, JSONValue] | None = None,
+ state_schema: Mapping[str, JSONValue] | None = None,
+ policy_manifest: Mapping[str, JSONValue] | None = None,
+ ) -> ExecutionPlan:
+ name = f"{type(workflow).__module__}.{type(workflow).__qualname__}"
+ version = str(getattr(workflow, "workflow_version", "1"))
+ nodes, entrypoint, durable, issues = self._nodes(workflow)
+ self._validate(
+ nodes,
+ entrypoint,
+ production_durable=production_durable,
+ )
+ edges = tuple(
+ EdgeSpec(source=node.id, target=target)
+ for node in nodes
+ for target in node.successors
+ )
+ definition_payload = {
+ "name": name,
+ "version": version,
+ "entrypoint": entrypoint,
+ "nodes": [node.to_dict() for node in nodes],
+ "edges": [edge.to_dict() for edge in edges],
+ "input_schema": thaw_json(input_schema or {}),
+ "state_schema": thaw_json(state_schema or {}),
+ }
+ definition_json = json.dumps(
+ definition_payload,
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ definition_hash = hashlib.sha256(definition_json.encode("utf-8")).hexdigest()
+ definition_id = uuid5(NAMESPACE_URL, f"openrath:definition:{definition_hash}")
+ definition = WorkflowDefinition(
+ id=definition_id,
+ name=name,
+ version=version,
+ entrypoint=entrypoint,
+ nodes=nodes,
+ edges=edges,
+ input_schema=input_schema or {},
+ state_schema=state_schema or {},
+ )
+ resources = self._resources(workflow)
+ plan_seed = json.dumps(
+ {
+ "definition_hash": definition_hash,
+ "revision_id": str(revision_id),
+ "resources": resources.to_dict(),
+ "policy_manifest": thaw_json(policy_manifest or {}),
+ },
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ plan_id = uuid5(NAMESPACE_URL, f"openrath:plan:{plan_seed}")
+ return ExecutionPlan(
+ id=plan_id,
+ definition_hash=definition_hash,
+ revision_id=revision_id,
+ definition=definition,
+ nodes=nodes,
+ resources=resources,
+ policy_manifest=policy_manifest or {},
+ durable=durable,
+ compatibility_issues=issues,
+ )
+
+ def _nodes(
+ self,
+ workflow: object,
+ ) -> tuple[tuple[NodeSpec, ...], str, bool, tuple[str, ...]]:
+ discovered: list[tuple[str, Callable[..., object]]] = []
+ for name, function in inspect.getmembers(type(workflow), predicate=callable):
+ if _metadata(function) is not None:
+ discovered.append((name, function))
+ if not discovered:
+ opaque = NodeSpec(
+ id="legacy.forward",
+ kind=NodeKind.OPAQUE,
+ handler=f"{type(workflow).__module__}.{type(workflow).__qualname__}.forward",
+ implementation_hash=self._implementation_hash(
+ getattr(type(workflow), "forward")
+ ),
+ is_async=inspect.iscoroutinefunction(
+ getattr(workflow, "forward", None)
+ ),
+ retry=RetryPolicy(),
+ effects=EffectClass.NON_IDEMPOTENT,
+ checkpoint=False,
+ )
+ return (
+ (opaque,),
+ opaque.id,
+ False,
+ (
+ "legacy forward() is opaque and cannot resume across checkpoint boundaries",
+ ),
+ )
+
+ nodes: list[NodeSpec] = []
+ entries: list[str] = []
+ for name, function in discovered:
+ metadata = _metadata(function)
+ assert metadata is not None
+ if metadata.entry:
+ entries.append(name)
+ nodes.append(
+ NodeSpec(
+ id=name,
+ kind=metadata.kind,
+ handler=f"{type(workflow).__module__}.{type(workflow).__qualname__}.{name}",
+ implementation_hash=self._implementation_hash(function),
+ is_async=inspect.iscoroutinefunction(function),
+ retry=metadata.retry,
+ effects=metadata.effects,
+ idempotency_key=metadata.idempotency_key,
+ timeout_seconds=metadata.timeout_seconds,
+ checkpoint=metadata.checkpoint,
+ successors=metadata.successors,
+ )
+ )
+ if len(entries) != 1:
+ raise DefinitionError(
+ f"workflow must declare exactly one entrypoint; found {len(entries)}"
+ )
+ return tuple(nodes), entries[0], True, ()
+
+ @staticmethod
+ def _implementation_hash(function: Callable[..., object]) -> str:
+ """Fingerprint executable source so behavior changes alter plan identity."""
+ try:
+ material = textwrap.dedent(inspect.getsource(function)).strip()
+ except (OSError, TypeError):
+ code = function.__code__
+ material = json.dumps(
+ {
+ "bytecode": code.co_code.hex(),
+ "constants": repr(code.co_consts),
+ "names": code.co_names,
+ "varnames": code.co_varnames,
+ "argcount": code.co_argcount,
+ "kwonlyargcount": code.co_kwonlyargcount,
+ },
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ return hashlib.sha256(material.encode("utf-8")).hexdigest()
+
+ def _validate(
+ self,
+ nodes: tuple[NodeSpec, ...],
+ entrypoint: str,
+ *,
+ production_durable: bool = False,
+ ) -> None:
+ ids = {node.id for node in nodes}
+ if len(ids) != len(nodes):
+ raise DefinitionError("workflow node ids must be unique")
+ for node in nodes:
+ if (
+ production_durable
+ and not node.is_async
+ and node.timeout_seconds is not None
+ ):
+ raise DefinitionError(
+ "synchronous durable steps cannot guarantee preemptive timeout; "
+ "use an async handler or an isolated executor"
+ )
+ for successor in node.successors:
+ if successor not in ids:
+ raise DefinitionError(
+ f"node {node.id!r} references unknown successor {successor!r}"
+ )
+ if node.kind is NodeKind.ROUTER and not node.successors:
+ raise DefinitionError(f"router {node.id!r} requires successors")
+
+ reachable: set[str] = set()
+ pending = [entrypoint]
+ by_id = {node.id: node for node in nodes}
+ while pending:
+ current = pending.pop()
+ if current in reachable:
+ continue
+ reachable.add(current)
+ pending.extend(by_id[current].successors)
+ unreachable = sorted(ids - reachable)
+ if unreachable:
+ raise DefinitionError(f"unreachable workflow nodes: {unreachable}")
+
+ def _resources(self, workflow: object) -> ResourceManifestV2:
+ providers: list[ProviderResource] = []
+ named_agents = getattr(workflow, "named_agents", None)
+ if callable(named_agents):
+ for path, agent in named_agents():
+ provider = agent.provider
+ providers.append(
+ ProviderResource(
+ path=path,
+ provider_kind=provider.provider_kind or "openai",
+ model=provider.model,
+ has_memory=agent.memory is not None,
+ )
+ )
+ return ResourceManifestV2(providers=tuple(providers))
diff --git a/src/rath/definition/decorators.py b/src/rath/definition/decorators.py
new file mode 100644
index 0000000..10ec048
--- /dev/null
+++ b/src/rath/definition/decorators.py
@@ -0,0 +1,96 @@
+"""Explicit durable step and router boundaries for Python workflows."""
+
+from __future__ import annotations
+
+from collections.abc import Callable
+from dataclasses import dataclass, field
+from typing import Any, TypeVar, cast
+
+from rath.definition.model import EffectClass, NodeKind, RetryPolicy
+
+__all__ = ["router", "step"]
+
+F = TypeVar("F", bound=Callable[..., Any])
+_METADATA_ATTR = "__openrath_node_spec__"
+
+
+@dataclass(frozen=True, slots=True)
+class _NodeMetadata:
+ kind: NodeKind
+ entry: bool
+ successors: tuple[str, ...]
+ retry: RetryPolicy = field(default_factory=RetryPolicy)
+ effects: EffectClass = EffectClass.NON_IDEMPOTENT
+ idempotency_key: str | None = None
+ timeout_seconds: float | None = None
+ checkpoint: bool = True
+
+
+def _decorate(function: F, metadata: _NodeMetadata) -> F:
+ if hasattr(function, _METADATA_ATTR):
+ raise ValueError(f"{function.__qualname__} already has OpenRath node metadata")
+ if (
+ metadata.effects is EffectClass.NON_IDEMPOTENT
+ and metadata.retry.max_attempts > 1
+ and not metadata.idempotency_key
+ ):
+ raise ValueError("non-idempotent retries require idempotency_key")
+ setattr(function, _METADATA_ATTR, metadata)
+ return function
+
+
+def step(
+ *,
+ entry: bool = False,
+ successors: tuple[str, ...] = (),
+ retry: RetryPolicy | None = None,
+ effects: EffectClass = EffectClass.NON_IDEMPOTENT,
+ idempotency_key: str | None = None,
+ timeout_seconds: float | None = None,
+ checkpoint: bool = True,
+) -> Callable[[F], F]:
+ """Mark a method as a checkpointable execution step."""
+
+ def decorator(function: F) -> F:
+ return _decorate(
+ function,
+ _NodeMetadata(
+ kind=NodeKind.STEP,
+ entry=entry,
+ successors=tuple(successors),
+ retry=retry or RetryPolicy(),
+ effects=effects,
+ idempotency_key=idempotency_key,
+ timeout_seconds=timeout_seconds,
+ checkpoint=checkpoint,
+ ),
+ )
+
+ return decorator
+
+
+def router(
+ *,
+ successors: tuple[str, ...],
+ entry: bool = False,
+) -> Callable[[F], F]:
+ """Mark a pure routing method with an explicit successor allowlist."""
+ if not successors:
+ raise ValueError("router successors must not be empty")
+
+ def decorator(function: F) -> F:
+ return _decorate(
+ function,
+ _NodeMetadata(
+ kind=NodeKind.ROUTER,
+ entry=entry,
+ successors=tuple(successors),
+ effects=EffectClass.NONE,
+ ),
+ )
+
+ return decorator
+
+
+def _metadata(function: Callable[..., Any]) -> _NodeMetadata | None:
+ return cast(_NodeMetadata | None, getattr(function, _METADATA_ATTR, None))
diff --git a/src/rath/definition/model.py b/src/rath/definition/model.py
new file mode 100644
index 0000000..7784b3f
--- /dev/null
+++ b/src/rath/definition/model.py
@@ -0,0 +1,220 @@
+"""Versioned workflow-definition and executable-plan value objects."""
+
+from __future__ import annotations
+
+import json
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from enum import Enum
+from uuid import UUID
+
+from rath._json import JSONValue, freeze_mapping, thaw_json
+
+__all__ = [
+ "EdgeSpec",
+ "EffectClass",
+ "ExecutionPlan",
+ "NodeKind",
+ "NodeSpec",
+ "ProviderResource",
+ "ResourceManifestV2",
+ "RetryPolicy",
+ "WorkflowDefinition",
+]
+
+
+class EffectClass(str, Enum):
+ NONE = "none"
+ READ_ONLY = "read_only"
+ IDEMPOTENT = "idempotent"
+ NON_IDEMPOTENT = "non_idempotent"
+
+
+class NodeKind(str, Enum):
+ STEP = "step"
+ ROUTER = "router"
+ OPAQUE = "opaque"
+
+
+@dataclass(frozen=True, slots=True)
+class RetryPolicy:
+ max_attempts: int = 1
+ base_seconds: float = 0.25
+ max_seconds: float = 30.0
+
+ def __post_init__(self) -> None:
+ if self.max_attempts < 1:
+ raise ValueError("max_attempts must be at least 1")
+ if self.base_seconds <= 0:
+ raise ValueError("base_seconds must be greater than zero")
+ if self.max_seconds < self.base_seconds:
+ raise ValueError(
+ "max_seconds must be greater than or equal to base_seconds"
+ )
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "max_attempts": self.max_attempts,
+ "base_seconds": self.base_seconds,
+ "max_seconds": self.max_seconds,
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class NodeSpec:
+ id: str
+ kind: NodeKind
+ handler: str
+ is_async: bool
+ implementation_hash: str | None = None
+ retry: RetryPolicy = field(default_factory=RetryPolicy)
+ effects: EffectClass = EffectClass.NON_IDEMPOTENT
+ idempotency_key: str | None = None
+ timeout_seconds: float | None = None
+ checkpoint: bool = True
+ successors: tuple[str, ...] = ()
+
+ def __post_init__(self) -> None:
+ if not self.id.strip():
+ raise ValueError("node id must not be empty")
+ if not self.handler.strip():
+ raise ValueError("node handler must not be empty")
+ if self.implementation_hash is not None:
+ if len(self.implementation_hash) != 64:
+ raise ValueError("node implementation_hash must be a SHA-256 digest")
+ int(self.implementation_hash, 16)
+ if self.timeout_seconds is not None and self.timeout_seconds <= 0:
+ raise ValueError("node timeout_seconds must be greater than zero")
+ if (
+ self.effects is EffectClass.NON_IDEMPOTENT
+ and self.retry.max_attempts > 1
+ and not self.idempotency_key
+ ):
+ raise ValueError("non-idempotent retries require a stable idempotency key")
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "id": self.id,
+ "kind": self.kind.value,
+ "handler": self.handler,
+ "implementation_hash": self.implementation_hash,
+ "is_async": self.is_async,
+ "retry": self.retry.to_dict(),
+ "effects": self.effects.value,
+ "idempotency_key": self.idempotency_key,
+ "timeout_seconds": self.timeout_seconds,
+ "checkpoint": self.checkpoint,
+ "successors": list(self.successors),
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class EdgeSpec:
+ source: str
+ target: str
+
+ def to_dict(self) -> dict[str, str]:
+ return {"source": self.source, "target": self.target}
+
+
+@dataclass(frozen=True, slots=True)
+class WorkflowDefinition:
+ id: UUID
+ name: str
+ version: str
+ entrypoint: str
+ nodes: tuple[NodeSpec, ...]
+ edges: tuple[EdgeSpec, ...]
+ input_schema: Mapping[str, JSONValue] = field(default_factory=dict)
+ state_schema: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "input_schema",
+ freeze_mapping(self.input_schema, field="definition.input_schema"),
+ )
+ object.__setattr__(
+ self,
+ "state_schema",
+ freeze_mapping(self.state_schema, field="definition.state_schema"),
+ )
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "id": str(self.id),
+ "name": self.name,
+ "version": self.version,
+ "entrypoint": self.entrypoint,
+ "nodes": [node.to_dict() for node in self.nodes],
+ "edges": [edge.to_dict() for edge in self.edges],
+ "input_schema": thaw_json(self.input_schema),
+ "state_schema": thaw_json(self.state_schema),
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class ProviderResource:
+ path: str
+ provider_kind: str
+ model: str | None
+ has_memory: bool
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "path": self.path,
+ "provider_kind": self.provider_kind,
+ "model": self.model,
+ "has_memory": self.has_memory,
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class ResourceManifestV2:
+ providers: tuple[ProviderResource, ...] = ()
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "providers": [provider.to_dict() for provider in self.providers],
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class ExecutionPlan:
+ id: UUID
+ definition_hash: str
+ revision_id: UUID
+ definition: WorkflowDefinition
+ nodes: tuple[NodeSpec, ...]
+ resources: ResourceManifestV2
+ policy_manifest: Mapping[str, JSONValue]
+ durable: bool
+ compatibility_issues: tuple[str, ...] = ()
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "policy_manifest",
+ freeze_mapping(self.policy_manifest, field="plan.policy_manifest"),
+ )
+
+ def to_dict(self) -> dict[str, object]:
+ return {
+ "id": str(self.id),
+ "definition_hash": self.definition_hash,
+ "revision_id": str(self.revision_id),
+ "definition": self.definition.to_dict(),
+ "nodes": [node.to_dict() for node in self.nodes],
+ "resources": self.resources.to_dict(),
+ "policy_manifest": thaw_json(self.policy_manifest),
+ "durable": self.durable,
+ "compatibility_issues": list(self.compatibility_issues),
+ }
+
+ def canonical_json(self) -> str:
+ return json.dumps(
+ self.to_dict(),
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ )
diff --git a/src/rath/deployment/__init__.py b/src/rath/deployment/__init__.py
new file mode 100644
index 0000000..e0c213c
--- /dev/null
+++ b/src/rath/deployment/__init__.py
@@ -0,0 +1,19 @@
+"""Immutable deployment revision contracts."""
+
+from rath.deployment.revisions import (
+ DeploymentManifest,
+ PostgresRevisionStore,
+ Revision,
+ RevisionConflict,
+ RevisionStore,
+ SQLiteRevisionStore,
+)
+
+__all__ = [
+ "DeploymentManifest",
+ "PostgresRevisionStore",
+ "Revision",
+ "RevisionConflict",
+ "RevisionStore",
+ "SQLiteRevisionStore",
+]
diff --git a/src/rath/deployment/revisions.py b/src/rath/deployment/revisions.py
new file mode 100644
index 0000000..7a8bc48
--- /dev/null
+++ b/src/rath/deployment/revisions.py
@@ -0,0 +1,221 @@
+"""Immutable, content-identified deployment revisions."""
+
+from __future__ import annotations
+
+import hashlib
+import json
+import sqlite3
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from typing import Any, Protocol, runtime_checkable
+from uuid import NAMESPACE_URL, UUID, uuid5
+
+from rath._json import JSONValue, freeze_mapping, thaw_json
+from rath.runtime import PostgresRunStore, SQLiteRunStore
+
+__all__ = [
+ "DeploymentManifest",
+ "PostgresRevisionStore",
+ "Revision",
+ "RevisionConflict",
+ "RevisionStore",
+ "SQLiteRevisionStore",
+]
+
+
+class RevisionConflict(RuntimeError):
+ pass
+
+
+@dataclass(frozen=True, slots=True)
+class DeploymentManifest:
+ image_digest: str
+ plan_hash: str
+ python_version: str
+ dependencies_digest: str
+ resources: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ for name, value in (
+ ("image_digest", self.image_digest),
+ ("plan_hash", self.plan_hash),
+ ("dependencies_digest", self.dependencies_digest),
+ ):
+ if len(value) != 64:
+ raise ValueError(f"{name} must be a SHA-256 digest")
+ int(value, 16)
+ object.__setattr__(
+ self,
+ "resources",
+ freeze_mapping(self.resources, field="deployment.resources"),
+ )
+
+ def canonical_json(self) -> str:
+ return json.dumps(
+ {
+ "image_digest": self.image_digest,
+ "plan_hash": self.plan_hash,
+ "python_version": self.python_version,
+ "dependencies_digest": self.dependencies_digest,
+ "resources": thaw_json(self.resources),
+ },
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class Revision:
+ id: UUID
+ code_digest: str
+ manifest: DeploymentManifest
+ created_at: datetime
+
+ @classmethod
+ def create(cls, *, code_digest: str, manifest: DeploymentManifest) -> "Revision":
+ if len(code_digest) != 64:
+ raise ValueError("code_digest must be a SHA-256 digest")
+ int(code_digest, 16)
+ identity = uuid5(
+ NAMESPACE_URL,
+ f"openrath-revision:{code_digest}:{manifest.canonical_json()}",
+ )
+ return cls(identity, code_digest, manifest, datetime.now(timezone.utc))
+
+ @property
+ def content_digest(self) -> str:
+ """SHA-256 identity covering executable code and deployment manifest."""
+
+ payload = json.dumps(
+ {
+ "code_digest": self.code_digest,
+ "manifest": json.loads(self.manifest.canonical_json()),
+ },
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ return hashlib.sha256(payload.encode("utf-8")).hexdigest()
+
+
+@runtime_checkable
+class RevisionStore(Protocol):
+ def put(self, revision: Revision) -> Revision: ...
+
+ def get(self, revision_id: UUID) -> Revision: ...
+
+
+def _manifest(value: str | Mapping[str, Any]) -> DeploymentManifest:
+ data = json.loads(value) if isinstance(value, str) else value
+ return DeploymentManifest(
+ image_digest=data["image_digest"],
+ plan_hash=data["plan_hash"],
+ python_version=data["python_version"],
+ dependencies_digest=data["dependencies_digest"],
+ resources=data["resources"],
+ )
+
+
+class SQLiteRevisionStore:
+ def __init__(self, run_store: SQLiteRunStore) -> None:
+ self.path = str(run_store.path)
+
+ def put(self, revision: Revision) -> Revision:
+ with sqlite3.connect(self.path) as connection:
+ existing = connection.execute(
+ "SELECT * FROM revisions WHERE id = ?", (str(revision.id),)
+ ).fetchone()
+ if existing is not None:
+ loaded = self.get(revision.id)
+ if (
+ loaded.code_digest != revision.code_digest
+ or loaded.manifest != revision.manifest
+ ):
+ raise RevisionConflict("revision identity is immutable")
+ return loaded
+ connection.execute(
+ """
+ INSERT INTO revisions(
+ id, content_digest, code_digest, plan_hash,
+ manifest_json, created_at
+ ) VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(revision.id),
+ revision.content_digest,
+ revision.code_digest,
+ revision.manifest.plan_hash,
+ revision.manifest.canonical_json(),
+ revision.created_at.isoformat(),
+ ),
+ )
+ return revision
+
+ def get(self, revision_id: UUID) -> Revision:
+ connection = sqlite3.connect(self.path)
+ connection.row_factory = sqlite3.Row
+ try:
+ row = connection.execute(
+ "SELECT * FROM revisions WHERE id = ?", (str(revision_id),)
+ ).fetchone()
+ finally:
+ connection.close()
+ if row is None:
+ raise KeyError(str(revision_id))
+ return Revision(
+ id=UUID(row["id"]),
+ code_digest=row["code_digest"],
+ manifest=_manifest(row["manifest_json"]),
+ created_at=datetime.fromisoformat(row["created_at"]),
+ )
+
+
+class PostgresRevisionStore:
+ def __init__(self, run_store: PostgresRunStore) -> None:
+ self.run_store = run_store
+
+ def put(self, revision: Revision) -> Revision:
+ from psycopg.types.json import Jsonb
+
+ manifest = json.loads(revision.manifest.canonical_json())
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ """
+ INSERT INTO revisions(
+ id, content_digest, code_digest, plan_hash,
+ manifest_json, created_at
+ ) VALUES (%s, %s, %s, %s, %s, %s)
+ ON CONFLICT (id) DO NOTHING RETURNING id
+ """,
+ (
+ revision.id,
+ revision.content_digest,
+ revision.code_digest,
+ revision.manifest.plan_hash,
+ Jsonb(manifest),
+ revision.created_at,
+ ),
+ ).fetchone()
+ if row is None:
+ loaded = self.get(revision.id)
+ if (
+ loaded.code_digest != revision.code_digest
+ or loaded.manifest != revision.manifest
+ ):
+ raise RevisionConflict("revision identity is immutable")
+ return loaded
+ return revision
+
+ def get(self, revision_id: UUID) -> Revision:
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ "SELECT * FROM revisions WHERE id = %s", (revision_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(revision_id))
+ return Revision(
+ id=row["id"],
+ code_digest=row["code_digest"],
+ manifest=_manifest(row["manifest_json"]),
+ created_at=row["created_at"],
+ )
diff --git a/src/rath/errors.py b/src/rath/errors.py
new file mode 100644
index 0000000..a97fbb7
--- /dev/null
+++ b/src/rath/errors.py
@@ -0,0 +1,59 @@
+"""Stable machine-readable errors for OpenRath v2 public contracts."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from enum import Enum
+from typing import Any
+
+from rath._json import JSONValue, freeze_mapping, thaw_json
+
+__all__ = ["ErrorCode", "RathError"]
+
+
+class ErrorCode(str, Enum):
+ """Stable error identifiers; enum values are part of the public API."""
+
+ INVALID_ARGUMENT = "request.invalid_argument"
+ UNAUTHENTICATED = "security.unauthenticated"
+ FORBIDDEN = "security.forbidden"
+ APPROVAL_REQUIRED = "security.approval_required"
+ POLICY_ERROR = "security.policy_error"
+ CONFLICT = "resource.conflict"
+ NOT_FOUND = "resource.not_found"
+ DEADLINE_EXCEEDED = "runtime.deadline_exceeded"
+ CANCELLED = "runtime.cancelled"
+ UNAVAILABLE = "runtime.unavailable"
+ INTERNAL = "internal.error"
+
+
+class RathError(RuntimeError):
+ """Base exception with a stable code and serialization contract."""
+
+ def __init__(
+ self,
+ code: ErrorCode,
+ message: str,
+ *,
+ retryable: bool = False,
+ details: Mapping[str, object] | None = None,
+ ) -> None:
+ if not message:
+ raise ValueError("message must not be empty")
+ super().__init__(message)
+ self.code = code
+ self.message = message
+ self.retryable = bool(retryable)
+ self.details: Mapping[str, JSONValue] = freeze_mapping(
+ details,
+ field="details",
+ )
+
+ def to_dict(self) -> dict[str, Any]:
+ """Return the stable transport representation."""
+ return {
+ "code": self.code.value,
+ "message": self.message,
+ "retryable": self.retryable,
+ "details": thaw_json(self.details),
+ }
diff --git a/src/rath/eval/__init__.py b/src/rath/eval/__init__.py
new file mode 100644
index 0000000..7fa7b1b
--- /dev/null
+++ b/src/rath/eval/__init__.py
@@ -0,0 +1,28 @@
+from rath.eval.models import (
+ Dataset,
+ EvaluationResult,
+ Evaluator,
+ Example,
+ Experiment,
+ GateDecision,
+)
+from rath.eval.runner import EvaluationRunner, regression_gate
+from rath.eval.store import (
+ EvaluationStore,
+ PostgresEvaluationStore,
+ SQLiteEvaluationStore,
+)
+
+__all__ = [
+ "Dataset",
+ "EvaluationResult",
+ "EvaluationRunner",
+ "EvaluationStore",
+ "Evaluator",
+ "Example",
+ "Experiment",
+ "GateDecision",
+ "PostgresEvaluationStore",
+ "SQLiteEvaluationStore",
+ "regression_gate",
+]
diff --git a/src/rath/eval/models.py b/src/rath/eval/models.py
new file mode 100644
index 0000000..fc956b1
--- /dev/null
+++ b/src/rath/eval/models.py
@@ -0,0 +1,98 @@
+"""Versioned evaluation datasets, results, and experiment summaries."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from enum import Enum
+from typing import Protocol, runtime_checkable
+from uuid import UUID, uuid4
+
+from rath._json import JSONValue, freeze_mapping
+from rath.runtime import Run
+
+__all__ = [
+ "Dataset",
+ "EvaluationResult",
+ "Evaluator",
+ "Example",
+ "Experiment",
+ "GateDecision",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class Example:
+ id: UUID
+ inputs: Mapping[str, JSONValue]
+ expected: Mapping[str, JSONValue]
+
+ def __post_init__(self) -> None:
+ object.__setattr__(self, "inputs", freeze_mapping(self.inputs, field="inputs"))
+ object.__setattr__(
+ self, "expected", freeze_mapping(self.expected, field="expected")
+ )
+
+ @classmethod
+ def create(
+ cls,
+ inputs: Mapping[str, object],
+ expected: Mapping[str, object],
+ ) -> "Example":
+ return cls(
+ id=uuid4(),
+ inputs=freeze_mapping(inputs, field="inputs"),
+ expected=freeze_mapping(expected, field="expected"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class Dataset:
+ id: UUID
+ name: str
+ version: str
+ examples: tuple[Example, ...]
+
+
+@dataclass(frozen=True, slots=True)
+class EvaluationResult:
+ evaluator: str
+ score: float
+ passed: bool
+ reason: str
+ metadata: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ if not 0 <= self.score <= 1:
+ raise ValueError("evaluation score must be between 0 and 1")
+ object.__setattr__(
+ self,
+ "metadata",
+ freeze_mapping(self.metadata, field="evaluation.metadata"),
+ )
+
+
+@runtime_checkable
+class Evaluator(Protocol):
+ name: str
+
+ async def evaluate(self, example: Example, run: Run) -> EvaluationResult: ...
+
+
+@dataclass(frozen=True, slots=True)
+class Experiment:
+ id: UUID
+ dataset_id: UUID
+ revision_id: UUID
+ results: tuple[EvaluationResult, ...]
+
+ @property
+ def mean_score(self) -> float:
+ if not self.results:
+ return 0.0
+ return sum(result.score for result in self.results) / len(self.results)
+
+
+class GateDecision(str, Enum):
+ PASS = "pass"
+ FAIL = "fail"
diff --git a/src/rath/eval/runner.py b/src/rath/eval/runner.py
new file mode 100644
index 0000000..400bbdc
--- /dev/null
+++ b/src/rath/eval/runner.py
@@ -0,0 +1,54 @@
+"""Offline evaluation runner and baseline regression gate."""
+
+from __future__ import annotations
+
+from collections.abc import Awaitable, Callable, Sequence
+from uuid import UUID, uuid4
+
+from rath.eval.models import (
+ Dataset,
+ EvaluationResult,
+ Evaluator,
+ Example,
+ Experiment,
+ GateDecision,
+)
+from rath.runtime import Run
+
+__all__ = ["EvaluationRunner", "regression_gate"]
+
+
+class EvaluationRunner:
+ async def run(
+ self,
+ dataset: Dataset,
+ *,
+ revision_id: UUID,
+ execute: Callable[[Example], Awaitable[Run]],
+ evaluators: Sequence[Evaluator],
+ ) -> Experiment:
+ results: list[EvaluationResult] = []
+ for example in dataset.examples:
+ run = await execute(example)
+ for evaluator in evaluators:
+ results.append(await evaluator.evaluate(example, run))
+ return Experiment(
+ id=uuid4(),
+ dataset_id=dataset.id,
+ revision_id=revision_id,
+ results=tuple(results),
+ )
+
+
+def regression_gate(
+ candidate: Experiment,
+ *,
+ baseline: Experiment,
+ maximum_regression: float = 0.02,
+ minimum_score: float = 0.8,
+) -> GateDecision:
+ if candidate.mean_score < minimum_score:
+ return GateDecision.FAIL
+ if candidate.mean_score < baseline.mean_score - maximum_regression:
+ return GateDecision.FAIL
+ return GateDecision.PASS
diff --git a/src/rath/eval/store.py b/src/rath/eval/store.py
new file mode 100644
index 0000000..ec57fa0
--- /dev/null
+++ b/src/rath/eval/store.py
@@ -0,0 +1,225 @@
+"""Durable evaluation dataset and experiment stores."""
+
+from __future__ import annotations
+
+import json
+import sqlite3
+from collections.abc import Mapping
+from datetime import datetime, timezone
+from typing import Any, Protocol, runtime_checkable
+from uuid import UUID
+
+from rath._json import thaw_json
+from rath.eval.models import Dataset, EvaluationResult, Example, Experiment
+from rath.runtime import PostgresRunStore, SQLiteRunStore
+
+__all__ = [
+ "EvaluationStore",
+ "PostgresEvaluationStore",
+ "SQLiteEvaluationStore",
+]
+
+
+def _dataset_json(dataset: Dataset) -> list[dict[str, object]]:
+ return [
+ {
+ "id": str(example.id),
+ "inputs": thaw_json(example.inputs),
+ "expected": thaw_json(example.expected),
+ }
+ for example in dataset.examples
+ ]
+
+
+def _results_json(experiment: Experiment) -> list[dict[str, object]]:
+ return [
+ {
+ "evaluator": result.evaluator,
+ "score": result.score,
+ "passed": result.passed,
+ "reason": result.reason,
+ "metadata": thaw_json(result.metadata),
+ }
+ for result in experiment.results
+ ]
+
+
+def _dataset(row: Mapping[str, Any]) -> Dataset:
+ values = row["examples_json"]
+ if isinstance(values, str):
+ values = json.loads(values)
+ return Dataset(
+ id=UUID(str(row["id"])),
+ name=row["name"],
+ version=row["version"],
+ examples=tuple(
+ Example(
+ id=UUID(item["id"]),
+ inputs=item["inputs"],
+ expected=item["expected"],
+ )
+ for item in values
+ ),
+ )
+
+
+def _experiment(row: Mapping[str, Any]) -> Experiment:
+ values = row["results_json"]
+ if isinstance(values, str):
+ values = json.loads(values)
+ return Experiment(
+ id=UUID(str(row["id"])),
+ dataset_id=UUID(str(row["dataset_id"])),
+ revision_id=UUID(str(row["revision_id"])),
+ results=tuple(
+ EvaluationResult(
+ evaluator=item["evaluator"],
+ score=float(item["score"]),
+ passed=bool(item["passed"]),
+ reason=item["reason"],
+ metadata=item["metadata"],
+ )
+ for item in values
+ ),
+ )
+
+
+@runtime_checkable
+class EvaluationStore(Protocol):
+ def save_dataset(self, dataset: Dataset) -> Dataset: ...
+
+ def get_dataset(self, dataset_id: UUID) -> Dataset: ...
+
+ def save_experiment(self, experiment: Experiment) -> Experiment: ...
+
+ def get_experiment(self, experiment_id: UUID) -> Experiment: ...
+
+
+class SQLiteEvaluationStore:
+ def __init__(self, run_store: SQLiteRunStore) -> None:
+ self.path = str(run_store.path)
+
+ def _connect(self) -> sqlite3.Connection:
+ connection = sqlite3.connect(self.path)
+ connection.row_factory = sqlite3.Row
+ connection.execute("PRAGMA foreign_keys = ON")
+ return connection
+
+ def save_dataset(self, dataset: Dataset) -> Dataset:
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT INTO evaluation_datasets(id, name, version, examples_json)
+ VALUES (?, ?, ?, ?)
+ ON CONFLICT(name, version) DO UPDATE
+ SET examples_json = excluded.examples_json
+ """,
+ (
+ str(dataset.id),
+ dataset.name,
+ dataset.version,
+ json.dumps(_dataset_json(dataset), separators=(",", ":")),
+ ),
+ )
+ return dataset
+
+ def get_dataset(self, dataset_id: UUID) -> Dataset:
+ with self._connect() as connection:
+ row = connection.execute(
+ "SELECT * FROM evaluation_datasets WHERE id = ?",
+ (str(dataset_id),),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(dataset_id))
+ return _dataset(row)
+
+ def save_experiment(self, experiment: Experiment) -> Experiment:
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT INTO evaluation_experiments(
+ id, dataset_id, revision_id, results_json, created_at
+ ) VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ str(experiment.id),
+ str(experiment.dataset_id),
+ str(experiment.revision_id),
+ json.dumps(_results_json(experiment), separators=(",", ":")),
+ datetime.now(timezone.utc).isoformat(),
+ ),
+ )
+ return experiment
+
+ def get_experiment(self, experiment_id: UUID) -> Experiment:
+ with self._connect() as connection:
+ row = connection.execute(
+ "SELECT * FROM evaluation_experiments WHERE id = ?",
+ (str(experiment_id),),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(experiment_id))
+ return _experiment(row)
+
+
+class PostgresEvaluationStore:
+ def __init__(self, run_store: PostgresRunStore) -> None:
+ self.run_store = run_store
+
+ def save_dataset(self, dataset: Dataset) -> Dataset:
+ from psycopg.types.json import Jsonb
+
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO evaluation_datasets(id, name, version, examples_json)
+ VALUES (%s, %s, %s, %s)
+ ON CONFLICT(name, version) DO UPDATE
+ SET examples_json = excluded.examples_json
+ """,
+ (
+ dataset.id,
+ dataset.name,
+ dataset.version,
+ Jsonb(_dataset_json(dataset)),
+ ),
+ )
+ return dataset
+
+ def get_dataset(self, dataset_id: UUID) -> Dataset:
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ "SELECT * FROM evaluation_datasets WHERE id = %s", (dataset_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(dataset_id))
+ return _dataset(row)
+
+ def save_experiment(self, experiment: Experiment) -> Experiment:
+ from psycopg.types.json import Jsonb
+
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO evaluation_experiments(
+ id, dataset_id, revision_id, results_json
+ ) VALUES (%s, %s, %s, %s)
+ """,
+ (
+ experiment.id,
+ experiment.dataset_id,
+ experiment.revision_id,
+ Jsonb(_results_json(experiment)),
+ ),
+ )
+ return experiment
+
+ def get_experiment(self, experiment_id: UUID) -> Experiment:
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ "SELECT * FROM evaluation_experiments WHERE id = %s",
+ (experiment_id,),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(experiment_id))
+ return _experiment(row)
diff --git a/src/rath/events.py b/src/rath/events.py
new file mode 100644
index 0000000..87d175b
--- /dev/null
+++ b/src/rath/events.py
@@ -0,0 +1,147 @@
+"""Immutable session event and lineage-friendly event-log contracts."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from enum import Enum
+from uuid import UUID, uuid4
+
+from rath._json import JSONValue, freeze_mapping
+from rath.context import TraceContext
+from rath.security import Provenance, TrustLevel
+
+__all__ = [
+ "Event",
+ "EventKind",
+ "ProducerRef",
+ "SessionEventLog",
+]
+
+
+class EventKind(str, Enum):
+ MESSAGE_CREATED = "session.message.created"
+ SESSION_FORKED = "session.forked"
+ SESSION_MERGED = "session.merged"
+ RUN_STATE_CHANGED = "run.state.changed"
+ NODE_STARTED = "run.node.started"
+ NODE_COMPLETED = "run.node.completed"
+ OUTPUT_DELTA = "run.output.delta"
+ INTERRUPT_CREATED = "run.interrupt.created"
+ TOOL_INVOCATION_CHANGED = "run.tool_invocation.changed"
+
+
+@dataclass(frozen=True, slots=True)
+class ProducerRef:
+ kind: str
+ id: str
+ revision_id: UUID | None = None
+
+ def __post_init__(self) -> None:
+ if not self.kind.strip():
+ raise ValueError("producer kind must not be empty")
+ if not self.id.strip():
+ raise ValueError("producer id must not be empty")
+
+
+@dataclass(frozen=True, slots=True)
+class Event:
+ """Deeply immutable event ordered within one Session."""
+
+ id: UUID
+ session_id: UUID
+ sequence: int
+ kind: EventKind
+ payload: Mapping[str, JSONValue]
+ producer: ProducerRef
+ trust: TrustLevel
+ provenance: Provenance
+ created_at: datetime
+ trace_context: TraceContext | None = None
+ schema_version: int = 1
+
+ def __post_init__(self) -> None:
+ if self.sequence < 1:
+ raise ValueError("event sequence must be greater than zero")
+ if self.schema_version < 1:
+ raise ValueError("event schema_version must be greater than zero")
+ if self.created_at.tzinfo is None:
+ raise ValueError("event created_at must be timezone-aware")
+ object.__setattr__(
+ self,
+ "payload",
+ freeze_mapping(self.payload, field="event.payload"),
+ )
+
+ @classmethod
+ def create(
+ cls,
+ *,
+ session_id: UUID,
+ sequence: int,
+ kind: EventKind,
+ payload: Mapping[str, object],
+ producer: ProducerRef,
+ trust: TrustLevel,
+ provenance: Provenance,
+ trace_context: TraceContext | None = None,
+ ) -> "Event":
+ return cls(
+ id=uuid4(),
+ session_id=session_id,
+ sequence=sequence,
+ kind=kind,
+ payload=freeze_mapping(payload, field="event.payload"),
+ producer=producer,
+ trust=trust,
+ provenance=provenance,
+ created_at=datetime.now(timezone.utc),
+ trace_context=trace_context,
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class SessionEventLog:
+ """Immutable ordered Event view; live runtime state is intentionally absent."""
+
+ id: UUID = field(default_factory=uuid4)
+ events: tuple[Event, ...] = ()
+ parent_session_ids: tuple[UUID, ...] = ()
+
+ def __post_init__(self) -> None:
+ expected = 1
+ for event in self.events:
+ if event.session_id != self.id:
+ raise ValueError("event session_id does not match event log id")
+ if event.sequence != expected:
+ raise ValueError("event sequence must be contiguous and start at 1")
+ expected += 1
+ if self.id in self.parent_session_ids:
+ raise ValueError("session cannot be its own lineage parent")
+
+ def append(
+ self,
+ *,
+ kind: EventKind,
+ payload: Mapping[str, object],
+ producer: ProducerRef,
+ trust: TrustLevel,
+ provenance: Provenance,
+ trace_context: TraceContext | None = None,
+ ) -> "SessionEventLog":
+ event = Event.create(
+ session_id=self.id,
+ sequence=len(self.events) + 1,
+ kind=kind,
+ payload=payload,
+ producer=producer,
+ trust=trust,
+ provenance=provenance,
+ trace_context=trace_context,
+ )
+ return SessionEventLog(
+ id=self.id,
+ events=(*self.events, event),
+ parent_session_ids=self.parent_session_ids,
+ )
diff --git a/src/rath/flow/__init__.py b/src/rath/flow/__init__.py
index 09506c5..042f3ab 100644
--- a/src/rath/flow/__init__.py
+++ b/src/rath/flow/__init__.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from rath.definition import EffectClass, RetryPolicy, router, step
from rath.flow.agent import Agent
from rath.flow.agent_param import AgentParam, Provider
from rath.flow.compile import CompiledWorkflow, ResourceManifest
@@ -20,4 +21,8 @@
"Selector",
"CompiledWorkflow",
"ResourceManifest",
+ "EffectClass",
+ "RetryPolicy",
+ "router",
+ "step",
]
diff --git a/src/rath/flow/compile.py b/src/rath/flow/compile.py
index bf688a9..07bf9b5 100644
--- a/src/rath/flow/compile.py
+++ b/src/rath/flow/compile.py
@@ -17,6 +17,7 @@
from collections.abc import Iterator
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
+from uuid import NAMESPACE_URL, uuid5
if TYPE_CHECKING:
from rath.flow.agent_param import AgentParam
@@ -128,11 +129,21 @@ class CompiledWorkflow:
static module tree (P5.1) to build the manifest.
"""
- __slots__ = ("workflow", "manifest", "_acquired")
+ __slots__ = ("workflow", "manifest", "execution_plan", "_acquired")
def __init__(self, workflow: "Workflow") -> None:
+ from rath.definition import WorkflowCompiler
+
self.workflow = workflow
self.manifest = collect_manifest(workflow)
+ revision_id = uuid5(
+ NAMESPACE_URL,
+ f"openrath:embedded-revision:{type(workflow).__module__}.{type(workflow).__qualname__}",
+ )
+ self.execution_plan = WorkflowCompiler().compile(
+ workflow,
+ revision_id=revision_id,
+ )
self._acquired: list[MemoryStore] = [] # stores acquired by __enter__
def __call__(self, session): # type: ignore[no-untyped-def]
diff --git a/src/rath/flow/memory_inject.py b/src/rath/flow/memory_inject.py
index 291cc19..4717b23 100644
--- a/src/rath/flow/memory_inject.py
+++ b/src/rath/flow/memory_inject.py
@@ -3,8 +3,7 @@
A policy reads a :class:`~rath.session.session.Session` and a
:class:`~rath.memory.abc.MemoryStore`, then returns a tuple of
:class:`~rath.session.chunk.ChunkRow` to prepend to the next loop turn
-(typically :attr:`ChunkKind.SYSTEM` notes that summarize relevant
-recalled memories).
+as untrusted user-context notes that summarize relevant recalled memories.
The injection step must NEVER raise into the session loop — on store
errors or a closed store, return an empty tuple and log a warning so
@@ -101,5 +100,6 @@ def _last_user_message(session: Session) -> str | None:
def _hit_to_chunk(hit: MemoryHit) -> ChunkRow:
snippet = (hit.snippet or "").strip()
- body = f"[memory:{hit.uri}] {snippet}" if snippet else f"[memory:{hit.uri}]"
- return ChunkRow(kind=ChunkKind.SYSTEM, payload={"content": body})
+ prefix = f"[untrusted memory:{hit.uri}]"
+ body = f"{prefix} {snippet}" if snippet else prefix
+ return ChunkRow(kind=ChunkKind.USER, payload={"content": body})
diff --git a/src/rath/flow/workflow.py b/src/rath/flow/workflow.py
index b54d50f..4c0df16 100644
--- a/src/rath/flow/workflow.py
+++ b/src/rath/flow/workflow.py
@@ -2,7 +2,11 @@
from __future__ import annotations
-from typing import Any
+from typing import TYPE_CHECKING, Any
+from uuid import UUID
+
+if TYPE_CHECKING:
+ from rath.definition import ExecutionPlan
from rath.flow.agent_param import AgentParam
from rath.llm.provider import Provider
@@ -103,6 +107,22 @@ def compile(self) -> "object":
return CompiledWorkflow(self)
+ def compile_plan(
+ self,
+ *,
+ revision_id: UUID,
+ ) -> "ExecutionPlan":
+ """Compile explicit ``@step`` boundaries into an immutable v2 plan."""
+ from rath.definition import WorkflowCompiler
+
+ return WorkflowCompiler().compile(self, revision_id=revision_id)
+
+ def inspect_resources(self) -> "object":
+ """Return the v1 static resource inventory without compiling a v2 plan."""
+ from rath.flow.compile import collect_manifest
+
+ return collect_manifest(self)
+
def forward(self, session: Session) -> Session:
"""Subclasses orchestrate Sessions (blocking)."""
diff --git a/src/rath/memory/adapters/local.py b/src/rath/memory/adapters/local.py
index c76602c..19d3014 100644
--- a/src/rath/memory/adapters/local.py
+++ b/src/rath/memory/adapters/local.py
@@ -13,10 +13,12 @@
from __future__ import annotations
import hashlib
+import ipaddress
import json
import logging
import math
import re
+import socket
import urllib.error
import urllib.parse
import urllib.request
@@ -77,6 +79,8 @@
_VEC_SUFFIX = ".vec"
_META_SUFFIX = ".meta.json"
_HIDDEN_SUFFIXES: frozenset[str] = frozenset({_VEC_SUFFIX, _META_SUFFIX})
+_DEFAULT_RESOURCE_MAX_BYTES = 10 * 1024 * 1024
+_SAFE_SEGMENT_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")
_CAPABILITIES = MemoryCapabilities(
@@ -119,6 +123,14 @@ class _LocalHandle:
chat_init_failed: bool = field(default=False)
+@dataclass(frozen=True, slots=True)
+class _ResourcePolicy:
+ local_roots: tuple[Path, ...]
+ allowed_http_hosts: frozenset[str]
+ allow_private_hosts: bool
+ max_bytes: int
+
+
@register("local")
class LocalMemoryBackend(MemoryBackend):
"""Filesystem-backed memory backend, default for ``pip install openrath``."""
@@ -307,13 +319,22 @@ def _dispatch_resource(
if isinstance(target_path, MemoryExecutionFailure):
return target_path
+ policy = _resource_policy(bound.options)
try:
- raw_bytes, original_name, source_label = _fetch_resource(op.source)
+ raw_bytes, original_name, source_label = _fetch_resource(
+ op.source,
+ policy=policy,
+ )
except FileNotFoundError as exc:
return MemoryExecutionFailure(
kind="not_found",
message=f"resource source not found: {exc}",
)
+ except _ResourceAccessDenied as exc:
+ return MemoryExecutionFailure(
+ kind="unauthorized",
+ message=f"resource source not allowed: {exc}",
+ )
except _ResourceFetchError as exc:
return MemoryExecutionFailure(
kind="transport",
@@ -363,15 +384,26 @@ def _dispatch_commit(
kind="invalid_uri",
message="MemoryOpCommit requires non-empty session_id",
)
+ session_id = _safe_storage_segment(op.session_id, field="session_id")
+ if isinstance(session_id, MemoryExecutionFailure):
+ return session_id
# Archive messages.json under session//commits//.
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%f")
- commit_root = bound.path / "session" / op.session_id / "commits" / stamp
+ commit_root = _contained_child(
+ bound.path,
+ "session",
+ session_id,
+ "commits",
+ stamp,
+ )
+ if isinstance(commit_root, MemoryExecutionFailure):
+ return commit_root
commit_root.mkdir(parents=True, exist_ok=True)
archive_path = commit_root / "messages.json"
normalized = [_normalize_message(m) for m in op.messages]
atomic_write_json(archive_path, normalized)
archived_uri = (
- f"{MEMORY_URI_PREFIX}session/{op.session_id}/commits/{stamp}/messages.json"
+ f"{MEMORY_URI_PREFIX}session/{session_id}/commits/{stamp}/messages.json"
)
if not op.wait:
@@ -979,11 +1011,63 @@ class _ResourceFetchError(Exception):
"""Wraps transport errors when fetching a remote resource."""
-def _fetch_resource(source: str) -> tuple[bytes, str, str]:
+class _ResourceAccessDenied(Exception):
+ """Raised when a resource source violates the configured policy."""
+
+
+class _NoRedirect(urllib.request.HTTPRedirectHandler):
+ """Reject redirects so each fetched URL is policy-checked directly."""
+
+ def redirect_request(self, *args: Any, **kwargs: Any) -> None: # noqa: D401
+ return None
+
+
+_NO_REDIRECT_OPENER = urllib.request.build_opener(_NoRedirect)
+
+
+def _resource_policy(options: dict[str, Any]) -> _ResourcePolicy:
+ roots = tuple(
+ Path(p).expanduser().resolve(strict=False)
+ for p in _option_strings(options.get("resource_import_roots"))
+ )
+ hosts = frozenset(
+ h.lower() for h in _option_strings(options.get("resource_allowed_http_hosts"))
+ )
+ raw_max = options.get("resource_max_bytes", _DEFAULT_RESOURCE_MAX_BYTES)
+ try:
+ max_bytes = int(raw_max)
+ except (TypeError, ValueError):
+ max_bytes = _DEFAULT_RESOURCE_MAX_BYTES
+ return _ResourcePolicy(
+ local_roots=roots,
+ allowed_http_hosts=hosts,
+ allow_private_hosts=bool(options.get("resource_allow_private_hosts", False)),
+ max_bytes=max(1, max_bytes),
+ )
+
+
+def _option_strings(raw: Any) -> tuple[str, ...]:
+ if raw is None:
+ return ()
+ if isinstance(raw, str):
+ return (raw,)
+ try:
+ return tuple(str(x) for x in raw)
+ except TypeError:
+ return (str(raw),)
+
+
+def _fetch_resource(
+ source: str,
+ *,
+ policy: _ResourcePolicy,
+) -> tuple[bytes, str, str]:
"""Resolve ``source`` to ``(bytes, original_name, source_label)``.
- ``source`` can be a local filesystem path, a ``file://`` URI, or an
- ``http(s)://`` URL. Anything else is treated as a local path.
+ Local paths and HTTP(S) URLs are disabled by default. Callers must opt in
+ with ``resource_import_roots`` or ``resource_allowed_http_hosts`` in the
+ store options so untrusted resource ingest cannot read host files or SSRF
+ internal services.
"""
parsed = urllib.parse.urlparse(source)
scheme = parsed.scheme.lower()
@@ -991,11 +1075,21 @@ def _fetch_resource(source: str) -> tuple[bytes, str, str]:
if len(scheme) == 1 and scheme.isalpha():
scheme = ""
if scheme in ("http", "https"):
+ _validate_resource_url(parsed, policy=policy)
try:
- with urllib.request.urlopen(source, timeout=30) as resp: # noqa: S310
- data = resp.read()
+ with _NO_REDIRECT_OPENER.open(source, timeout=30) as resp:
+ raw_len = resp.headers.get("Content-Length")
+ if raw_len is not None and int(raw_len) > policy.max_bytes:
+ raise _ResourceFetchError(
+ f"resource exceeds {policy.max_bytes} bytes",
+ )
+ data = resp.read(policy.max_bytes + 1)
except urllib.error.URLError as exc:
raise _ResourceFetchError(str(exc)) from exc
+ except ValueError as exc:
+ raise _ResourceFetchError(str(exc)) from exc
+ if len(data) > policy.max_bytes:
+ raise _ResourceFetchError(f"resource exceeds {policy.max_bytes} bytes")
name = Path(parsed.path).name or "resource"
return data, name, source
if scheme == "file":
@@ -1004,11 +1098,92 @@ def _fetch_resource(source: str) -> tuple[bytes, str, str]:
local = Path(source)
else:
raise _ResourceFetchError(f"unsupported scheme: {scheme!r}")
+ local = local.expanduser().resolve(strict=False)
+ _validate_local_resource_path(local, policy=policy)
if not local.is_file():
raise FileNotFoundError(str(local))
+ size = local.stat().st_size
+ if size > policy.max_bytes:
+ raise _ResourceFetchError(f"resource exceeds {policy.max_bytes} bytes")
return local.read_bytes(), local.name, str(local)
+def _validate_local_resource_path(local: Path, *, policy: _ResourcePolicy) -> None:
+ if not policy.local_roots:
+ raise _ResourceAccessDenied("local paths require resource_import_roots")
+ for root in policy.local_roots:
+ try:
+ local.relative_to(root)
+ except ValueError:
+ continue
+ return
+ raise _ResourceAccessDenied(f"{local} is outside resource_import_roots")
+
+
+def _validate_resource_url(
+ parsed: urllib.parse.ParseResult,
+ *,
+ policy: _ResourcePolicy,
+) -> None:
+ host = (parsed.hostname or "").lower()
+ if not host:
+ raise _ResourceAccessDenied("HTTP(S) resource URL requires a host")
+ if host not in policy.allowed_http_hosts:
+ raise _ResourceAccessDenied("HTTP(S) host is not allowed")
+ try:
+ infos = socket.getaddrinfo(
+ host,
+ parsed.port or (443 if parsed.scheme == "https" else 80),
+ type=socket.SOCK_STREAM,
+ )
+ except OSError as exc:
+ raise _ResourceFetchError(str(exc)) from exc
+ for info in infos:
+ address = info[4][0]
+ try:
+ ip = ipaddress.ip_address(address)
+ except ValueError as exc:
+ raise _ResourceAccessDenied(f"cannot validate address {address!r}") from exc
+ if _is_restricted_address(ip) and not policy.allow_private_hosts:
+ raise _ResourceAccessDenied("HTTP(S) host resolves to a private address")
+
+
+def _is_restricted_address(ip: ipaddress.IPv4Address | ipaddress.IPv6Address) -> bool:
+ return (
+ ip.is_loopback
+ or ip.is_private
+ or ip.is_link_local
+ or ip.is_multicast
+ or ip.is_reserved
+ or ip.is_unspecified
+ )
+
+
+def _safe_storage_segment(value: str, *, field: str) -> str | MemoryExecutionFailure:
+ text = str(value)
+ if not text or text in (".", "..") or not _SAFE_SEGMENT_RE.fullmatch(text):
+ return MemoryExecutionFailure(
+ kind="invalid_uri",
+ message=f"{field} must be a single safe path segment",
+ )
+ return text
+
+
+def _contained_child(
+ root: Path,
+ *parts: str,
+) -> Path | MemoryExecutionFailure:
+ try:
+ resolved = root.joinpath(*parts).resolve(strict=False)
+ resolved.relative_to(root.resolve(strict=False))
+ except (OSError, ValueError) as exc:
+ return MemoryExecutionFailure(
+ kind="invalid_uri",
+ message=f"path escapes store root: {exc}",
+ )
+ return resolved
+
+
def _walk_tree(
dir_path: Path,
uri_base: str,
diff --git a/src/rath/memory/adapters/openviking.py b/src/rath/memory/adapters/openviking.py
index b824ad5..7a9473c 100644
--- a/src/rath/memory/adapters/openviking.py
+++ b/src/rath/memory/adapters/openviking.py
@@ -94,7 +94,7 @@ class _OpenVikingHandle:
@register("openviking")
class OpenVikingBackend(MemoryBackend):
- """:class:`~rath.memory.MemoryBackend` backed by OpenViking 0.3.x."""
+ """:class:`~rath.memory.MemoryBackend` backed by OpenViking 0.4.11+."""
def __init__(self) -> None:
self._handles: dict[str, _OpenVikingHandle] = {}
@@ -357,20 +357,25 @@ def _dispatch_tree(client: Any, op: "MemoryOpTree") -> MemoryListResult:
def _hits_from_findresult(raw: Any) -> tuple[MemoryHit, ...]:
- """Walk an ``openviking.FindResult`` into typed :class:`MemoryHit` tuples.
+ """Normalize OpenViking retrieval results into typed :class:`MemoryHit` tuples.
- The SDK exposes two parallel lists — ``raw.memories`` and ``raw.resources``
- — each carrying ``MatchedContext`` objects with ``uri``, ``score``,
- ``abstract``, ``overview``, ``level`` (int 0/1/2).
+ Supports 0.4.11 HTTP mappings and embedded ``FindResult`` objects. Both
+ shapes group matched contexts under ``memories``, ``resources``, and
+ ``skills`` with ``uri``, ``score``, summary, and level fields.
"""
+
+ def value(item: Any, key: str, default: Any = None) -> Any:
+ if isinstance(item, Mapping):
+ return item.get(key, default)
+ return getattr(item, key, default)
+
matches: list[Any] = []
for attr in ("memories", "resources", "skills"):
- ms = getattr(raw, attr, None) or []
- matches.extend(ms)
- matches.sort(key=lambda m: getattr(m, "score", 0.0), reverse=True)
+ matches.extend(value(raw, attr, []) or [])
+ matches.sort(key=lambda item: float(value(item, "score", 0.0)), reverse=True)
hits: list[MemoryHit] = []
- for m in matches:
- level_raw = getattr(m, "level", None)
+ for match in matches:
+ level_raw = value(match, "level")
level: Any
if isinstance(level_raw, int):
level = _LEVEL_INT_TO_NAME.get(level_raw)
@@ -378,11 +383,11 @@ def _hits_from_findresult(raw: Any) -> tuple[MemoryHit, ...]:
level = level_raw if level_raw in _LEVEL_INT_TO_NAME.values() else None
else:
level = None
- snippet = getattr(m, "abstract", None) or getattr(m, "overview", None)
+ snippet = value(match, "abstract") or value(match, "overview")
hits.append(
MemoryHit(
- uri=to_public_uri(str(getattr(m, "uri", ""))),
- score=float(getattr(m, "score", 0.0)),
+ uri=to_public_uri(str(value(match, "uri", ""))),
+ score=float(value(match, "score", 0.0)),
snippet=snippet,
level=level,
)
diff --git a/src/rath/memory/persistence/paths.py b/src/rath/memory/persistence/paths.py
index 3545681..5ae2d2f 100644
--- a/src/rath/memory/persistence/paths.py
+++ b/src/rath/memory/persistence/paths.py
@@ -15,6 +15,7 @@
from uuid import UUID
from rath.config.paths import resolve_config_dir
+from rath.utils.ids import coerce_uuid_str
__all__ = [
"MEMORY_DIR_NAME",
@@ -41,7 +42,7 @@ def local_memory_root() -> Path:
def local_store_dir(store_id: UUID | str) -> Path:
"""``/`` — the per-store directory."""
- return local_memory_root() / str(store_id)
+ return local_memory_root() / coerce_uuid_str(store_id, field="store_id")
def ensure_local_memory_root() -> Path:
diff --git a/src/rath/observability/__init__.py b/src/rath/observability/__init__.py
new file mode 100644
index 0000000..6e0e93d
--- /dev/null
+++ b/src/rath/observability/__init__.py
@@ -0,0 +1,21 @@
+from rath.observability.core import (
+ GuardedTelemetry,
+ InMemoryTelemetry,
+ NoOpTelemetry,
+ SpanRecord,
+ Telemetry,
+)
+from rath.observability.logging import StructuredLogger
+from rath.observability.otel import OpenTelemetry
+from rath.observability.redaction import redact
+
+__all__ = [
+ "InMemoryTelemetry",
+ "GuardedTelemetry",
+ "NoOpTelemetry",
+ "OpenTelemetry",
+ "SpanRecord",
+ "StructuredLogger",
+ "Telemetry",
+ "redact",
+]
diff --git a/src/rath/observability/core.py b/src/rath/observability/core.py
new file mode 100644
index 0000000..78b0509
--- /dev/null
+++ b/src/rath/observability/core.py
@@ -0,0 +1,199 @@
+"""Dependency-light OpenTelemetry-compatible tracing and metric hooks."""
+
+from __future__ import annotations
+
+import threading
+import time
+from collections.abc import Iterator, Mapping
+from contextlib import contextmanager
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from typing import Protocol, runtime_checkable
+
+from rath._json import JSONValue, freeze_mapping
+from rath.context import TraceContext
+
+__all__ = [
+ "InMemoryTelemetry",
+ "NoOpTelemetry",
+ "GuardedTelemetry",
+ "SpanRecord",
+ "Telemetry",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class SpanRecord:
+ name: str
+ trace_id: str
+ span_id: str
+ parent_span_id: str | None
+ started_at: datetime
+ ended_at: datetime
+ duration_ms: float
+ status: str
+ attributes: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "attributes",
+ freeze_mapping(self.attributes, field="span.attributes"),
+ )
+
+
+@runtime_checkable
+class Telemetry(Protocol):
+ @contextmanager
+ def span(
+ self,
+ name: str,
+ *,
+ context: TraceContext,
+ attributes: Mapping[str, object] | None = None,
+ ) -> Iterator[None]: ...
+
+ def increment(
+ self,
+ name: str,
+ value: int = 1,
+ *,
+ attributes: Mapping[str, str] | None = None,
+ ) -> None: ...
+
+
+class NoOpTelemetry:
+ @contextmanager
+ def span(
+ self,
+ name: str,
+ *,
+ context: TraceContext,
+ attributes: Mapping[str, object] | None = None,
+ ) -> Iterator[None]:
+ yield
+
+ def increment(
+ self,
+ name: str,
+ value: int = 1,
+ *,
+ attributes: Mapping[str, str] | None = None,
+ ) -> None:
+ return None
+
+
+class InMemoryTelemetry:
+ """Reference exporter used by tests and embedded diagnostics."""
+
+ def __init__(self) -> None:
+ self._spans: list[SpanRecord] = []
+ self._counters: dict[tuple[str, tuple[tuple[str, str], ...]], int] = {}
+ self._lock = threading.Lock()
+
+ @property
+ def spans(self) -> tuple[SpanRecord, ...]:
+ with self._lock:
+ return tuple(self._spans)
+
+ @property
+ def counters(self) -> Mapping[tuple[str, tuple[tuple[str, str], ...]], int]:
+ with self._lock:
+ return dict(self._counters)
+
+ @contextmanager
+ def span(
+ self,
+ name: str,
+ *,
+ context: TraceContext,
+ attributes: Mapping[str, object] | None = None,
+ ) -> Iterator[None]:
+ started_at = datetime.now(timezone.utc)
+ started = time.perf_counter()
+ status = "ok"
+ try:
+ yield
+ except BaseException:
+ status = "error"
+ raise
+ finally:
+ ended_at = datetime.now(timezone.utc)
+ record = SpanRecord(
+ name=name,
+ trace_id=context.trace_id,
+ span_id=context.span_id,
+ parent_span_id=None,
+ started_at=started_at,
+ ended_at=ended_at,
+ duration_ms=(time.perf_counter() - started) * 1000.0,
+ status=status,
+ attributes=freeze_mapping(attributes, field="span.attributes"),
+ )
+ with self._lock:
+ self._spans.append(record)
+
+ def increment(
+ self,
+ name: str,
+ value: int = 1,
+ *,
+ attributes: Mapping[str, str] | None = None,
+ ) -> None:
+ labels = tuple(sorted((attributes or {}).items()))
+ with self._lock:
+ key = (name, labels)
+ self._counters[key] = self._counters.get(key, 0) + value
+
+
+class GuardedTelemetry:
+ """Failure-isolating wrapper: exporter faults never change application results."""
+
+ def __init__(self, delegate: Telemetry) -> None:
+ self.delegate = delegate
+
+ @contextmanager
+ def span(
+ self,
+ name: str,
+ *,
+ context: TraceContext,
+ attributes: Mapping[str, object] | None = None,
+ ) -> Iterator[None]:
+ manager = None
+ try:
+ manager = self.delegate.span(
+ name,
+ context=context,
+ attributes=attributes,
+ )
+ manager.__enter__()
+ except Exception:
+ manager = None
+ try:
+ yield
+ except BaseException as exc:
+ if manager is not None:
+ try:
+ manager.__exit__(type(exc), exc, exc.__traceback__)
+ except Exception:
+ pass
+ raise
+ else:
+ if manager is not None:
+ try:
+ manager.__exit__(None, None, None)
+ except Exception:
+ pass
+
+ def increment(
+ self,
+ name: str,
+ value: int = 1,
+ *,
+ attributes: Mapping[str, str] | None = None,
+ ) -> None:
+ try:
+ self.delegate.increment(name, value, attributes=attributes)
+ except Exception:
+ pass
diff --git a/src/rath/observability/logging.py b/src/rath/observability/logging.py
new file mode 100644
index 0000000..6c0052c
--- /dev/null
+++ b/src/rath/observability/logging.py
@@ -0,0 +1,54 @@
+"""Redacted newline-delimited JSON records for operational logging."""
+
+from __future__ import annotations
+
+import json
+import logging
+from collections.abc import Callable, Mapping
+from datetime import datetime, timezone
+
+from rath.context import TraceContext
+from rath.observability.redaction import redact
+
+__all__ = ["StructuredLogger"]
+
+
+class StructuredLogger:
+ """Emit stable JSON records without ever failing the application path."""
+
+ def __init__(self, sink: Callable[[str], None] | None = None) -> None:
+ self._sink = sink or logging.getLogger("openrath").info
+
+ def emit(
+ self,
+ event: str,
+ *,
+ context: TraceContext | None = None,
+ fields: Mapping[str, object] | None = None,
+ ) -> None:
+ record: dict[str, object] = {
+ "timestamp": datetime.now(timezone.utc).isoformat(),
+ "event": event,
+ }
+ if context is not None:
+ record.update(
+ {
+ "trace_id": context.trace_id,
+ "span_id": context.span_id,
+ }
+ )
+ safe = redact(dict(fields or {}))
+ assert isinstance(safe, dict)
+ record.update(safe)
+ try:
+ self._sink(
+ json.dumps(
+ record,
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ default=str,
+ )
+ )
+ except Exception:
+ return
diff --git a/src/rath/observability/otel.py b/src/rath/observability/otel.py
new file mode 100644
index 0000000..f84aa27
--- /dev/null
+++ b/src/rath/observability/otel.py
@@ -0,0 +1,84 @@
+"""OpenTelemetry SDK bridge with W3C trace correlation."""
+
+from __future__ import annotations
+
+from collections.abc import Iterator, Mapping
+from contextlib import contextmanager
+from typing import Any
+
+from rath.context import TraceContext
+from rath.observability.redaction import redact
+
+__all__ = ["OpenTelemetry"]
+
+
+class OpenTelemetry:
+ """Telemetry implementation backed by configured OpenTelemetry providers."""
+
+ def __init__(
+ self,
+ *,
+ service_name: str = "openrath",
+ tracer_provider: Any | None = None,
+ meter_provider: Any | None = None,
+ ) -> None:
+ try:
+ from opentelemetry import metrics, trace
+ except ImportError as exc:
+ raise RuntimeError(
+ "OpenTelemetry support requires `pip install openrath[otel]`"
+ ) from exc
+ self._trace = trace
+ self._tracer = trace.get_tracer(service_name, tracer_provider=tracer_provider)
+ self._meter = metrics.get_meter(service_name, meter_provider=meter_provider)
+ self._counters: dict[str, Any] = {}
+
+ @contextmanager
+ def span(
+ self,
+ name: str,
+ *,
+ context: TraceContext,
+ attributes: Mapping[str, object] | None = None,
+ ) -> Iterator[None]:
+ trace = self._trace
+ parent = trace.NonRecordingSpan(
+ trace.SpanContext(
+ trace_id=int(context.trace_id, 16),
+ span_id=int(context.span_id, 16),
+ is_remote=True,
+ trace_flags=trace.TraceFlags(
+ trace.TraceFlags.SAMPLED
+ if context.sampled
+ else trace.TraceFlags.DEFAULT
+ ),
+ trace_state=trace.TraceState(),
+ )
+ )
+ parent_context = trace.set_span_in_context(parent)
+ safe = redact(dict(attributes or {}))
+ assert isinstance(safe, dict)
+ scalar_attributes = {
+ key: value
+ for key, value in safe.items()
+ if isinstance(value, (bool, str, int, float))
+ }
+ with self._tracer.start_as_current_span(
+ name,
+ context=parent_context,
+ attributes=scalar_attributes,
+ ):
+ yield
+
+ def increment(
+ self,
+ name: str,
+ value: int = 1,
+ *,
+ attributes: Mapping[str, str] | None = None,
+ ) -> None:
+ counter = self._counters.get(name)
+ if counter is None:
+ counter = self._meter.create_counter(name)
+ self._counters[name] = counter
+ counter.add(value, attributes=dict(attributes or {}))
diff --git a/src/rath/observability/redaction.py b/src/rath/observability/redaction.py
new file mode 100644
index 0000000..1507f00
--- /dev/null
+++ b/src/rath/observability/redaction.py
@@ -0,0 +1,26 @@
+"""Recursive telemetry redaction with safe defaults."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+
+__all__ = ["redact"]
+
+_SENSITIVE = frozenset(
+ {"api_key", "authorization", "cookie", "password", "secret", "token"}
+)
+
+
+def redact(value: object) -> object:
+ if isinstance(value, Mapping):
+ return {
+ str(key): (
+ ""
+ if any(part in str(key).lower() for part in _SENSITIVE)
+ else redact(item)
+ )
+ for key, item in value.items()
+ }
+ if isinstance(value, (list, tuple)):
+ return [redact(item) for item in value]
+ return value
diff --git a/src/rath/runtime/__init__.py b/src/rath/runtime/__init__.py
new file mode 100644
index 0000000..a6137dd
--- /dev/null
+++ b/src/rath/runtime/__init__.py
@@ -0,0 +1,85 @@
+"""Public durable runtime state and persistence contracts."""
+
+from rath.runtime.effects import (
+ EffectLedger,
+ InvocationStatus,
+ PostgresEffectLedger,
+ Reconciliation,
+ SQLiteEffectLedger,
+ ToolInvocation,
+ arguments_digest,
+ reconcile_stale_effects,
+)
+from rath.runtime.execution import (
+ ExecutionServices,
+ PythonStepExecutor,
+ StepExecutor,
+ StepSuspended,
+)
+from rath.runtime.local import LocalRuntime, PlanMismatchError, StepContext
+from rath.runtime.models import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Checkpoint,
+ ClaimedRun,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ InvalidRunTransition,
+ ResourceLease,
+ Run,
+ RunEvent,
+ RunStatus,
+ assert_transition,
+)
+from rath.runtime.postgres import PostgresRunStore
+from rath.runtime.signals import (
+ GuardedSignalBus,
+ InMemorySignalBus,
+ RedisSignalBus,
+ RunSignal,
+ SignalBus,
+ SignalKind,
+)
+from rath.runtime.sqlite import SQLiteRunStore
+from rath.runtime.store import RunStore
+
+__all__ = [
+ "ApprovalDecision",
+ "ApprovalDecisionKind",
+ "assert_transition",
+ "Checkpoint",
+ "ClaimedRun",
+ "ConflictError",
+ "EffectLedger",
+ "ExecutionServices",
+ "Interrupt",
+ "InterruptKind",
+ "InvocationStatus",
+ "GuardedSignalBus",
+ "InMemorySignalBus",
+ "InvalidRunTransition",
+ "LocalRuntime",
+ "PlanMismatchError",
+ "PostgresRunStore",
+ "PythonStepExecutor",
+ "PostgresEffectLedger",
+ "Reconciliation",
+ "RedisSignalBus",
+ "Run",
+ "RunEvent",
+ "RunStatus",
+ "RunSignal",
+ "ResourceLease",
+ "RunStore",
+ "SQLiteRunStore",
+ "SignalBus",
+ "SignalKind",
+ "SQLiteEffectLedger",
+ "StepContext",
+ "StepExecutor",
+ "StepSuspended",
+ "ToolInvocation",
+ "arguments_digest",
+ "reconcile_stale_effects",
+]
diff --git a/src/rath/runtime/effects.py b/src/rath/runtime/effects.py
new file mode 100644
index 0000000..38b8aa8
--- /dev/null
+++ b/src/rath/runtime/effects.py
@@ -0,0 +1,679 @@
+"""Durable side-effect ledger and crash ambiguity reconciliation."""
+
+from __future__ import annotations
+
+import hashlib
+import json
+import sqlite3
+from collections.abc import Mapping
+from dataclasses import dataclass
+from datetime import datetime, timedelta, timezone
+from enum import Enum
+from typing import Any, Protocol, cast, runtime_checkable
+from uuid import UUID, uuid4
+
+from rath._json import JSONValue, freeze_json, thaw_json
+from rath.definition import EffectClass
+from rath.runtime.models import ConflictError, RunStatus
+from rath.runtime.store import RunStore
+
+__all__ = [
+ "EffectLedger",
+ "InvocationStatus",
+ "PostgresEffectLedger",
+ "Reconciliation",
+ "SQLiteEffectLedger",
+ "ToolInvocation",
+ "arguments_digest",
+ "reconcile_stale_effects",
+]
+
+
+class InvocationStatus(str, Enum):
+ PREPARED = "prepared"
+ DISPATCHED = "dispatched"
+ SUCCEEDED = "succeeded"
+ FAILED = "failed"
+ AMBIGUOUS = "ambiguous"
+
+
+@dataclass(frozen=True, slots=True)
+class ToolInvocation:
+ id: UUID
+ run_id: UUID
+ tool_name: str
+ effect_class: EffectClass
+ arguments_digest: str
+ status: InvocationStatus
+ created_at: datetime
+ updated_at: datetime
+ node_id: str | None = None
+ checkpoint_sequence: int | None = None
+ invocation_sequence: int | None = None
+ idempotency_key: str | None = None
+ result: JSONValue | None = None
+ error: str | None = None
+
+ def __post_init__(self) -> None:
+ if not self.tool_name:
+ raise ValueError("tool_name must not be empty")
+ if len(self.arguments_digest) != 64:
+ raise ValueError("arguments_digest must be a SHA-256 digest")
+ if self.created_at.tzinfo is None or self.updated_at.tzinfo is None:
+ raise ValueError("invocation timestamps must be timezone-aware")
+
+
+@dataclass(frozen=True, slots=True)
+class Reconciliation:
+ retryable: tuple[UUID, ...]
+ needs_review: tuple[UUID, ...]
+
+
+@runtime_checkable
+class EffectLedger(Protocol):
+ def prepare(
+ self,
+ *,
+ run_id: UUID,
+ tool_name: str,
+ effect_class: EffectClass,
+ arguments_digest: str,
+ idempotency_key: str | None,
+ node_id: str | None = None,
+ checkpoint_sequence: int | None = None,
+ ) -> ToolInvocation: ...
+
+ def get(self, invocation_id: UUID) -> ToolInvocation: ...
+
+ def mark_dispatched(self, invocation_id: UUID) -> ToolInvocation: ...
+
+ def complete(self, invocation_id: UUID, result: object) -> ToolInvocation: ...
+
+ def fail(self, invocation_id: UUID, error: str) -> ToolInvocation: ...
+
+ def reconcile_stale(
+ self, *, older_than: datetime
+ ) -> tuple[ToolInvocation, ...]: ...
+
+ def watermark(self, run_id: UUID) -> int: ...
+
+
+def arguments_digest(arguments: Mapping[str, object]) -> str:
+ frozen = freeze_json(arguments, field="tool arguments")
+ encoded = json.dumps(
+ thaw_json(frozen),
+ sort_keys=True,
+ ensure_ascii=False,
+ separators=(",", ":"),
+ ).encode()
+ return hashlib.sha256(encoded).hexdigest()
+
+
+def reconcile_stale_effects(
+ ledger: EffectLedger,
+ run_store: RunStore,
+ *,
+ grace_seconds: float = 30.0,
+ now: datetime | None = None,
+) -> Reconciliation:
+ """Classify dispatched work after a worker crash.
+
+ Idempotent calls may be retried under their stable key. Non-idempotent calls
+ are never replayed automatically and move their Run to NEEDS_REVIEW.
+ """
+
+ if grace_seconds < 0:
+ raise ValueError("grace_seconds must not be negative")
+ current = now or datetime.now(timezone.utc)
+ stale = ledger.reconcile_stale(
+ older_than=current - timedelta(seconds=grace_seconds)
+ )
+ retryable: list[UUID] = []
+ needs_review: list[UUID] = []
+ for invocation in stale:
+ if invocation.status is InvocationStatus.PREPARED:
+ retryable.append(invocation.id)
+ continue
+ needs_review.append(invocation.id)
+ run = run_store.get_run(invocation.run_id)
+ if run.status is RunStatus.RUNNING:
+ try:
+ run_store.transition_run(
+ run.id,
+ expected_version=run.version,
+ target=RunStatus.NEEDS_REVIEW,
+ )
+ except ConflictError:
+ pass
+ return Reconciliation(tuple(retryable), tuple(needs_review))
+
+
+class SQLiteEffectLedger:
+ """Effect ledger sharing the embedded runtime SQLite database."""
+
+ def __init__(self, path: str) -> None:
+ self.path = path
+
+ def _connect(self) -> sqlite3.Connection:
+ connection = sqlite3.connect(self.path, isolation_level=None)
+ connection.row_factory = sqlite3.Row
+ connection.execute("PRAGMA foreign_keys = ON")
+ return connection
+
+ def prepare(
+ self,
+ *,
+ run_id: UUID,
+ tool_name: str,
+ effect_class: EffectClass,
+ arguments_digest: str,
+ idempotency_key: str | None,
+ node_id: str | None = None,
+ checkpoint_sequence: int | None = None,
+ ) -> ToolInvocation:
+ now = datetime.now(timezone.utc)
+ connection = self._connect()
+ try:
+ connection.execute("BEGIN IMMEDIATE")
+ if idempotency_key is not None:
+ row = connection.execute(
+ """
+ SELECT * FROM tool_invocations
+ WHERE run_id = ? AND idempotency_key = ?
+ """,
+ (str(run_id), idempotency_key),
+ ).fetchone()
+ if row is not None:
+ existing = self._from_row(row)
+ if (
+ existing.arguments_digest != arguments_digest
+ or existing.tool_name != tool_name
+ ):
+ raise ConflictError(
+ "effect idempotency key was reused with different input"
+ )
+ connection.commit()
+ return existing
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(invocation_sequence), 0) AS value
+ FROM tool_invocations WHERE run_id = ?
+ """,
+ (str(run_id),),
+ ).fetchone()
+ invocation_sequence = int(row["value"]) + 1
+ invocation = ToolInvocation(
+ id=uuid4(),
+ run_id=run_id,
+ tool_name=tool_name,
+ effect_class=effect_class,
+ arguments_digest=arguments_digest,
+ idempotency_key=idempotency_key,
+ status=InvocationStatus.PREPARED,
+ created_at=now,
+ updated_at=now,
+ node_id=node_id,
+ checkpoint_sequence=checkpoint_sequence,
+ invocation_sequence=invocation_sequence,
+ )
+ connection.execute(
+ """
+ INSERT INTO tool_invocations(
+ id, run_id, tool_name, effect_class, idempotency_key,
+ arguments_digest, status, created_at, updated_at,
+ node_id, checkpoint_sequence, invocation_sequence
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(invocation.id),
+ str(run_id),
+ tool_name,
+ effect_class.value,
+ idempotency_key,
+ arguments_digest,
+ invocation.status.value,
+ now.isoformat(),
+ now.isoformat(),
+ node_id,
+ checkpoint_sequence,
+ invocation_sequence,
+ ),
+ )
+ connection.commit()
+ return invocation
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ def get(self, invocation_id: UUID) -> ToolInvocation:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ "SELECT * FROM tool_invocations WHERE id = ?",
+ (str(invocation_id),),
+ ).fetchone()
+ finally:
+ connection.close()
+ if row is None:
+ raise KeyError(str(invocation_id))
+ return self._from_row(row)
+
+ def mark_dispatched(self, invocation_id: UUID) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED,),
+ target=InvocationStatus.DISPATCHED,
+ )
+
+ def complete(self, invocation_id: UUID, result: object) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED, InvocationStatus.DISPATCHED),
+ target=InvocationStatus.SUCCEEDED,
+ result=result,
+ )
+
+ def fail(self, invocation_id: UUID, error: str) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED, InvocationStatus.DISPATCHED),
+ target=InvocationStatus.FAILED,
+ error=error,
+ )
+
+ def reconcile_stale(self, *, older_than: datetime) -> tuple[ToolInvocation, ...]:
+ connection = self._connect()
+ try:
+ connection.execute("BEGIN IMMEDIATE")
+ rows = connection.execute(
+ """
+ SELECT * FROM tool_invocations
+ WHERE status = ? AND updated_at <= ?
+ ORDER BY created_at, id
+ """,
+ (InvocationStatus.DISPATCHED.value, older_than.isoformat()),
+ ).fetchall()
+ output: list[ToolInvocation] = []
+ now = datetime.now(timezone.utc).isoformat()
+ for row in rows:
+ effect = EffectClass(row["effect_class"])
+ target = (
+ InvocationStatus.PREPARED
+ if effect in {EffectClass.NONE, EffectClass.READ_ONLY}
+ or (
+ effect is EffectClass.IDEMPOTENT
+ and row["idempotency_key"] is not None
+ )
+ else InvocationStatus.AMBIGUOUS
+ )
+ connection.execute(
+ """
+ UPDATE tool_invocations SET status = ?, updated_at = ?
+ WHERE id = ? AND status = ?
+ """,
+ (
+ target.value,
+ now,
+ row["id"],
+ InvocationStatus.DISPATCHED.value,
+ ),
+ )
+ updated = dict(row)
+ updated["status"] = target.value
+ updated["updated_at"] = now
+ output.append(self._from_row(updated))
+ connection.commit()
+ return tuple(output)
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ def watermark(self, run_id: UUID) -> int:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ """
+ SELECT COALESCE(
+ MAX(invocation_sequence),
+ COUNT(*)
+ ) AS value FROM tool_invocations
+ WHERE run_id = ? AND status = ?
+ """,
+ (str(run_id), InvocationStatus.SUCCEEDED.value),
+ ).fetchone()
+ finally:
+ connection.close()
+ return int(row["value"]) if row is not None else 0
+
+ def _transition(
+ self,
+ invocation_id: UUID,
+ *,
+ expected: tuple[InvocationStatus, ...],
+ target: InvocationStatus,
+ result: object | None = None,
+ error: str | None = None,
+ ) -> ToolInvocation:
+ connection = self._connect()
+ try:
+ connection.execute("BEGIN IMMEDIATE")
+ row = connection.execute(
+ "SELECT * FROM tool_invocations WHERE id = ?",
+ (str(invocation_id),),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(invocation_id))
+ if InvocationStatus(row["status"]) not in expected:
+ raise ConflictError("invalid effect invocation transition")
+ now = datetime.now(timezone.utc).isoformat()
+ result_json = (
+ json.dumps(
+ thaw_json(freeze_json(result, field="tool result")),
+ ensure_ascii=False,
+ sort_keys=True,
+ )
+ if result is not None
+ else None
+ )
+ connection.execute(
+ """
+ UPDATE tool_invocations SET status = ?, result_json = ?,
+ error = ?, updated_at = ? WHERE id = ?
+ """,
+ (target.value, result_json, error, now, str(invocation_id)),
+ )
+ connection.commit()
+ return self.get(invocation_id)
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ @staticmethod
+ def _from_row(row: Mapping[str, Any]) -> ToolInvocation:
+ result = row["result_json"]
+ return ToolInvocation(
+ id=UUID(row["id"]),
+ run_id=UUID(row["run_id"]),
+ tool_name=row["tool_name"],
+ effect_class=EffectClass(row["effect_class"]),
+ idempotency_key=row["idempotency_key"],
+ arguments_digest=row["arguments_digest"],
+ status=InvocationStatus(row["status"]),
+ result=json.loads(result) if isinstance(result, str) else result,
+ error=row["error"],
+ created_at=datetime.fromisoformat(row["created_at"]),
+ updated_at=datetime.fromisoformat(row["updated_at"]),
+ node_id=(row["node_id"] if "node_id" in row.keys() else None),
+ checkpoint_sequence=(
+ row["checkpoint_sequence"]
+ if "checkpoint_sequence" in row.keys()
+ else None
+ ),
+ invocation_sequence=(
+ row["invocation_sequence"]
+ if "invocation_sequence" in row.keys()
+ else None
+ ),
+ )
+
+
+class PostgresEffectLedger:
+ """Effect ledger sharing a production Postgres Run schema."""
+
+ def __init__(self, dsn: str, *, schema: str = "openrath") -> None:
+ self.dsn = dsn
+ self.schema = schema
+
+ def _connect(self) -> Any:
+ import psycopg
+ from psycopg import sql
+ from psycopg.rows import dict_row
+
+ connection = psycopg.connect(self.dsn, row_factory=dict_row)
+ connection.execute(
+ sql.SQL("SET search_path TO {}").format(sql.Identifier(self.schema))
+ )
+ return connection
+
+ def prepare(
+ self,
+ *,
+ run_id: UUID,
+ tool_name: str,
+ effect_class: EffectClass,
+ arguments_digest: str,
+ idempotency_key: str | None,
+ node_id: str | None = None,
+ checkpoint_sequence: int | None = None,
+ ) -> ToolInvocation:
+ now = datetime.now(timezone.utc)
+ invocation_id = uuid4()
+ connection = self._connect()
+ try:
+ connection.execute(
+ "SELECT id FROM runs WHERE id = %s FOR UPDATE",
+ (run_id,),
+ ).fetchone()
+ sequence_row = connection.execute(
+ """
+ SELECT COALESCE(MAX(invocation_sequence), 0) AS value
+ FROM tool_invocations WHERE run_id = %s
+ """,
+ (run_id,),
+ ).fetchone()
+ invocation_sequence = int(sequence_row["value"]) + 1
+ row = connection.execute(
+ """
+ INSERT INTO tool_invocations(
+ id, run_id, tool_name, effect_class, idempotency_key,
+ arguments_digest, status, created_at, updated_at,
+ node_id, checkpoint_sequence, invocation_sequence
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
+ ON CONFLICT (run_id, idempotency_key) DO NOTHING RETURNING *
+ """,
+ (
+ invocation_id,
+ run_id,
+ tool_name,
+ effect_class.value,
+ idempotency_key,
+ arguments_digest,
+ InvocationStatus.PREPARED.value,
+ now,
+ now,
+ node_id,
+ checkpoint_sequence,
+ invocation_sequence,
+ ),
+ ).fetchone()
+ if row is None:
+ row = connection.execute(
+ """
+ SELECT * FROM tool_invocations
+ WHERE run_id = %s AND idempotency_key = %s FOR UPDATE
+ """,
+ (run_id, idempotency_key),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("effect invocation already exists")
+ if (
+ row["arguments_digest"] != arguments_digest
+ or row["tool_name"] != tool_name
+ ):
+ raise ConflictError(
+ "effect idempotency key was reused with different input"
+ )
+ connection.commit()
+ return self._from_row(row)
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ def get(self, invocation_id: UUID) -> ToolInvocation:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ "SELECT * FROM tool_invocations WHERE id = %s", (invocation_id,)
+ ).fetchone()
+ connection.commit()
+ finally:
+ connection.close()
+ if row is None:
+ raise KeyError(str(invocation_id))
+ return self._from_row(row)
+
+ def mark_dispatched(self, invocation_id: UUID) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED,),
+ target=InvocationStatus.DISPATCHED,
+ )
+
+ def complete(self, invocation_id: UUID, result: object) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED, InvocationStatus.DISPATCHED),
+ target=InvocationStatus.SUCCEEDED,
+ result=result,
+ )
+
+ def fail(self, invocation_id: UUID, error: str) -> ToolInvocation:
+ return self._transition(
+ invocation_id,
+ expected=(InvocationStatus.PREPARED, InvocationStatus.DISPATCHED),
+ target=InvocationStatus.FAILED,
+ error=error,
+ )
+
+ def reconcile_stale(self, *, older_than: datetime) -> tuple[ToolInvocation, ...]:
+ connection = self._connect()
+ try:
+ rows = connection.execute(
+ """
+ SELECT * FROM tool_invocations
+ WHERE status = %s AND updated_at <= %s
+ ORDER BY created_at, id FOR UPDATE SKIP LOCKED
+ """,
+ (InvocationStatus.DISPATCHED.value, older_than),
+ ).fetchall()
+ output: list[ToolInvocation] = []
+ for row in rows:
+ effect = EffectClass(row["effect_class"])
+ target = (
+ InvocationStatus.PREPARED
+ if effect in {EffectClass.NONE, EffectClass.READ_ONLY}
+ or (
+ effect is EffectClass.IDEMPOTENT
+ and row["idempotency_key"] is not None
+ )
+ else InvocationStatus.AMBIGUOUS
+ )
+ updated = connection.execute(
+ """
+ UPDATE tool_invocations SET status = %s, updated_at = %s
+ WHERE id = %s AND status = %s RETURNING *
+ """,
+ (
+ target.value,
+ datetime.now(timezone.utc),
+ row["id"],
+ InvocationStatus.DISPATCHED.value,
+ ),
+ ).fetchone()
+ if updated is not None:
+ output.append(self._from_row(updated))
+ connection.commit()
+ return tuple(output)
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ def watermark(self, run_id: UUID) -> int:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ """
+ SELECT COALESCE(
+ MAX(invocation_sequence),
+ COUNT(*)
+ ) AS value FROM tool_invocations
+ WHERE run_id = %s AND status = %s
+ """,
+ (run_id, InvocationStatus.SUCCEEDED.value),
+ ).fetchone()
+ connection.commit()
+ finally:
+ connection.close()
+ return int(row["value"]) if row is not None else 0
+
+ def _transition(
+ self,
+ invocation_id: UUID,
+ *,
+ expected: tuple[InvocationStatus, ...],
+ target: InvocationStatus,
+ result: object | None = None,
+ error: str | None = None,
+ ) -> ToolInvocation:
+ from psycopg.types.json import Jsonb
+
+ result_value = (
+ thaw_json(freeze_json(result, field="tool result"))
+ if result is not None
+ else None
+ )
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ """
+ UPDATE tool_invocations SET status = %s, result_json = %s,
+ error = %s, updated_at = %s
+ WHERE id = %s AND status = ANY(%s) RETURNING *
+ """,
+ (
+ target.value,
+ Jsonb(result_value) if result_value is not None else None,
+ error,
+ datetime.now(timezone.utc),
+ invocation_id,
+ [item.value for item in expected],
+ ),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("invalid effect invocation transition")
+ connection.commit()
+ return self._from_row(row)
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ @staticmethod
+ def _from_row(row: Mapping[str, Any]) -> ToolInvocation:
+ return ToolInvocation(
+ id=row["id"],
+ run_id=row["run_id"],
+ tool_name=row["tool_name"],
+ effect_class=EffectClass(row["effect_class"]),
+ idempotency_key=row["idempotency_key"],
+ arguments_digest=row["arguments_digest"],
+ status=InvocationStatus(row["status"]),
+ result=cast(JSONValue | None, row["result_json"]),
+ error=row["error"],
+ created_at=row["created_at"],
+ updated_at=row["updated_at"],
+ node_id=row.get("node_id"),
+ checkpoint_sequence=row.get("checkpoint_sequence"),
+ invocation_sequence=row.get("invocation_sequence"),
+ )
diff --git a/src/rath/runtime/execution.py b/src/rath/runtime/execution.py
new file mode 100644
index 0000000..58f3f68
--- /dev/null
+++ b/src/rath/runtime/execution.py
@@ -0,0 +1,139 @@
+"""Single governed execution boundary used by durable runtime workers."""
+
+from __future__ import annotations
+
+import asyncio
+import inspect
+import time
+from concurrent.futures import TimeoutError as FutureTimeout
+from dataclasses import dataclass
+from typing import TYPE_CHECKING, Any, Coroutine, Protocol, cast
+
+from rath.definition import NodeKind, NodeSpec
+from rath.runtime.effects import EffectLedger
+from rath.runtime.models import Run
+from rath.runtime.store import RunStore
+
+if TYPE_CHECKING:
+ from rath.adapters import (
+ MemoryExecutor,
+ ProviderExecutor,
+ SandboxExecutor,
+ ToolExecutor,
+ )
+ from rath.runtime.local import StepContext
+ from rath.security import AuditSink, PolicyEngine
+
+__all__ = [
+ "ExecutionServices",
+ "PythonStepExecutor",
+ "StepSuspended",
+ "StepExecutor",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class ExecutionServices:
+ """Governed capabilities made available to a workflow step."""
+
+ policy: PolicyEngine
+ tools: ToolExecutor
+ providers: ProviderExecutor
+ sandboxes: SandboxExecutor
+ memory: MemoryExecutor
+ effects: EffectLedger
+ audit: AuditSink
+
+
+class StepExecutor(Protocol):
+ """Execute one compiled node through the durable worker boundary."""
+
+ def execute(
+ self,
+ *,
+ handler: object,
+ state: dict[str, object],
+ context: StepContext,
+ node: NodeSpec,
+ run: Run,
+ ) -> object: ...
+
+
+class StepSuspended(RuntimeError):
+ """Internal control flow indicating a durable interrupt boundary."""
+
+
+class PythonStepExecutor:
+ """Reference in-process executor for embedded and async durable steps."""
+
+ def __init__(self, store: RunStore) -> None:
+ self.store = store
+
+ def execute(
+ self,
+ *,
+ handler: object,
+ state: dict[str, object],
+ context: StepContext,
+ node: NodeSpec,
+ run: Run,
+ ) -> object:
+ last_error: BaseException | None = None
+ for attempt in range(1, node.retry.max_attempts + 1):
+ try:
+ callable_handler = cast(Any, handler)
+ if node.is_async:
+ value = (
+ callable_handler(state, context)
+ if node.kind is not NodeKind.ROUTER
+ else callable_handler(state)
+ )
+ if not inspect.isawaitable(value):
+ raise TypeError(
+ f"async step {node.id!r} did not return an awaitable"
+ )
+ from rath._async.runtime import runtime as async_runtime
+
+ coroutine = cast(Coroutine[Any, Any, object], value)
+ if node.timeout_seconds is not None:
+ coroutine = cast(
+ Coroutine[Any, Any, object],
+ asyncio.wait_for(coroutine, node.timeout_seconds),
+ )
+ return async_runtime().run(coroutine)
+
+ arguments = (
+ (state,) if node.kind is NodeKind.ROUTER else (state, context)
+ )
+ if node.timeout_seconds is None:
+ return callable_handler(*arguments)
+ started = time.monotonic()
+ result = callable_handler(*arguments)
+ if time.monotonic() - started > node.timeout_seconds:
+ raise FutureTimeout(
+ f"sync step {node.id!r} exceeded timeout; "
+ "the handler was allowed to stop before terminalization"
+ )
+ return result
+ except StepSuspended:
+ raise
+ except BaseException as exc:
+ last_error = exc
+ self.store.append_run_event(
+ run.id,
+ "run.step.attempt.failed",
+ {
+ "node_id": node.id,
+ "attempt": attempt,
+ "error_type": type(exc).__name__,
+ },
+ )
+ if attempt >= node.retry.max_attempts:
+ raise
+ delay = min(
+ node.retry.max_seconds,
+ node.retry.base_seconds * (2 ** (attempt - 1)),
+ )
+ time.sleep(delay)
+ assert last_error is not None
+ raise last_error
diff --git a/src/rath/runtime/local.py b/src/rath/runtime/local.py
new file mode 100644
index 0000000..224b66e
--- /dev/null
+++ b/src/rath/runtime/local.py
@@ -0,0 +1,560 @@
+"""Embedded durable executor for explicit Workflow step boundaries."""
+
+from __future__ import annotations
+
+import threading
+from asyncio import TimeoutError as AsyncTimeoutError
+from collections.abc import Callable, Mapping
+from concurrent.futures import TimeoutError as FutureTimeout
+from dataclasses import dataclass, field, replace
+from datetime import datetime
+from typing import cast
+from uuid import UUID
+
+from rath._json import JSONValue, freeze_mapping, thaw_json
+from rath.adapters.schema import validate_json
+from rath.context import DeadlineExceededError, RunContext, TraceContext
+from rath.definition import ExecutionPlan, NodeKind, WorkflowCompiler
+from rath.observability import (
+ GuardedTelemetry,
+ NoOpTelemetry,
+ StructuredLogger,
+ Telemetry,
+)
+from rath.runtime.effects import (
+ EffectLedger,
+ Reconciliation,
+ reconcile_stale_effects,
+)
+from rath.runtime.execution import (
+ ExecutionServices,
+ PythonStepExecutor,
+ StepExecutor,
+ StepSuspended,
+)
+from rath.runtime.models import (
+ TERMINAL_RUN_STATUSES,
+ ApprovalDecision,
+ Checkpoint,
+ ClaimedRun,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ Run,
+ RunStatus,
+)
+from rath.runtime.store import RunStore
+from rath.security import Principal, PrincipalKind, SecurityContext
+
+__all__ = ["LocalRuntime", "PlanMismatchError", "StepContext"]
+
+
+class PlanMismatchError(RuntimeError):
+ """A durable checkpoint does not belong to the registered executable plan."""
+
+
+@dataclass(frozen=True, slots=True)
+class StepContext:
+ run_id: UUID
+ request: RunContext
+ worker_id: str
+ fencing_token: int
+ policy_manifest: Mapping[str, JSONValue]
+ services: ExecutionServices | None
+ _interrupt_handler: Callable[
+ [InterruptKind, Mapping[str, object], float | None], ApprovalDecision
+ ] = field(repr=False)
+
+ def interrupt(
+ self,
+ kind: InterruptKind,
+ request: Mapping[str, object],
+ *,
+ timeout_seconds: float | None = None,
+ ) -> ApprovalDecision:
+ """Suspend durably on first call and return the decision after resume."""
+ return self._interrupt_handler(kind, request, timeout_seconds)
+
+
+@dataclass(frozen=True, slots=True)
+class _Registration:
+ workflow: object
+ plan: ExecutionPlan
+
+
+class LocalRuntime:
+ """Sync façade over the durable local worker engine."""
+
+ def __init__(
+ self,
+ store: RunStore,
+ *,
+ telemetry: Telemetry | None = None,
+ structured_logger: StructuredLogger | None = None,
+ effect_ledger: EffectLedger | None = None,
+ production_mode: bool = False,
+ execution_services: ExecutionServices | None = None,
+ step_executor: StepExecutor | None = None,
+ ) -> None:
+ self.store = store
+ self.telemetry = GuardedTelemetry(telemetry or NoOpTelemetry())
+ self.structured_logger = structured_logger or StructuredLogger()
+ if (
+ effect_ledger is not None
+ and execution_services is not None
+ and effect_ledger is not execution_services.effects
+ ):
+ raise ValueError(
+ "effect_ledger and execution_services.effects must be identical"
+ )
+ self.execution_services = execution_services
+ self.effect_ledger = (
+ effect_ledger
+ if effect_ledger is not None
+ else execution_services.effects
+ if execution_services is not None
+ else None
+ )
+ self.production_mode = production_mode
+ self.step_executor = step_executor or PythonStepExecutor(store)
+ self._registrations: dict[UUID, _Registration] = {}
+ self._contexts: dict[UUID, RunContext] = {}
+
+ def register(self, workflow: object, *, revision_id: UUID) -> ExecutionPlan:
+ plan = WorkflowCompiler().compile(
+ workflow,
+ revision_id=revision_id,
+ production_durable=self.production_mode,
+ input_schema=getattr(workflow, "input_schema", None),
+ state_schema=getattr(workflow, "state_schema", None),
+ policy_manifest=getattr(workflow, "policy_manifest", None),
+ )
+ if not plan.durable:
+ raise ValueError(
+ "durable runtime requires explicit @step boundaries; "
+ f"issues: {plan.compatibility_issues}"
+ )
+ self._registrations[plan.id] = _Registration(workflow=workflow, plan=plan)
+ return plan
+
+ def submit(
+ self,
+ workflow: object,
+ *,
+ session_id: UUID,
+ context: RunContext,
+ state: Mapping[str, object] | None = None,
+ idempotency_key: str | None = None,
+ priority: int = 0,
+ ) -> Run:
+ context.ensure_active()
+ plan = self.register(workflow, revision_id=context.revision_id)
+ input_state = state or {}
+ if plan.definition.input_schema:
+ validate_json(input_state, plan.definition.input_schema)
+ run = Run.create(
+ plan_id=plan.id,
+ revision_id=plan.revision_id,
+ session_id=session_id,
+ tenant_id=context.security.tenant_id,
+ state=state,
+ next_nodes=(plan.definition.entrypoint,),
+ idempotency_key=idempotency_key,
+ context={
+ "principal": {
+ "id": context.security.principal.id,
+ "kind": context.security.principal.kind.value,
+ "claims": context.security.principal.claims,
+ },
+ "project_id": context.security.project_id,
+ "grants": sorted(context.security.grants),
+ "attributes": context.security.attributes,
+ "request_id": str(context.request_id),
+ "trace_id": context.trace_context.trace_id,
+ "span_id": context.trace_context.span_id,
+ "sampled": context.trace_context.sampled,
+ "deadline": (
+ context.deadline.isoformat()
+ if context.deadline is not None
+ else None
+ ),
+ },
+ priority=priority,
+ )
+ created = self.store.create_run(run)
+ self._contexts[created.id] = context
+ self.structured_logger.emit(
+ "run.submitted",
+ context=context.trace_context,
+ fields={
+ "run_id": str(created.id),
+ "tenant_id": created.tenant_id,
+ "plan_id": str(created.plan_id),
+ "revision_id": str(created.revision_id),
+ "status": created.status.value,
+ },
+ )
+ return created
+
+ def work_once(
+ self,
+ *,
+ worker_id: str,
+ lease_seconds: float = 30.0,
+ max_steps: int | None = None,
+ now: datetime | None = None,
+ ) -> Run | None:
+ claim = self.store.claim_next(
+ worker_id=worker_id,
+ lease_seconds=lease_seconds,
+ now=now,
+ )
+ if claim is None:
+ return None
+ claim_context = self._contexts.get(claim.run.id)
+ self.structured_logger.emit(
+ "run.claimed",
+ context=(
+ claim_context.trace_context if claim_context is not None else None
+ ),
+ fields={
+ "run_id": str(claim.run.id),
+ "tenant_id": claim.run.tenant_id,
+ "worker_id": worker_id,
+ "fencing_token": claim.lease.fencing_token,
+ },
+ )
+ try:
+ stop_heartbeat = threading.Event()
+ heartbeat = threading.Thread(
+ target=self._heartbeat,
+ args=(claim, lease_seconds, stop_heartbeat),
+ daemon=True,
+ name=f"openrath-lease-{claim.run.id}",
+ )
+ heartbeat.start()
+ try:
+ result = self._execute_claim(claim, max_steps=max_steps)
+ self._forget_context_if_terminal(result)
+ return result
+ finally:
+ stop_heartbeat.set()
+ heartbeat.join(timeout=min(1.0, lease_seconds))
+ except StepSuspended:
+ waiting = self.store.get_run(claim.run.id)
+ self.structured_logger.emit(
+ "run.suspended",
+ context=(
+ claim_context.trace_context if claim_context is not None else None
+ ),
+ fields={
+ "run_id": str(waiting.id),
+ "tenant_id": waiting.tenant_id,
+ "status": waiting.status.value,
+ },
+ )
+ return waiting
+ except BaseException as exc:
+ current = self.store.get_run(claim.run.id)
+ if current.status in TERMINAL_RUN_STATUSES:
+ self._forget_context_if_terminal(current)
+ return current
+ target = (
+ RunStatus.TIMED_OUT
+ if isinstance(
+ exc,
+ (
+ AsyncTimeoutError,
+ DeadlineExceededError,
+ TimeoutError,
+ FutureTimeout,
+ ),
+ )
+ else RunStatus.FAILED
+ )
+ try:
+ failed = self.store.finish_claim(
+ claim.run.id,
+ worker_id=worker_id,
+ fencing_token=claim.lease.fencing_token,
+ expected_run_version=current.version,
+ target=target,
+ event_type="run.execution.failed",
+ event_data={
+ "error_type": type(exc).__name__,
+ "message": str(exc),
+ },
+ )
+ except ConflictError:
+ # Lease loss/fencing means this worker no longer owns the right
+ # to publish a terminal result. Recovery will reconcile effects
+ # and requeue the durable Run under a new fencing token.
+ return self.store.get_run(claim.run.id)
+ self.structured_logger.emit(
+ "run.failed",
+ context=(
+ claim_context.trace_context if claim_context is not None else None
+ ),
+ fields={
+ "run_id": str(failed.id),
+ "tenant_id": failed.tenant_id,
+ "status": failed.status.value,
+ "error_type": type(exc).__name__,
+ "error": str(exc),
+ },
+ )
+ self._forget_context_if_terminal(failed)
+ return failed
+
+ def _execute_claim(
+ self,
+ claim: ClaimedRun,
+ *,
+ max_steps: int | None,
+ ) -> Run:
+ registration = self._registrations.get(claim.run.plan_id)
+ if registration is None:
+ raise RuntimeError(f"execution plan {claim.run.plan_id} is not registered")
+ context = self._contexts.get(claim.run.id)
+ if context is None:
+ context = self._restore_context(claim.run)
+ run = claim.run
+ latest_checkpoint = self.store.latest_checkpoint(run.id)
+ if (
+ latest_checkpoint is not None
+ and latest_checkpoint.plan_hash != registration.plan.definition_hash
+ ):
+ raise PlanMismatchError(
+ "checkpoint plan hash does not match registered execution plan"
+ )
+ steps = 0
+ by_id = {node.id: node for node in registration.plan.nodes}
+ while run.next_nodes and (max_steps is None or steps < max_steps):
+ context.ensure_active()
+ durable = self.store.get_run(run.id)
+ if durable.status in TERMINAL_RUN_STATUSES:
+ return durable
+ if durable.version != run.version:
+ raise ConflictError("run changed while worker was executing")
+ node_id = run.next_nodes[0]
+ node = by_id[node_id]
+ state_value = thaw_json(run.state)
+ assert isinstance(state_value, dict)
+ handler = getattr(registration.workflow, node.id)
+ latest = self.store.latest_checkpoint(run.id)
+ checkpoint_sequence = 1 if latest is None else latest.sequence + 1
+
+ def request_interrupt(
+ kind: InterruptKind,
+ request: Mapping[str, object],
+ timeout_seconds: float | None,
+ ) -> ApprovalDecision:
+ for existing in self.store.list_interrupts(
+ tenant_id=run.tenant_id,
+ pending_only=False,
+ ):
+ if (
+ existing.run_id == run.id
+ and existing.request.get("_openrath_node_id") == node.id
+ and existing.request.get("_openrath_checkpoint_sequence")
+ == checkpoint_sequence
+ ):
+ if existing.decision is None:
+ raise StepSuspended("run is waiting for a decision")
+ return existing.decision
+ interrupt = Interrupt.create(
+ run_id=run.id,
+ kind=kind,
+ request={
+ **request,
+ "_openrath_node_id": node.id,
+ "_openrath_checkpoint_sequence": checkpoint_sequence,
+ },
+ timeout_seconds=timeout_seconds,
+ )
+ self.store.create_interrupt(
+ interrupt,
+ expected_run_version=run.version,
+ )
+ raise StepSuspended("run was suspended for a decision")
+
+ step_context = StepContext(
+ run_id=run.id,
+ request=context,
+ worker_id=claim.lease.holder_worker_id,
+ fencing_token=claim.lease.fencing_token,
+ policy_manifest=registration.plan.policy_manifest,
+ services=self.execution_services,
+ _interrupt_handler=request_interrupt,
+ )
+ with self.telemetry.span(
+ "openrath.node",
+ context=context.trace_context,
+ attributes={"run_id": str(run.id), "node_id": node.id},
+ ):
+ result = self.step_executor.execute(
+ handler=handler,
+ state=state_value,
+ context=step_context,
+ node=node,
+ run=run,
+ )
+
+ next_nodes: tuple[str, ...]
+ if node.kind is NodeKind.ROUTER:
+ if not isinstance(result, str) or result not in node.successors:
+ raise ValueError(
+ f"router {node.id!r} returned invalid successor {result!r}"
+ )
+ next_nodes = (result,)
+ next_state = state_value
+ else:
+ if result is None:
+ next_state = state_value
+ elif isinstance(result, Mapping):
+ next_state = dict(result)
+ else:
+ raise TypeError(f"step {node.id!r} must return a mapping or None")
+ if len(node.successors) > 1:
+ raise ValueError(
+ f"step {node.id!r} has multiple successors; use @router"
+ )
+ next_nodes = node.successors
+
+ if registration.plan.definition.state_schema:
+ validate_json(
+ next_state,
+ registration.plan.definition.state_schema,
+ )
+
+ if node.checkpoint or not next_nodes:
+ checkpoint = Checkpoint.create(
+ run_id=run.id,
+ sequence=checkpoint_sequence,
+ plan_hash=registration.plan.definition_hash,
+ state=next_state,
+ next_nodes=next_nodes,
+ effect_watermark=(
+ self.effect_ledger.watermark(run.id)
+ if self.effect_ledger is not None
+ else 0
+ ),
+ )
+ run = self.store.commit_checkpoint(
+ checkpoint,
+ worker_id=claim.lease.holder_worker_id,
+ fencing_token=claim.lease.fencing_token,
+ expected_run_version=run.version,
+ )
+ else:
+ run = replace(
+ run,
+ state=freeze_mapping(next_state, field="run.state"),
+ next_nodes=next_nodes,
+ )
+ steps += 1
+ self.telemetry.increment(
+ "openrath.node.completed",
+ attributes={"kind": node.kind.value},
+ )
+
+ if not run.next_nodes:
+ completed = self.store.finish_claim(
+ run.id,
+ worker_id=claim.lease.holder_worker_id,
+ fencing_token=claim.lease.fencing_token,
+ expected_run_version=run.version,
+ target=RunStatus.SUCCEEDED,
+ )
+ self.structured_logger.emit(
+ "run.completed",
+ context=context.trace_context,
+ fields={
+ "run_id": str(completed.id),
+ "tenant_id": completed.tenant_id,
+ "status": completed.status.value,
+ },
+ )
+ return completed
+ return run
+
+ def reconcile_effects(
+ self,
+ *,
+ grace_seconds: float = 30.0,
+ now: datetime | None = None,
+ ) -> Reconciliation:
+ if self.effect_ledger is None:
+ return Reconciliation((), ())
+ return reconcile_stale_effects(
+ self.effect_ledger,
+ self.store,
+ grace_seconds=grace_seconds,
+ now=now,
+ )
+
+ def _heartbeat(
+ self,
+ claim: ClaimedRun,
+ lease_seconds: float,
+ stopped: threading.Event,
+ ) -> None:
+ interval = max(0.1, lease_seconds / 3)
+ while not stopped.wait(interval):
+ try:
+ self.store.renew_lease(
+ claim.run.id,
+ worker_id=claim.lease.holder_worker_id,
+ fencing_token=claim.lease.fencing_token,
+ lease_seconds=lease_seconds,
+ )
+ except Exception:
+ return
+
+ def _forget_context_if_terminal(self, run: Run) -> None:
+ if run.status in TERMINAL_RUN_STATUSES:
+ self._contexts.pop(run.id, None)
+
+ @staticmethod
+ def _restore_context(run: Run) -> RunContext:
+ raw = thaw_json(run.context)
+ if not isinstance(raw, dict) or not raw:
+ return RunContext(
+ security=SecurityContext(
+ principal=Principal(
+ id="legacy-runtime-worker",
+ kind=PrincipalKind.SYSTEM,
+ claims={"context": "legacy-run"},
+ ),
+ tenant_id=run.tenant_id,
+ ),
+ revision_id=run.revision_id,
+ )
+ principal = raw["principal"]
+ assert isinstance(principal, dict)
+ deadline = raw.get("deadline")
+ return RunContext(
+ security=SecurityContext(
+ principal=Principal(
+ id=str(principal["id"]),
+ kind=PrincipalKind(str(principal["kind"])),
+ claims=cast(Mapping[str, JSONValue], principal.get("claims") or {}),
+ ),
+ tenant_id=run.tenant_id,
+ project_id=(
+ str(raw["project_id"])
+ if raw.get("project_id") is not None
+ else None
+ ),
+ grants=frozenset(str(item) for item in raw.get("grants", [])),
+ attributes=cast(Mapping[str, JSONValue], raw.get("attributes") or {}),
+ ),
+ revision_id=run.revision_id,
+ request_id=UUID(str(raw["request_id"])),
+ trace_context=TraceContext(
+ trace_id=str(raw["trace_id"]),
+ span_id=str(raw["span_id"]),
+ sampled=bool(raw.get("sampled", True)),
+ ),
+ deadline=datetime.fromisoformat(str(deadline)) if deadline else None,
+ )
diff --git a/src/rath/runtime/migrations/postgres/0001_initial.sql b/src/rath/runtime/migrations/postgres/0001_initial.sql
new file mode 100644
index 0000000..57f9b03
--- /dev/null
+++ b/src/rath/runtime/migrations/postgres/0001_initial.sql
@@ -0,0 +1,170 @@
+CREATE TABLE IF NOT EXISTS schema_migrations (
+ version INTEGER PRIMARY KEY,
+ applied_at TIMESTAMPTZ NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS runs (
+ id UUID PRIMARY KEY,
+ plan_id UUID NOT NULL,
+ revision_id UUID NOT NULL,
+ session_id UUID NOT NULL,
+ tenant_id TEXT NOT NULL,
+ status TEXT NOT NULL,
+ state_json JSONB NOT NULL,
+ next_nodes_json JSONB NOT NULL,
+ idempotency_key TEXT,
+ context_json JSONB NOT NULL DEFAULT '{}'::jsonb,
+ priority INTEGER NOT NULL DEFAULT 0,
+ request_fingerprint TEXT NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ updated_at TIMESTAMPTZ NOT NULL,
+ version BIGINT NOT NULL,
+ UNIQUE (tenant_id, idempotency_key)
+);
+
+CREATE INDEX IF NOT EXISTS runs_tenant_status_idx
+ ON runs (tenant_id, status, created_at);
+
+CREATE UNIQUE INDEX IF NOT EXISTS runs_one_active_per_session_idx
+ ON runs (session_id)
+ WHERE status IN ('queued', 'running', 'waiting', 'needs_review');
+
+CREATE TABLE IF NOT EXISTS run_events (
+ run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ sequence BIGINT NOT NULL,
+ type TEXT NOT NULL,
+ data_json JSONB NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ PRIMARY KEY (run_id, sequence)
+);
+
+CREATE TABLE IF NOT EXISTS checkpoints (
+ id UUID PRIMARY KEY,
+ run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ sequence BIGINT NOT NULL,
+ plan_hash TEXT NOT NULL,
+ state_json JSONB NOT NULL,
+ next_nodes_json JSONB NOT NULL,
+ pending_interrupts_json JSONB NOT NULL,
+ effect_watermark BIGINT NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ UNIQUE (run_id, sequence)
+);
+
+CREATE TABLE IF NOT EXISTS interrupts (
+ id UUID PRIMARY KEY,
+ run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ kind TEXT NOT NULL,
+ request_json JSONB NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ expires_at TIMESTAMPTZ,
+ decision_kind TEXT,
+ decision_actor_id TEXT,
+ decision_reason TEXT,
+ decision_payload_json JSONB,
+ decided_at TIMESTAMPTZ
+);
+
+CREATE INDEX IF NOT EXISTS interrupts_run_pending_idx
+ ON interrupts (run_id, decided_at);
+
+ALTER TABLE interrupts
+ ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ;
+
+CREATE INDEX IF NOT EXISTS interrupts_expiry_idx
+ ON interrupts (expires_at) WHERE decided_at IS NULL;
+
+CREATE TABLE IF NOT EXISTS run_leases (
+ id UUID PRIMARY KEY,
+ run_id UUID NOT NULL UNIQUE REFERENCES runs(id) ON DELETE CASCADE,
+ holder_worker_id TEXT NOT NULL,
+ expires_at TIMESTAMPTZ NOT NULL,
+ fencing_token BIGINT NOT NULL,
+ active BOOLEAN NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ updated_at TIMESTAMPTZ NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS run_leases_expiry_idx
+ ON run_leases (active, expires_at);
+
+CREATE TABLE IF NOT EXISTS tool_invocations (
+ id UUID PRIMARY KEY,
+ run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ tool_name TEXT NOT NULL,
+ effect_class TEXT NOT NULL,
+ idempotency_key TEXT,
+ arguments_digest TEXT NOT NULL,
+ status TEXT NOT NULL,
+ result_json JSONB,
+ error TEXT,
+ created_at TIMESTAMPTZ NOT NULL,
+ updated_at TIMESTAMPTZ NOT NULL,
+ UNIQUE (run_id, idempotency_key)
+);
+
+CREATE INDEX IF NOT EXISTS tool_invocations_reconcile_idx
+ ON tool_invocations (status, effect_class, updated_at);
+
+CREATE TABLE IF NOT EXISTS server_sessions (
+ id UUID PRIMARY KEY,
+ tenant_id TEXT NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS server_sessions_tenant_idx
+ ON server_sessions (tenant_id, created_at);
+
+CREATE TABLE IF NOT EXISTS server_assistants (
+ tenant_id TEXT NOT NULL,
+ id TEXT NOT NULL,
+ template_id TEXT NOT NULL,
+ revision_id UUID NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL,
+ PRIMARY KEY (tenant_id, id)
+);
+
+CREATE TABLE IF NOT EXISTS feedback (
+ id UUID PRIMARY KEY,
+ tenant_id TEXT NOT NULL,
+ run_id UUID NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ key TEXT NOT NULL,
+ score DOUBLE PRECISION,
+ value TEXT,
+ created_at TIMESTAMPTZ NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS feedback_run_idx ON feedback (run_id, created_at);
+
+ALTER TABLE runs
+ ADD COLUMN IF NOT EXISTS context_json JSONB NOT NULL DEFAULT '{}'::jsonb;
+
+ALTER TABLE runs
+ ADD COLUMN IF NOT EXISTS priority INTEGER NOT NULL DEFAULT 0;
+
+CREATE TABLE IF NOT EXISTS evaluation_datasets (
+ id UUID PRIMARY KEY,
+ name TEXT NOT NULL,
+ version TEXT NOT NULL,
+ examples_json JSONB NOT NULL,
+ UNIQUE (name, version)
+);
+
+CREATE TABLE IF NOT EXISTS evaluation_experiments (
+ id UUID PRIMARY KEY,
+ dataset_id UUID NOT NULL REFERENCES evaluation_datasets(id),
+ revision_id UUID NOT NULL,
+ results_json JSONB NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
+);
+
+CREATE INDEX IF NOT EXISTS evaluation_experiments_revision_idx
+ ON evaluation_experiments (revision_id, created_at);
+
+CREATE TABLE IF NOT EXISTS revisions (
+ id UUID PRIMARY KEY,
+ code_digest TEXT NOT NULL,
+ plan_hash TEXT NOT NULL,
+ manifest_json JSONB NOT NULL,
+ created_at TIMESTAMPTZ NOT NULL
+);
diff --git a/src/rath/runtime/migrations/postgres/0002_release_hardening.sql b/src/rath/runtime/migrations/postgres/0002_release_hardening.sql
new file mode 100644
index 0000000..67d7254
--- /dev/null
+++ b/src/rath/runtime/migrations/postgres/0002_release_hardening.sql
@@ -0,0 +1,26 @@
+ALTER TABLE schema_migrations
+ ADD COLUMN IF NOT EXISTS filename TEXT;
+ALTER TABLE schema_migrations
+ ADD COLUMN IF NOT EXISTS checksum TEXT;
+
+ALTER TABLE tool_invocations
+ ADD COLUMN IF NOT EXISTS node_id TEXT;
+ALTER TABLE tool_invocations
+ ADD COLUMN IF NOT EXISTS checkpoint_sequence BIGINT;
+ALTER TABLE tool_invocations
+ ADD COLUMN IF NOT EXISTS invocation_sequence BIGINT;
+
+CREATE UNIQUE INDEX IF NOT EXISTS tool_invocations_run_sequence_idx
+ ON tool_invocations (run_id, invocation_sequence)
+ WHERE invocation_sequence IS NOT NULL;
+
+CREATE INDEX IF NOT EXISTS run_events_created_idx
+ ON run_events (run_id, created_at, sequence);
+
+ALTER TABLE revisions
+ ADD COLUMN IF NOT EXISTS content_digest TEXT;
+UPDATE revisions
+ SET content_digest = code_digest || ':' || id::text
+ WHERE content_digest IS NULL;
+CREATE UNIQUE INDEX IF NOT EXISTS revisions_content_digest_idx
+ ON revisions (content_digest);
diff --git a/src/rath/runtime/models.py b/src/rath/runtime/models.py
new file mode 100644
index 0000000..498a1a7
--- /dev/null
+++ b/src/rath/runtime/models.py
@@ -0,0 +1,382 @@
+"""Durable Run, Checkpoint, Interrupt, and event state models."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from datetime import datetime, timedelta, timezone
+from enum import Enum
+from uuid import UUID, uuid4
+
+from rath._json import JSONValue, freeze_mapping
+from rath.errors import ErrorCode, RathError
+
+__all__ = [
+ "ApprovalDecision",
+ "ApprovalDecisionKind",
+ "Checkpoint",
+ "ConflictError",
+ "Interrupt",
+ "InterruptKind",
+ "InvalidRunTransition",
+ "Run",
+ "RunEvent",
+ "RunStatus",
+ "ClaimedRun",
+ "ResourceLease",
+ "assert_transition",
+]
+
+
+class RunStatus(str, Enum):
+ QUEUED = "queued"
+ RUNNING = "running"
+ WAITING = "waiting"
+ SUCCEEDED = "succeeded"
+ FAILED = "failed"
+ CANCELLED = "cancelled"
+ TIMED_OUT = "timed_out"
+ NEEDS_REVIEW = "needs_review"
+
+
+TERMINAL_RUN_STATUSES = frozenset(
+ {
+ RunStatus.SUCCEEDED,
+ RunStatus.FAILED,
+ RunStatus.CANCELLED,
+ RunStatus.TIMED_OUT,
+ }
+)
+
+_TRANSITIONS: Mapping[RunStatus, frozenset[RunStatus]] = {
+ RunStatus.QUEUED: frozenset(
+ {
+ RunStatus.RUNNING,
+ RunStatus.CANCELLED,
+ RunStatus.TIMED_OUT,
+ }
+ ),
+ RunStatus.RUNNING: frozenset(
+ {
+ RunStatus.QUEUED,
+ RunStatus.WAITING,
+ RunStatus.SUCCEEDED,
+ RunStatus.FAILED,
+ RunStatus.CANCELLED,
+ RunStatus.TIMED_OUT,
+ RunStatus.NEEDS_REVIEW,
+ }
+ ),
+ RunStatus.WAITING: frozenset(
+ {
+ RunStatus.QUEUED,
+ RunStatus.CANCELLED,
+ RunStatus.TIMED_OUT,
+ RunStatus.FAILED,
+ }
+ ),
+ RunStatus.NEEDS_REVIEW: frozenset(
+ {
+ RunStatus.QUEUED,
+ RunStatus.FAILED,
+ RunStatus.CANCELLED,
+ }
+ ),
+ RunStatus.SUCCEEDED: frozenset(),
+ RunStatus.FAILED: frozenset(),
+ RunStatus.CANCELLED: frozenset(),
+ RunStatus.TIMED_OUT: frozenset(),
+}
+
+
+class ConflictError(RathError):
+ def __init__(self, message: str, *, details: Mapping[str, object] | None = None):
+ super().__init__(
+ ErrorCode.CONFLICT,
+ message,
+ retryable=False,
+ details=details,
+ )
+
+
+class InvalidRunTransition(ConflictError):
+ def __init__(self, source: RunStatus, target: RunStatus) -> None:
+ super().__init__(
+ f"invalid run transition from {source.value!r} to {target.value!r}",
+ details={"source": source.value, "target": target.value},
+ )
+ self.source = source
+ self.target = target
+
+
+def assert_transition(source: RunStatus, target: RunStatus) -> None:
+ if target not in _TRANSITIONS[source]:
+ raise InvalidRunTransition(source, target)
+
+
+def _aware(value: datetime, *, field_name: str) -> None:
+ if value.tzinfo is None:
+ raise ValueError(f"{field_name} must be timezone-aware")
+
+
+@dataclass(frozen=True, slots=True)
+class Run:
+ id: UUID
+ plan_id: UUID
+ revision_id: UUID
+ session_id: UUID
+ tenant_id: str
+ status: RunStatus
+ state: Mapping[str, JSONValue]
+ next_nodes: tuple[str, ...]
+ created_at: datetime
+ updated_at: datetime
+ version: int = 0
+ idempotency_key: str | None = None
+ context: Mapping[str, JSONValue] = field(default_factory=dict)
+ priority: int = 0
+
+ def __post_init__(self) -> None:
+ if not self.tenant_id.strip():
+ raise ValueError("run tenant_id must not be empty")
+ if self.version < 0:
+ raise ValueError("run version must not be negative")
+ if not -100 <= self.priority <= 100:
+ raise ValueError("run priority must be between -100 and 100")
+ _aware(self.created_at, field_name="run.created_at")
+ _aware(self.updated_at, field_name="run.updated_at")
+ object.__setattr__(self, "state", freeze_mapping(self.state, field="run.state"))
+ object.__setattr__(
+ self, "context", freeze_mapping(self.context, field="run.context")
+ )
+ object.__setattr__(self, "next_nodes", tuple(self.next_nodes))
+
+ @classmethod
+ def create(
+ cls,
+ *,
+ plan_id: UUID,
+ revision_id: UUID,
+ session_id: UUID,
+ tenant_id: str,
+ status: RunStatus = RunStatus.QUEUED,
+ state: Mapping[str, object] | None = None,
+ next_nodes: tuple[str, ...] = (),
+ idempotency_key: str | None = None,
+ context: Mapping[str, object] | None = None,
+ priority: int = 0,
+ id: UUID | None = None,
+ ) -> "Run":
+ now = datetime.now(timezone.utc)
+ return cls(
+ id=id or uuid4(),
+ plan_id=plan_id,
+ revision_id=revision_id,
+ session_id=session_id,
+ tenant_id=tenant_id,
+ status=status,
+ state=freeze_mapping(state, field="run.state"),
+ next_nodes=next_nodes,
+ idempotency_key=idempotency_key,
+ context=freeze_mapping(context, field="run.context"),
+ priority=priority,
+ created_at=now,
+ updated_at=now,
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class RunEvent:
+ run_id: UUID
+ sequence: int
+ type: str
+ data: Mapping[str, JSONValue]
+ created_at: datetime
+
+ def __post_init__(self) -> None:
+ if self.sequence < 1:
+ raise ValueError("run event sequence must be greater than zero")
+ _aware(self.created_at, field_name="run_event.created_at")
+ object.__setattr__(
+ self,
+ "data",
+ freeze_mapping(self.data, field="run_event.data"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class Checkpoint:
+ id: UUID
+ run_id: UUID
+ sequence: int
+ plan_hash: str
+ state: Mapping[str, JSONValue]
+ next_nodes: tuple[str, ...]
+ pending_interrupts: tuple[UUID, ...]
+ effect_watermark: int
+ created_at: datetime
+
+ def __post_init__(self) -> None:
+ if self.sequence < 1:
+ raise ValueError("checkpoint sequence must be greater than zero")
+ if self.effect_watermark < 0:
+ raise ValueError("effect_watermark must not be negative")
+ if len(self.plan_hash) != 64:
+ raise ValueError("plan_hash must be a SHA-256 hexadecimal digest")
+ try:
+ int(self.plan_hash, 16)
+ except ValueError as exc:
+ raise ValueError("plan_hash must be hexadecimal") from exc
+ _aware(self.created_at, field_name="checkpoint.created_at")
+ object.__setattr__(
+ self,
+ "state",
+ freeze_mapping(self.state, field="checkpoint.state"),
+ )
+ object.__setattr__(self, "next_nodes", tuple(self.next_nodes))
+ object.__setattr__(
+ self,
+ "pending_interrupts",
+ tuple(self.pending_interrupts),
+ )
+
+ @classmethod
+ def create(
+ cls,
+ *,
+ run_id: UUID,
+ sequence: int,
+ plan_hash: str,
+ state: Mapping[str, object],
+ next_nodes: tuple[str, ...],
+ effect_watermark: int,
+ pending_interrupts: tuple[UUID, ...] = (),
+ ) -> "Checkpoint":
+ return cls(
+ id=uuid4(),
+ run_id=run_id,
+ sequence=sequence,
+ plan_hash=plan_hash,
+ state=freeze_mapping(state, field="checkpoint.state"),
+ next_nodes=next_nodes,
+ pending_interrupts=pending_interrupts,
+ effect_watermark=effect_watermark,
+ created_at=datetime.now(timezone.utc),
+ )
+
+
+class InterruptKind(str, Enum):
+ APPROVAL = "approval"
+ INPUT = "input"
+ REVIEW = "review"
+
+
+class ApprovalDecisionKind(str, Enum):
+ APPROVE = "approve"
+ EDIT = "edit"
+ REJECT = "reject"
+ RESPOND = "respond"
+
+
+@dataclass(frozen=True, slots=True)
+class ApprovalDecision:
+ kind: ApprovalDecisionKind
+ actor_id: str
+ reason: str
+ payload: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ if not self.actor_id.strip():
+ raise ValueError("decision actor_id must not be empty")
+ if not self.reason.strip():
+ raise ValueError("decision reason must not be empty")
+ object.__setattr__(
+ self,
+ "payload",
+ freeze_mapping(self.payload, field="decision.payload"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class Interrupt:
+ id: UUID
+ run_id: UUID
+ kind: InterruptKind
+ request: Mapping[str, JSONValue]
+ created_at: datetime
+ expires_at: datetime | None = None
+ decision: ApprovalDecision | None = None
+ decided_at: datetime | None = None
+
+ def __post_init__(self) -> None:
+ _aware(self.created_at, field_name="interrupt.created_at")
+ if self.expires_at is not None:
+ _aware(self.expires_at, field_name="interrupt.expires_at")
+ if self.expires_at <= self.created_at:
+ raise ValueError("interrupt expires_at must be after created_at")
+ if self.decided_at is not None:
+ _aware(self.decided_at, field_name="interrupt.decided_at")
+ if (self.decision is None) != (self.decided_at is None):
+ raise ValueError("decision and decided_at must be set together")
+ object.__setattr__(
+ self,
+ "request",
+ freeze_mapping(self.request, field="interrupt.request"),
+ )
+
+ @classmethod
+ def create(
+ cls,
+ *,
+ run_id: UUID,
+ kind: InterruptKind,
+ request: Mapping[str, object],
+ timeout_seconds: float | None = None,
+ ) -> "Interrupt":
+ if timeout_seconds is not None and timeout_seconds <= 0:
+ raise ValueError("interrupt timeout_seconds must be positive")
+ created_at = datetime.now(timezone.utc)
+ return cls(
+ id=uuid4(),
+ run_id=run_id,
+ kind=kind,
+ request=freeze_mapping(request, field="interrupt.request"),
+ created_at=created_at,
+ expires_at=(
+ created_at + timedelta(seconds=timeout_seconds)
+ if timeout_seconds is not None
+ else None
+ ),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class ResourceLease:
+ id: UUID
+ resource_type: str
+ resource_id: str
+ owner_run_id: UUID
+ holder_worker_id: str
+ expires_at: datetime
+ fencing_token: int
+ created_at: datetime
+ updated_at: datetime
+
+ def __post_init__(self) -> None:
+ if not self.resource_type.strip():
+ raise ValueError("lease resource_type must not be empty")
+ if not self.resource_id.strip():
+ raise ValueError("lease resource_id must not be empty")
+ if not self.holder_worker_id.strip():
+ raise ValueError("lease holder_worker_id must not be empty")
+ if self.fencing_token < 1:
+ raise ValueError("lease fencing_token must be positive")
+ _aware(self.expires_at, field_name="lease.expires_at")
+ _aware(self.created_at, field_name="lease.created_at")
+ _aware(self.updated_at, field_name="lease.updated_at")
+
+
+@dataclass(frozen=True, slots=True)
+class ClaimedRun:
+ run: Run
+ lease: ResourceLease
diff --git a/src/rath/runtime/postgres.py b/src/rath/runtime/postgres.py
new file mode 100644
index 0000000..9692017
--- /dev/null
+++ b/src/rath/runtime/postgres.py
@@ -0,0 +1,1227 @@
+"""PostgreSQL source-of-truth Run store for multi-worker production mode."""
+
+from __future__ import annotations
+
+import hashlib
+import re
+from collections.abc import Iterator, Mapping
+from contextlib import contextmanager
+from datetime import datetime, timedelta, timezone
+from importlib.resources import files
+from typing import Any, cast
+from uuid import UUID
+
+from rath._json import freeze_json, thaw_json
+from rath.runtime.models import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Checkpoint,
+ ClaimedRun,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ ResourceLease,
+ Run,
+ RunEvent,
+ RunStatus,
+ assert_transition,
+)
+
+__all__ = ["PostgresRunStore"]
+
+_SCHEMA_NAME = re.compile(r"^[a-z_][a-z0-9_]{0,62}$")
+
+
+def _now() -> datetime:
+ return datetime.now(timezone.utc)
+
+
+def _json(value: object) -> object:
+ from psycopg.types.json import Jsonb
+
+ return Jsonb(thaw_json(freeze_json(value, field="persistence value")))
+
+
+class PostgresRunStore:
+ """Transactional Postgres store using row locks and fencing tokens."""
+
+ def __init__(
+ self,
+ dsn: str,
+ *,
+ schema: str = "openrath",
+ auto_migrate: bool = False,
+ pool_max_size: int = 20,
+ ) -> None:
+ if not dsn.strip():
+ raise ValueError("dsn must not be empty")
+ if not _SCHEMA_NAME.fullmatch(schema):
+ raise ValueError("schema must be a safe lowercase PostgreSQL identifier")
+ self.dsn = dsn
+ self.schema = schema
+ self._closed = False
+ if pool_max_size < 1:
+ raise ValueError("pool_max_size must be positive")
+ if auto_migrate:
+ self.migrate(dsn, schema=schema)
+ try:
+ from psycopg import sql
+ from psycopg.rows import dict_row
+ from psycopg_pool import ConnectionPool
+ except ImportError as exc:
+ raise RuntimeError(
+ "Postgres support requires `pip install openrath[postgres]`"
+ ) from exc
+ self._sql = sql
+ self._pool = ConnectionPool(
+ self.dsn,
+ min_size=1,
+ max_size=pool_max_size,
+ timeout=10,
+ kwargs={"row_factory": dict_row},
+ configure=self._configure_connection,
+ open=True,
+ )
+
+ def _configure_connection(self, connection: Any) -> None:
+ connection.execute(
+ self._sql.SQL("SET search_path TO {}").format(
+ self._sql.Identifier(self.schema)
+ )
+ )
+ connection.commit()
+
+ @staticmethod
+ def _migrations() -> tuple[tuple[int, str, str, str], ...]:
+ root = files("rath.runtime").joinpath("migrations/postgres")
+ output: list[tuple[int, str, str, str]] = []
+ for item in root.iterdir():
+ match = re.fullmatch(r"(\d{4})_[a-z0-9_]+\.sql", item.name)
+ if match is None:
+ continue
+ migration = item.read_text(encoding="utf-8")
+ output.append(
+ (
+ int(match.group(1)),
+ item.name,
+ migration,
+ hashlib.sha256(migration.encode("utf-8")).hexdigest(),
+ )
+ )
+ output.sort(key=lambda item: item[0])
+ expected = list(range(1, len(output) + 1))
+ if [item[0] for item in output] != expected:
+ raise RuntimeError("PostgreSQL migrations must be contiguous from 0001")
+ return tuple(output)
+
+ @classmethod
+ def migrate(cls, dsn: str, *, schema: str = "openrath") -> None:
+ if not dsn.strip():
+ raise ValueError("dsn must not be empty")
+ if not _SCHEMA_NAME.fullmatch(schema):
+ raise ValueError("schema must be a safe lowercase PostgreSQL identifier")
+ try:
+ import psycopg
+ from psycopg import sql
+ except ImportError as exc:
+ raise RuntimeError(
+ "Postgres support requires `pip install openrath[postgres]`"
+ ) from exc
+ migrations = cls._migrations()
+ with psycopg.connect(dsn) as connection:
+ connection.execute(
+ sql.SQL("CREATE SCHEMA IF NOT EXISTS {}").format(sql.Identifier(schema))
+ )
+ connection.execute(
+ sql.SQL("SET search_path TO {}").format(sql.Identifier(schema))
+ )
+ table_row = connection.execute(
+ "SELECT to_regclass('schema_migrations')"
+ ).fetchone()
+ table_exists = table_row[0] if table_row is not None else None
+ for migration_version, filename, migration, checksum in migrations:
+ existing = (
+ connection.execute(
+ "SELECT version FROM schema_migrations WHERE version = %s",
+ (migration_version,),
+ ).fetchone()
+ if table_exists is not None
+ else None
+ )
+ if existing is not None:
+ continue
+ connection.execute(migration)
+ table_exists = "schema_migrations"
+ if migration_version == 1:
+ connection.execute(
+ """
+ INSERT INTO schema_migrations(version, applied_at)
+ VALUES (%s, %s)
+ """,
+ (migration_version, _now()),
+ )
+ else:
+ connection.execute(
+ """
+ INSERT INTO schema_migrations(
+ version, filename, checksum, applied_at
+ ) VALUES (%s, %s, %s, %s)
+ """,
+ (migration_version, filename, checksum, _now()),
+ )
+ # Migration 0002 introduces checksum metadata. Backfill the
+ # immutable 0001 identity for legacy schemas after it is applied.
+ first = migrations[0]
+ connection.execute(
+ """
+ UPDATE schema_migrations
+ SET filename = COALESCE(filename, %s),
+ checksum = COALESCE(checksum, %s)
+ WHERE version = 1
+ """,
+ (first[1], first[3]),
+ )
+ for migration_version, filename, _, checksum in migrations:
+ row = connection.execute(
+ """
+ SELECT filename, checksum FROM schema_migrations
+ WHERE version = %s
+ """,
+ (migration_version,),
+ ).fetchone()
+ if row != (filename, checksum):
+ raise RuntimeError(f"migration {filename} checksum mismatch")
+
+ @classmethod
+ def verify_schema(cls, dsn: str, *, schema: str = "openrath") -> None:
+ if not _SCHEMA_NAME.fullmatch(schema):
+ raise ValueError("schema must be a safe lowercase PostgreSQL identifier")
+ import psycopg
+ from psycopg import sql
+
+ migrations = cls._migrations()
+ required_tables = {
+ "runs",
+ "run_events",
+ "checkpoints",
+ "interrupts",
+ "run_leases",
+ "tool_invocations",
+ }
+ with psycopg.connect(dsn) as connection:
+ migration_rows = connection.execute(
+ sql.SQL(
+ """
+ SELECT version, filename, checksum
+ FROM {}.schema_migrations ORDER BY version
+ """
+ ).format(sql.Identifier(schema))
+ ).fetchall()
+ rows = connection.execute(
+ """
+ SELECT table_name FROM information_schema.tables
+ WHERE table_schema = %s
+ """,
+ (schema,),
+ ).fetchall()
+ column_rows = connection.execute(
+ """
+ SELECT table_name, column_name
+ FROM information_schema.columns
+ WHERE table_schema = %s
+ AND table_name IN ('schema_migrations', 'tool_invocations')
+ """,
+ (schema,),
+ ).fetchall()
+ expected_rows = [
+ (migration_version, filename, checksum)
+ for migration_version, filename, _, checksum in migrations
+ ]
+ if migration_rows != expected_rows:
+ raise RuntimeError("OpenRath schema migration checksums are not current")
+ present = {str(value[0]) for value in rows}
+ missing = required_tables - present
+ if missing:
+ raise RuntimeError(f"OpenRath schema is missing tables: {sorted(missing)}")
+ present_columns = {(str(row[0]), str(row[1])) for row in column_rows}
+ required_columns = {
+ ("schema_migrations", "filename"),
+ ("schema_migrations", "checksum"),
+ ("tool_invocations", "node_id"),
+ ("tool_invocations", "checkpoint_sequence"),
+ ("tool_invocations", "invocation_sequence"),
+ }
+ missing_columns = required_columns - present_columns
+ if missing_columns:
+ raise RuntimeError(
+ f"OpenRath schema is missing columns: {sorted(missing_columns)}"
+ )
+
+ @contextmanager
+ def _transaction(self) -> Iterator[Any]:
+ if self._closed:
+ raise RuntimeError("PostgresRunStore is closed")
+ with self._pool.connection() as connection:
+ yield connection
+
+ @contextmanager
+ def connection(self) -> Iterator[Any]:
+ """Borrow a schema-configured pooled connection for related stores."""
+ with self._transaction() as connection:
+ yield connection
+
+ def close(self) -> None:
+ if not self._closed:
+ self._pool.close()
+ self._closed = True
+
+ def create_run(self, run: Run) -> Run:
+ fingerprint = self._fingerprint(run)
+ with self._transaction() as connection:
+ if run.idempotency_key is not None:
+ existing = connection.execute(
+ """
+ SELECT * FROM runs
+ WHERE tenant_id = %s AND idempotency_key = %s
+ FOR UPDATE
+ """,
+ (run.tenant_id, run.idempotency_key),
+ ).fetchone()
+ if existing is not None:
+ if existing["request_fingerprint"] != fingerprint:
+ raise ConflictError(
+ "idempotency key was already used for a different request"
+ )
+ return self._run_from_row(existing)
+ inserted = connection.execute(
+ """
+ INSERT INTO runs(
+ id, plan_id, revision_id, session_id, tenant_id, status,
+ state_json, next_nodes_json, idempotency_key, context_json,
+ priority,
+ request_fingerprint, created_at, updated_at, version
+ ) VALUES (
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
+ )
+ ON CONFLICT DO NOTHING
+ RETURNING id
+ """,
+ (
+ run.id,
+ run.plan_id,
+ run.revision_id,
+ run.session_id,
+ run.tenant_id,
+ run.status.value,
+ _json(run.state),
+ _json(run.next_nodes),
+ run.idempotency_key,
+ _json(run.context),
+ run.priority,
+ fingerprint,
+ run.created_at,
+ run.updated_at,
+ run.version,
+ ),
+ ).fetchone()
+ if inserted is None:
+ if run.idempotency_key is not None:
+ existing = connection.execute(
+ """
+ SELECT * FROM runs
+ WHERE tenant_id = %s AND idempotency_key = %s
+ """,
+ (run.tenant_id, run.idempotency_key),
+ ).fetchone()
+ if (
+ existing is not None
+ and existing["request_fingerprint"] == fingerprint
+ ):
+ return self._run_from_row(existing)
+ raise ConflictError("run already exists")
+ self._append_event(
+ connection, run.id, "run.created", {"status": run.status.value}
+ )
+ return run
+
+ def get_run(self, run_id: UUID) -> Run:
+ with self._transaction() as connection:
+ row = connection.execute(
+ "SELECT * FROM runs WHERE id = %s", (run_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(run_id))
+ return self._run_from_row(row)
+
+ def list_runs(
+ self,
+ *,
+ tenant_id: str,
+ after: UUID | None = None,
+ limit: int | None = None,
+ session_id: UUID | None = None,
+ statuses: tuple[RunStatus, ...] | None = None,
+ ) -> tuple[Run, ...]:
+ if limit is not None and limit < 1:
+ raise ValueError("limit must be positive")
+ with self._transaction() as connection:
+ clauses = ["tenant_id = %s"]
+ parameters: list[object] = [tenant_id]
+ if after is not None:
+ cursor = connection.execute(
+ """
+ SELECT created_at, id FROM runs
+ WHERE id = %s AND tenant_id = %s
+ """,
+ (after, tenant_id),
+ ).fetchone()
+ if cursor is None:
+ raise KeyError(str(after))
+ clauses.append("(created_at, id) > (%s, %s)")
+ parameters.extend((cursor["created_at"], cursor["id"]))
+ if session_id is not None:
+ clauses.append("session_id = %s")
+ parameters.append(session_id)
+ if statuses:
+ clauses.append("status = ANY(%s)")
+ parameters.append([item.value for item in statuses])
+ suffix = " LIMIT %s" if limit is not None else ""
+ if limit is not None:
+ parameters.append(limit)
+ rows = connection.execute(
+ f"""
+ SELECT * FROM runs WHERE {" AND ".join(clauses)}
+ ORDER BY created_at, id{suffix}
+ """,
+ parameters,
+ ).fetchall()
+ return tuple(self._run_from_row(row) for row in rows)
+
+ def count_runs(
+ self,
+ *,
+ status: RunStatus,
+ tenant_id: str | None = None,
+ ) -> int:
+ with self._transaction() as connection:
+ if tenant_id is None:
+ row = connection.execute(
+ "SELECT COUNT(*) AS value FROM runs WHERE status = %s",
+ (status.value,),
+ ).fetchone()
+ else:
+ row = connection.execute(
+ """
+ SELECT COUNT(*) AS value FROM runs
+ WHERE status = %s AND tenant_id = %s
+ """,
+ (status.value, tenant_id),
+ ).fetchone()
+ return int(row["value"])
+
+ def transition_run(
+ self,
+ run_id: UUID,
+ *,
+ expected_version: int,
+ target: RunStatus,
+ state: Mapping[str, object] | None = None,
+ next_nodes: tuple[str, ...] | None = None,
+ ) -> Run:
+ with self._transaction() as connection:
+ current = self._run_from_row(self._required_run_row(connection, run_id))
+ if current.version != expected_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, target)
+ row = connection.execute(
+ """
+ UPDATE runs SET status = %s, state_json = %s,
+ next_nodes_json = %s, updated_at = %s, version = version + 1
+ WHERE id = %s AND version = %s RETURNING *
+ """,
+ (
+ target.value,
+ _json(state if state is not None else current.state),
+ _json(next_nodes if next_nodes is not None else current.next_nodes),
+ _now(),
+ run_id,
+ expected_version,
+ ),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("run version conflict")
+ self._append_event(
+ connection,
+ run_id,
+ "run.state.changed",
+ {"from": current.status.value, "to": target.value},
+ )
+ return self._run_from_row(row)
+
+ def list_run_events(
+ self,
+ run_id: UUID,
+ *,
+ after_sequence: int = 0,
+ limit: int | None = None,
+ ) -> tuple[RunEvent, ...]:
+ if after_sequence < 0:
+ raise ValueError("after_sequence must not be negative")
+ if limit is not None and limit < 1:
+ raise ValueError("limit must be positive")
+ with self._transaction() as connection:
+ suffix = " LIMIT %s" if limit is not None else ""
+ parameters: list[object] = [run_id, after_sequence]
+ if limit is not None:
+ parameters.append(limit)
+ rows = connection.execute(
+ f"""
+ SELECT * FROM run_events
+ WHERE run_id = %s AND sequence > %s ORDER BY sequence{suffix}
+ """,
+ parameters,
+ ).fetchall()
+ return tuple(
+ RunEvent(
+ run_id=row["run_id"],
+ sequence=int(row["sequence"]),
+ type=row["type"],
+ data=row["data_json"],
+ created_at=row["created_at"],
+ )
+ for row in rows
+ )
+
+ def append_run_event(
+ self,
+ run_id: UUID,
+ type: str,
+ data: Mapping[str, object],
+ ) -> RunEvent:
+ with self._transaction() as connection:
+ self._required_run_row(connection, run_id)
+ return self._append_event(connection, run_id, type, data)
+
+ def append_checkpoint(self, checkpoint: Checkpoint) -> None:
+ with self._transaction() as connection:
+ self._required_run_row(connection, checkpoint.run_id, lock=True)
+ self._validate_checkpoint_sequence(connection, checkpoint)
+ self._insert_checkpoint(connection, checkpoint)
+ self._append_event(
+ connection,
+ checkpoint.run_id,
+ "run.checkpoint.created",
+ {"checkpoint_id": str(checkpoint.id), "sequence": checkpoint.sequence},
+ )
+
+ def latest_checkpoint(self, run_id: UUID) -> Checkpoint | None:
+ with self._transaction() as connection:
+ row = connection.execute(
+ """
+ SELECT * FROM checkpoints
+ WHERE run_id = %s ORDER BY sequence DESC LIMIT 1
+ """,
+ (run_id,),
+ ).fetchone()
+ return None if row is None else self._checkpoint_from_row(row)
+
+ def list_checkpoints(self, run_id: UUID) -> tuple[Checkpoint, ...]:
+ with self._transaction() as connection:
+ rows = connection.execute(
+ """
+ SELECT * FROM checkpoints
+ WHERE run_id = %s ORDER BY sequence
+ """,
+ (run_id,),
+ ).fetchall()
+ return tuple(self._checkpoint_from_row(row) for row in rows)
+
+ def commit_checkpoint(
+ self,
+ checkpoint: Checkpoint,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ ) -> Run:
+ with self._transaction() as connection:
+ self._required_lease(
+ connection,
+ checkpoint.run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ current = self._run_from_row(
+ self._required_run_row(connection, checkpoint.run_id, lock=True)
+ )
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ if current.status is not RunStatus.RUNNING:
+ raise ConflictError("checkpoint requires a running run")
+ self._validate_checkpoint_sequence(connection, checkpoint)
+ self._insert_checkpoint(connection, checkpoint)
+ row = connection.execute(
+ """
+ UPDATE runs SET state_json = %s, next_nodes_json = %s,
+ updated_at = %s, version = version + 1
+ WHERE id = %s AND version = %s RETURNING *
+ """,
+ (
+ _json(checkpoint.state),
+ _json(checkpoint.next_nodes),
+ checkpoint.created_at,
+ checkpoint.run_id,
+ expected_run_version,
+ ),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("run version conflict")
+ self._append_event(
+ connection,
+ checkpoint.run_id,
+ "run.checkpoint.created",
+ {"checkpoint_id": str(checkpoint.id), "sequence": checkpoint.sequence},
+ )
+ return self._run_from_row(row)
+
+ def finish_claim(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ target: RunStatus,
+ event_type: str = "run.execution.completed",
+ event_data: Mapping[str, object] | None = None,
+ ) -> Run:
+ with self._transaction() as connection:
+ self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ current = self._run_from_row(
+ self._required_run_row(connection, run_id, lock=True)
+ )
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, target)
+ row = connection.execute(
+ """
+ UPDATE runs SET status = %s, updated_at = %s, version = version + 1
+ WHERE id = %s AND version = %s RETURNING *
+ """,
+ (target.value, _now(), run_id, expected_run_version),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("run version conflict")
+ connection.execute(
+ """
+ UPDATE run_leases SET active = FALSE, updated_at = %s
+ WHERE run_id = %s
+ """,
+ (_now(), run_id),
+ )
+ self._append_event(
+ connection,
+ run_id,
+ event_type,
+ event_data or {"status": target.value},
+ )
+ return self._run_from_row(row)
+
+ def create_interrupt(
+ self, interrupt: Interrupt, *, expected_run_version: int
+ ) -> Run:
+ with self._transaction() as connection:
+ current = self._run_from_row(
+ self._required_run_row(connection, interrupt.run_id, lock=True)
+ )
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, RunStatus.WAITING)
+ connection.execute(
+ """
+ INSERT INTO interrupts(
+ id, run_id, kind, request_json, created_at, expires_at
+ )
+ VALUES (%s, %s, %s, %s, %s, %s)
+ """,
+ (
+ interrupt.id,
+ interrupt.run_id,
+ interrupt.kind.value,
+ _json(interrupt.request),
+ interrupt.created_at,
+ interrupt.expires_at,
+ ),
+ )
+ row = self._update_status(
+ connection,
+ current,
+ target=RunStatus.WAITING,
+ expected_version=expected_run_version,
+ )
+ connection.execute(
+ """
+ UPDATE run_leases SET active = FALSE, updated_at = %s
+ WHERE run_id = %s
+ """,
+ (interrupt.created_at, interrupt.run_id),
+ )
+ self._append_event(
+ connection,
+ interrupt.run_id,
+ "run.interrupt.created",
+ {"interrupt_id": str(interrupt.id), "kind": interrupt.kind.value},
+ )
+ return self._run_from_row(row)
+
+ def get_interrupt(self, interrupt_id: UUID) -> Interrupt:
+ with self._transaction() as connection:
+ row = connection.execute(
+ "SELECT * FROM interrupts WHERE id = %s", (interrupt_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(interrupt_id))
+ return self._interrupt_from_row(row)
+
+ def list_interrupts(
+ self,
+ *,
+ tenant_id: str,
+ pending_only: bool = True,
+ ) -> tuple[Interrupt, ...]:
+ pending_clause = "AND i.decided_at IS NULL" if pending_only else ""
+ with self.connection() as connection:
+ rows = connection.execute(
+ f"""
+ SELECT i.* FROM interrupts AS i
+ JOIN runs AS r ON r.id = i.run_id
+ WHERE r.tenant_id = %s {pending_clause}
+ ORDER BY i.created_at, i.id
+ """,
+ (tenant_id,),
+ ).fetchall()
+ return tuple(self._interrupt_from_row(row) for row in rows)
+
+ def expire_interrupts(
+ self,
+ *,
+ now: datetime | None = None,
+ ) -> tuple[UUID, ...]:
+ expired_at = now or _now()
+ if expired_at.tzinfo is None:
+ raise ValueError("now must be timezone-aware")
+ expired: list[UUID] = []
+ with self._transaction() as connection:
+ rows = connection.execute(
+ """
+ SELECT i.*, r.version AS run_version, r.status AS run_status
+ FROM interrupts AS i
+ JOIN runs AS r ON r.id = i.run_id
+ WHERE i.decided_at IS NULL
+ AND i.expires_at IS NOT NULL
+ AND i.expires_at <= %s
+ ORDER BY i.expires_at, i.id
+ FOR UPDATE OF i, r SKIP LOCKED
+ """,
+ (expired_at,),
+ ).fetchall()
+ for row in rows:
+ connection.execute(
+ """
+ UPDATE interrupts SET decision_kind = %s,
+ decision_actor_id = %s, decision_reason = %s,
+ decision_payload_json = %s, decided_at = %s
+ WHERE id = %s AND decided_at IS NULL
+ """,
+ (
+ ApprovalDecisionKind.REJECT.value,
+ "openrath-system",
+ "interrupt deadline expired",
+ _json({}),
+ expired_at,
+ row["id"],
+ ),
+ )
+ if RunStatus(row["run_status"]) is RunStatus.WAITING:
+ current = self._run_from_row(
+ self._required_run_row(connection, row["run_id"], lock=True)
+ )
+ self._update_status(
+ connection,
+ current,
+ target=RunStatus.TIMED_OUT,
+ expected_version=int(row["run_version"]),
+ )
+ self._append_event(
+ connection,
+ row["run_id"],
+ "run.interrupt.expired",
+ {"interrupt_id": str(row["id"])},
+ )
+ expired.append(row["id"])
+ return tuple(expired)
+
+ def decide_interrupt(
+ self,
+ interrupt_id: UUID,
+ *,
+ decision: ApprovalDecision,
+ expected_run_version: int,
+ ) -> Run:
+ with self._transaction() as connection:
+ row = connection.execute(
+ "SELECT * FROM interrupts WHERE id = %s FOR UPDATE",
+ (interrupt_id,),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(interrupt_id))
+ if row["decision_kind"] is not None:
+ raise ConflictError("interrupt was already decided")
+ current = self._run_from_row(
+ self._required_run_row(connection, row["run_id"], lock=True)
+ )
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, RunStatus.QUEUED)
+ connection.execute(
+ """
+ UPDATE interrupts SET decision_kind = %s,
+ decision_actor_id = %s, decision_reason = %s,
+ decision_payload_json = %s, decided_at = %s
+ WHERE id = %s AND decision_kind IS NULL
+ """,
+ (
+ decision.kind.value,
+ decision.actor_id,
+ decision.reason,
+ _json(decision.payload),
+ _now(),
+ interrupt_id,
+ ),
+ )
+ updated = self._update_status(
+ connection,
+ current,
+ target=RunStatus.QUEUED,
+ expected_version=expected_run_version,
+ )
+ self._append_event(
+ connection,
+ current.id,
+ "run.interrupt.decided",
+ {
+ "interrupt_id": str(interrupt_id),
+ "decision": decision.kind.value,
+ "actor_id": decision.actor_id,
+ },
+ )
+ return self._run_from_row(updated)
+
+ def claim_next(
+ self,
+ *,
+ worker_id: str,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ClaimedRun | None:
+ if not worker_id.strip():
+ raise ValueError("worker_id must not be empty")
+ if lease_seconds <= 0:
+ raise ValueError("lease_seconds must be greater than zero")
+ claimed_at = now or _now()
+ if claimed_at.tzinfo is None:
+ raise ValueError("now must be timezone-aware")
+ with self._transaction() as connection:
+ row = connection.execute(
+ """
+ SELECT * FROM runs WHERE status = %s
+ ORDER BY priority DESC, created_at, id
+ FOR UPDATE SKIP LOCKED LIMIT 1
+ """,
+ (RunStatus.QUEUED.value,),
+ ).fetchone()
+ if row is None:
+ return None
+ current = self._run_from_row(row)
+ previous = connection.execute(
+ "SELECT * FROM run_leases WHERE run_id = %s FOR UPDATE",
+ (current.id,),
+ ).fetchone()
+ lease_id = (
+ previous["id"]
+ if previous is not None
+ else UUID(bytes=hashlib.sha256(str(current.id).encode()).digest()[:16])
+ )
+ token = int(previous["fencing_token"]) + 1 if previous else 1
+ created_at = previous["created_at"] if previous else claimed_at
+ expires_at = claimed_at + timedelta(seconds=lease_seconds)
+ updated = connection.execute(
+ """
+ UPDATE runs SET status = %s, updated_at = %s, version = version + 1
+ WHERE id = %s AND version = %s AND status = %s RETURNING *
+ """,
+ (
+ RunStatus.RUNNING.value,
+ claimed_at,
+ current.id,
+ current.version,
+ RunStatus.QUEUED.value,
+ ),
+ ).fetchone()
+ if updated is None:
+ raise ConflictError("run claim conflict")
+ connection.execute(
+ """
+ INSERT INTO run_leases(
+ id, run_id, holder_worker_id, expires_at, fencing_token,
+ active, created_at, updated_at
+ ) VALUES (%s, %s, %s, %s, %s, TRUE, %s, %s)
+ ON CONFLICT(run_id) DO UPDATE SET
+ holder_worker_id = excluded.holder_worker_id,
+ expires_at = excluded.expires_at,
+ fencing_token = excluded.fencing_token,
+ active = TRUE, updated_at = excluded.updated_at
+ """,
+ (
+ lease_id,
+ current.id,
+ worker_id,
+ expires_at,
+ token,
+ created_at,
+ claimed_at,
+ ),
+ )
+ self._append_event(
+ connection,
+ current.id,
+ "run.claimed",
+ {"worker_id": worker_id, "fencing_token": token},
+ )
+ return ClaimedRun(
+ run=self._run_from_row(updated),
+ lease=ResourceLease(
+ id=lease_id,
+ resource_type="run",
+ resource_id=str(current.id),
+ owner_run_id=current.id,
+ holder_worker_id=worker_id,
+ expires_at=expires_at,
+ fencing_token=token,
+ created_at=created_at,
+ updated_at=claimed_at,
+ ),
+ )
+
+ def renew_lease(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ResourceLease:
+ if lease_seconds <= 0:
+ raise ValueError("lease_seconds must be greater than zero")
+ renewed_at = now or _now()
+ expires_at = renewed_at + timedelta(seconds=lease_seconds)
+ with self._transaction() as connection:
+ row = self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ connection.execute(
+ """
+ UPDATE run_leases SET expires_at = %s, updated_at = %s
+ WHERE run_id = %s
+ """,
+ (expires_at, renewed_at, run_id),
+ )
+ return self._lease_from_row(
+ {**row, "expires_at": expires_at, "updated_at": renewed_at}
+ )
+
+ def assert_fencing_token(
+ self, run_id: UUID, *, worker_id: str, fencing_token: int
+ ) -> None:
+ with self._transaction() as connection:
+ self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+
+ def requeue_expired_leases(
+ self, *, now: datetime | None = None
+ ) -> tuple[UUID, ...]:
+ recovered_at = now or _now()
+ with self._transaction() as connection:
+ rows = connection.execute(
+ """
+ SELECT l.*, r.status, r.version FROM run_leases l
+ JOIN runs r ON r.id = l.run_id
+ WHERE l.active = TRUE AND l.expires_at <= %s
+ ORDER BY l.expires_at, l.run_id FOR UPDATE OF l, r SKIP LOCKED
+ """,
+ (recovered_at,),
+ ).fetchall()
+ recovered: list[UUID] = []
+ for row in rows:
+ run_id = row["run_id"]
+ if RunStatus(row["status"]) is RunStatus.RUNNING:
+ connection.execute(
+ """
+ UPDATE runs SET status = %s, updated_at = %s,
+ version = version + 1
+ WHERE id = %s AND version = %s
+ """,
+ (
+ RunStatus.QUEUED.value,
+ recovered_at,
+ run_id,
+ row["version"],
+ ),
+ )
+ self._append_event(
+ connection,
+ run_id,
+ "run.lease.expired",
+ {"fencing_token": int(row["fencing_token"])},
+ )
+ recovered.append(run_id)
+ connection.execute(
+ """
+ UPDATE run_leases SET active = FALSE, updated_at = %s
+ WHERE run_id = %s
+ """,
+ (recovered_at, run_id),
+ )
+ return tuple(recovered)
+
+ def _required_run_row(
+ self, connection: Any, run_id: UUID, *, lock: bool = False
+ ) -> Mapping[str, Any]:
+ suffix = " FOR UPDATE" if lock else ""
+ row = connection.execute(
+ f"SELECT * FROM runs WHERE id = %s{suffix}", (run_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(run_id))
+ return cast(Mapping[str, Any], row)
+
+ def _required_lease(
+ self,
+ connection: Any,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ ) -> Mapping[str, Any]:
+ row = connection.execute(
+ "SELECT * FROM run_leases WHERE run_id = %s FOR UPDATE", (run_id,)
+ ).fetchone()
+ if (
+ row is None
+ or not row["active"]
+ or row["holder_worker_id"] != worker_id
+ or int(row["fencing_token"]) != fencing_token
+ or row["expires_at"] <= _now()
+ ):
+ raise ConflictError("lease fencing token is stale or not owned")
+ return cast(Mapping[str, Any], row)
+
+ def _update_status(
+ self,
+ connection: Any,
+ current: Run,
+ *,
+ target: RunStatus,
+ expected_version: int,
+ ) -> Mapping[str, Any]:
+ row = connection.execute(
+ """
+ UPDATE runs SET status = %s, updated_at = %s, version = version + 1
+ WHERE id = %s AND version = %s RETURNING *
+ """,
+ (target.value, _now(), current.id, expected_version),
+ ).fetchone()
+ if row is None:
+ raise ConflictError("run version conflict")
+ return cast(Mapping[str, Any], row)
+
+ def _validate_checkpoint_sequence(
+ self, connection: Any, checkpoint: Checkpoint
+ ) -> None:
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(sequence), 0) AS sequence
+ FROM checkpoints WHERE run_id = %s
+ """,
+ (checkpoint.run_id,),
+ ).fetchone()
+ expected = int(row["sequence"]) + 1
+ if checkpoint.sequence != expected:
+ raise ConflictError(
+ f"checkpoint sequence must be {expected}, got {checkpoint.sequence}"
+ )
+
+ def _insert_checkpoint(self, connection: Any, checkpoint: Checkpoint) -> None:
+ connection.execute(
+ """
+ INSERT INTO checkpoints(
+ id, run_id, sequence, plan_hash, state_json,
+ next_nodes_json, pending_interrupts_json,
+ effect_watermark, created_at
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
+ """,
+ (
+ checkpoint.id,
+ checkpoint.run_id,
+ checkpoint.sequence,
+ checkpoint.plan_hash,
+ _json(checkpoint.state),
+ _json(checkpoint.next_nodes),
+ _json(tuple(str(item) for item in checkpoint.pending_interrupts)),
+ checkpoint.effect_watermark,
+ checkpoint.created_at,
+ ),
+ )
+
+ def _append_event(
+ self,
+ connection: Any,
+ run_id: UUID,
+ type: str,
+ data: Mapping[str, object],
+ ) -> RunEvent:
+ # Serialize sequence allocation with every other event writer for this
+ # Run. MAX(sequence)+1 is safe only while the parent row is locked.
+ connection.execute(
+ "SELECT id FROM runs WHERE id = %s FOR UPDATE",
+ (run_id,),
+ ).fetchone()
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(sequence), 0) AS sequence
+ FROM run_events WHERE run_id = %s
+ """,
+ (run_id,),
+ ).fetchone()
+ created_at = _now()
+ connection.execute(
+ """
+ INSERT INTO run_events(run_id, sequence, type, data_json, created_at)
+ VALUES (%s, %s, %s, %s, %s)
+ """,
+ (run_id, int(row["sequence"]) + 1, type, _json(data), created_at),
+ )
+ return RunEvent(
+ run_id=run_id,
+ sequence=int(row["sequence"]) + 1,
+ type=type,
+ data=freeze_json(data, field="run event data"), # type: ignore[arg-type]
+ created_at=created_at,
+ )
+
+ def _fingerprint(self, run: Run) -> str:
+ frozen = freeze_json(
+ {
+ "plan_id": str(run.plan_id),
+ "revision_id": str(run.revision_id),
+ "session_id": str(run.session_id),
+ "tenant_id": run.tenant_id,
+ "state": run.state,
+ "next_nodes": run.next_nodes,
+ "priority": run.priority,
+ },
+ field="run fingerprint",
+ )
+ import json
+
+ payload = json.dumps(
+ thaw_json(frozen),
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+ return hashlib.sha256(payload.encode()).hexdigest()
+
+ @staticmethod
+ def _run_from_row(row: Mapping[str, Any]) -> Run:
+ return Run(
+ id=row["id"],
+ plan_id=row["plan_id"],
+ revision_id=row["revision_id"],
+ session_id=row["session_id"],
+ tenant_id=row["tenant_id"],
+ status=RunStatus(row["status"]),
+ state=row["state_json"],
+ next_nodes=tuple(row["next_nodes_json"]),
+ idempotency_key=row["idempotency_key"],
+ context=row["context_json"],
+ priority=int(row["priority"]),
+ created_at=row["created_at"],
+ updated_at=row["updated_at"],
+ version=int(row["version"]),
+ )
+
+ @staticmethod
+ def _checkpoint_from_row(row: Mapping[str, Any]) -> Checkpoint:
+ return Checkpoint(
+ id=row["id"],
+ run_id=row["run_id"],
+ sequence=int(row["sequence"]),
+ plan_hash=row["plan_hash"],
+ state=row["state_json"],
+ next_nodes=tuple(row["next_nodes_json"]),
+ pending_interrupts=tuple(
+ UUID(item) for item in row["pending_interrupts_json"]
+ ),
+ effect_watermark=int(row["effect_watermark"]),
+ created_at=row["created_at"],
+ )
+
+ @staticmethod
+ def _interrupt_from_row(row: Mapping[str, Any]) -> Interrupt:
+ decision = None
+ if row["decision_kind"] is not None:
+ decision = ApprovalDecision(
+ kind=ApprovalDecisionKind(row["decision_kind"]),
+ actor_id=row["decision_actor_id"],
+ reason=row["decision_reason"],
+ payload=row["decision_payload_json"],
+ )
+ return Interrupt(
+ id=row["id"],
+ run_id=row["run_id"],
+ kind=InterruptKind(row["kind"]),
+ request=row["request_json"],
+ created_at=row["created_at"],
+ expires_at=row["expires_at"],
+ decision=decision,
+ decided_at=row["decided_at"],
+ )
+
+ @staticmethod
+ def _lease_from_row(row: Mapping[str, Any]) -> ResourceLease:
+ run_id = row["run_id"]
+ return ResourceLease(
+ id=row["id"],
+ resource_type="run",
+ resource_id=str(run_id),
+ owner_run_id=run_id,
+ holder_worker_id=row["holder_worker_id"],
+ expires_at=row["expires_at"],
+ fencing_token=int(row["fencing_token"]),
+ created_at=row["created_at"],
+ updated_at=row["updated_at"],
+ )
diff --git a/src/rath/runtime/signals.py b/src/rath/runtime/signals.py
new file mode 100644
index 0000000..941e9c1
--- /dev/null
+++ b/src/rath/runtime/signals.py
@@ -0,0 +1,144 @@
+"""Optional low-latency signals; never a durable Run source of truth."""
+
+from __future__ import annotations
+
+import json
+import math
+import queue
+from dataclasses import dataclass
+from datetime import datetime
+from enum import Enum
+from typing import Protocol, runtime_checkable
+from uuid import UUID
+
+__all__ = [
+ "GuardedSignalBus",
+ "InMemorySignalBus",
+ "RedisSignalBus",
+ "RunSignal",
+ "SignalBus",
+ "SignalKind",
+]
+
+
+class SignalKind(str, Enum):
+ WAKE = "wake"
+ CANCEL = "cancel"
+
+
+@dataclass(frozen=True, slots=True)
+class RunSignal:
+ kind: SignalKind
+ run_id: UUID
+ tenant_id: str
+ created_at: datetime
+
+ def __post_init__(self) -> None:
+ if not self.tenant_id:
+ raise ValueError("tenant_id must not be empty")
+ if self.created_at.tzinfo is None:
+ raise ValueError("created_at must be timezone-aware")
+
+
+@runtime_checkable
+class SignalBus(Protocol):
+ def publish(self, signal: RunSignal) -> None: ...
+
+ def receive(self, *, timeout_seconds: float = 0) -> RunSignal | None: ...
+
+
+class InMemorySignalBus:
+ def __init__(self) -> None:
+ self._queue: queue.Queue[RunSignal] = queue.Queue()
+
+ def publish(self, signal: RunSignal) -> None:
+ self._queue.put_nowait(signal)
+
+ def receive(self, *, timeout_seconds: float = 0) -> RunSignal | None:
+ try:
+ return self._queue.get(timeout=timeout_seconds)
+ except queue.Empty:
+ return None
+
+
+class RedisSignalBus:
+ """Redis list transport used only to reduce polling latency."""
+
+ def __init__(
+ self,
+ url: str,
+ *,
+ namespace: str = "openrath",
+ client: object | None = None,
+ ) -> None:
+ if not namespace or any(char.isspace() for char in namespace):
+ raise ValueError("namespace must be a non-empty token")
+ if client is None:
+ try:
+ import redis
+ except ImportError as exc:
+ raise RuntimeError(
+ "Redis signaling requires `pip install openrath[redis]`"
+ ) from exc
+ client = redis.Redis.from_url(
+ url,
+ decode_responses=True,
+ socket_connect_timeout=2,
+ socket_timeout=2,
+ )
+ self.client = client
+ self.key = f"{namespace}:run-signals"
+
+ def publish(self, signal: RunSignal) -> None:
+ payload = json.dumps(
+ {
+ "kind": signal.kind.value,
+ "run_id": str(signal.run_id),
+ "tenant_id": signal.tenant_id,
+ "created_at": signal.created_at.isoformat(),
+ },
+ separators=(",", ":"),
+ )
+ self.client.lpush(self.key, payload) # type: ignore[attr-defined]
+ self.client.ltrim(self.key, 0, 9999) # type: ignore[attr-defined]
+
+ def receive(self, *, timeout_seconds: float = 0) -> RunSignal | None:
+ if timeout_seconds <= 0:
+ payload = self.client.rpop(self.key) # type: ignore[attr-defined]
+ else:
+ timeout = max(1, math.ceil(timeout_seconds))
+ result = self.client.brpop( # type: ignore[attr-defined]
+ self.key,
+ timeout=timeout,
+ )
+ payload = result[1] if result is not None else None
+ if payload is None:
+ return None
+ data = json.loads(payload)
+ return RunSignal(
+ kind=SignalKind(data["kind"]),
+ run_id=UUID(data["run_id"]),
+ tenant_id=data["tenant_id"],
+ created_at=datetime.fromisoformat(data["created_at"]),
+ )
+
+
+class GuardedSignalBus:
+ """Best-effort wrapper preserving database success when Redis is unavailable."""
+
+ def __init__(self, inner: SignalBus) -> None:
+ self.inner = inner
+ self.failures = 0
+
+ def publish(self, signal: RunSignal) -> None:
+ try:
+ self.inner.publish(signal)
+ except Exception:
+ self.failures += 1
+
+ def receive(self, *, timeout_seconds: float = 0) -> RunSignal | None:
+ try:
+ return self.inner.receive(timeout_seconds=timeout_seconds)
+ except Exception:
+ self.failures += 1
+ return None
diff --git a/src/rath/runtime/sqlite.py b/src/rath/runtime/sqlite.py
new file mode 100644
index 0000000..7adaf6f
--- /dev/null
+++ b/src/rath/runtime/sqlite.py
@@ -0,0 +1,1396 @@
+"""Transactional SQLite reference store for embedded durable execution."""
+
+from __future__ import annotations
+
+import hashlib
+import json
+import sqlite3
+import threading
+from collections.abc import Iterator, Mapping
+from contextlib import contextmanager
+from datetime import datetime, timedelta, timezone
+from pathlib import Path
+from typing import cast
+from uuid import UUID
+
+from rath._json import freeze_json, thaw_json
+from rath.runtime.models import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Checkpoint,
+ ClaimedRun,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ ResourceLease,
+ Run,
+ RunEvent,
+ RunStatus,
+ assert_transition,
+)
+
+__all__ = ["SQLiteRunStore"]
+
+_SCHEMA = """
+CREATE TABLE IF NOT EXISTS schema_migrations (
+ version INTEGER PRIMARY KEY,
+ applied_at TEXT NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS runs (
+ id TEXT PRIMARY KEY,
+ plan_id TEXT NOT NULL,
+ revision_id TEXT NOT NULL,
+ session_id TEXT NOT NULL,
+ tenant_id TEXT NOT NULL,
+ status TEXT NOT NULL,
+ state_json TEXT NOT NULL,
+ next_nodes_json TEXT NOT NULL,
+ idempotency_key TEXT,
+ context_json TEXT NOT NULL DEFAULT '{}',
+ priority INTEGER NOT NULL DEFAULT 0,
+ request_fingerprint TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL,
+ version INTEGER NOT NULL,
+ UNIQUE (tenant_id, idempotency_key)
+);
+
+CREATE INDEX IF NOT EXISTS runs_tenant_status_idx
+ ON runs (tenant_id, status, created_at);
+
+CREATE UNIQUE INDEX IF NOT EXISTS runs_one_active_per_session_idx
+ ON runs (session_id)
+ WHERE status IN ('queued', 'running', 'waiting', 'needs_review');
+
+CREATE TABLE IF NOT EXISTS run_events (
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ sequence INTEGER NOT NULL,
+ type TEXT NOT NULL,
+ data_json TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ PRIMARY KEY (run_id, sequence)
+);
+
+CREATE TABLE IF NOT EXISTS checkpoints (
+ id TEXT PRIMARY KEY,
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ sequence INTEGER NOT NULL,
+ plan_hash TEXT NOT NULL,
+ state_json TEXT NOT NULL,
+ next_nodes_json TEXT NOT NULL,
+ pending_interrupts_json TEXT NOT NULL,
+ effect_watermark INTEGER NOT NULL,
+ created_at TEXT NOT NULL,
+ UNIQUE (run_id, sequence)
+);
+
+CREATE TABLE IF NOT EXISTS interrupts (
+ id TEXT PRIMARY KEY,
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ kind TEXT NOT NULL,
+ request_json TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ expires_at TEXT,
+ decision_kind TEXT,
+ decision_actor_id TEXT,
+ decision_reason TEXT,
+ decision_payload_json TEXT,
+ decided_at TEXT
+);
+
+CREATE INDEX IF NOT EXISTS interrupts_run_pending_idx
+ ON interrupts (run_id, decided_at);
+
+CREATE TABLE IF NOT EXISTS run_leases (
+ id TEXT PRIMARY KEY,
+ run_id TEXT NOT NULL UNIQUE REFERENCES runs(id) ON DELETE CASCADE,
+ holder_worker_id TEXT NOT NULL,
+ expires_at TEXT NOT NULL,
+ fencing_token INTEGER NOT NULL,
+ active INTEGER NOT NULL,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS run_leases_expiry_idx
+ ON run_leases (active, expires_at);
+
+CREATE TABLE IF NOT EXISTS tool_invocations (
+ id TEXT PRIMARY KEY,
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ tool_name TEXT NOT NULL,
+ effect_class TEXT NOT NULL,
+ idempotency_key TEXT,
+ arguments_digest TEXT NOT NULL,
+ status TEXT NOT NULL,
+ result_json TEXT,
+ error TEXT,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL,
+ node_id TEXT,
+ checkpoint_sequence INTEGER,
+ invocation_sequence INTEGER,
+ UNIQUE (run_id, idempotency_key)
+);
+
+CREATE INDEX IF NOT EXISTS tool_invocations_reconcile_idx
+ ON tool_invocations (status, effect_class, updated_at);
+
+CREATE TABLE IF NOT EXISTS server_sessions (
+ id TEXT PRIMARY KEY,
+ tenant_id TEXT NOT NULL,
+ created_at TEXT NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS server_sessions_tenant_idx
+ ON server_sessions (tenant_id, created_at);
+
+CREATE TABLE IF NOT EXISTS server_assistants (
+ tenant_id TEXT NOT NULL,
+ id TEXT NOT NULL,
+ template_id TEXT NOT NULL,
+ revision_id TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ PRIMARY KEY (tenant_id, id)
+);
+
+CREATE TABLE IF NOT EXISTS feedback (
+ id TEXT PRIMARY KEY,
+ tenant_id TEXT NOT NULL,
+ run_id TEXT NOT NULL REFERENCES runs(id) ON DELETE CASCADE,
+ key TEXT NOT NULL,
+ score REAL,
+ value TEXT,
+ created_at TEXT NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS feedback_run_idx ON feedback (run_id, created_at);
+
+CREATE TABLE IF NOT EXISTS evaluation_datasets (
+ id TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ version TEXT NOT NULL,
+ examples_json TEXT NOT NULL,
+ UNIQUE (name, version)
+);
+
+CREATE TABLE IF NOT EXISTS evaluation_experiments (
+ id TEXT PRIMARY KEY,
+ dataset_id TEXT NOT NULL REFERENCES evaluation_datasets(id),
+ revision_id TEXT NOT NULL,
+ results_json TEXT NOT NULL,
+ created_at TEXT NOT NULL
+);
+
+CREATE INDEX IF NOT EXISTS evaluation_experiments_revision_idx
+ ON evaluation_experiments (revision_id, created_at);
+
+CREATE TABLE IF NOT EXISTS revisions (
+ id TEXT PRIMARY KEY,
+ content_digest TEXT NOT NULL UNIQUE,
+ code_digest TEXT NOT NULL,
+ plan_hash TEXT NOT NULL,
+ manifest_json TEXT NOT NULL,
+ created_at TEXT NOT NULL
+);
+"""
+
+
+def _dump(value: object) -> str:
+ frozen = freeze_json(value, field="persistence value")
+ return json.dumps(
+ thaw_json(frozen),
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ )
+
+
+def _load(value: str) -> object:
+ return json.loads(value)
+
+
+def _now() -> datetime:
+ return datetime.now(timezone.utc)
+
+
+def _parse_time(value: str) -> datetime:
+ parsed = datetime.fromisoformat(value)
+ if parsed.tzinfo is None:
+ raise ValueError("persisted timestamp must be timezone-aware")
+ return parsed
+
+
+class SQLiteRunStore:
+ """SQLite source of truth for local mode; every mutation is transactional."""
+
+ def __init__(self, path: str | Path) -> None:
+ self.path = Path(path).expanduser().resolve(strict=False)
+ self.path.parent.mkdir(parents=True, exist_ok=True)
+ self._closed = False
+ self._migration_lock = threading.Lock()
+ self._migrate()
+
+ def _connect(self) -> sqlite3.Connection:
+ if self._closed:
+ raise RuntimeError("SQLiteRunStore is closed")
+ connection = sqlite3.connect(
+ str(self.path),
+ timeout=30.0,
+ isolation_level=None,
+ )
+ connection.row_factory = sqlite3.Row
+ connection.execute("PRAGMA foreign_keys = ON")
+ connection.execute("PRAGMA journal_mode = WAL")
+ connection.execute("PRAGMA busy_timeout = 30000")
+ return connection
+
+ def _migrate(self) -> None:
+ with self._migration_lock:
+ connection = self._connect()
+ try:
+ connection.executescript(_SCHEMA)
+ columns = {
+ row[1]
+ for row in connection.execute("PRAGMA table_info(runs)").fetchall()
+ }
+ if "context_json" not in columns:
+ connection.execute(
+ "ALTER TABLE runs ADD COLUMN context_json TEXT NOT NULL DEFAULT '{}'"
+ )
+ if "priority" not in columns:
+ connection.execute(
+ "ALTER TABLE runs ADD COLUMN priority INTEGER NOT NULL DEFAULT 0"
+ )
+ revision_columns = {
+ row[1]
+ for row in connection.execute(
+ "PRAGMA table_info(revisions)"
+ ).fetchall()
+ }
+ if "content_digest" not in revision_columns:
+ connection.execute(
+ "ALTER TABLE revisions ADD COLUMN content_digest TEXT"
+ )
+ connection.execute(
+ """
+ UPDATE revisions
+ SET content_digest = code_digest || ':' || id
+ WHERE content_digest IS NULL
+ """
+ )
+ invocation_columns = {
+ row[1]
+ for row in connection.execute(
+ "PRAGMA table_info(tool_invocations)"
+ ).fetchall()
+ }
+ for name, kind in (
+ ("node_id", "TEXT"),
+ ("checkpoint_sequence", "INTEGER"),
+ ("invocation_sequence", "INTEGER"),
+ ):
+ if name not in invocation_columns:
+ connection.execute(
+ f"ALTER TABLE tool_invocations ADD COLUMN {name} {kind}"
+ )
+ connection.execute(
+ """
+ CREATE UNIQUE INDEX IF NOT EXISTS
+ tool_invocations_run_sequence_idx
+ ON tool_invocations (run_id, invocation_sequence)
+ WHERE invocation_sequence IS NOT NULL
+ """
+ )
+ connection.execute(
+ """
+ CREATE UNIQUE INDEX IF NOT EXISTS revisions_content_digest_idx
+ ON revisions (content_digest)
+ """
+ )
+ interrupt_columns = {
+ row[1]
+ for row in connection.execute(
+ "PRAGMA table_info(interrupts)"
+ ).fetchall()
+ }
+ if "expires_at" not in interrupt_columns:
+ connection.execute(
+ "ALTER TABLE interrupts ADD COLUMN expires_at TEXT"
+ )
+ connection.execute(
+ """
+ CREATE INDEX IF NOT EXISTS interrupts_expiry_idx
+ ON interrupts (expires_at) WHERE decided_at IS NULL
+ """
+ )
+ connection.execute(
+ """
+ INSERT OR IGNORE INTO schema_migrations(version, applied_at)
+ VALUES (1, ?)
+ """,
+ (_now().isoformat(),),
+ )
+ finally:
+ connection.close()
+
+ @contextmanager
+ def _transaction(self) -> Iterator[sqlite3.Connection]:
+ connection = self._connect()
+ try:
+ connection.execute("BEGIN IMMEDIATE")
+ yield connection
+ connection.commit()
+ except BaseException:
+ connection.rollback()
+ raise
+ finally:
+ connection.close()
+
+ def close(self) -> None:
+ self._closed = True
+
+ def create_run(self, run: Run) -> Run:
+ fingerprint = self._fingerprint(run)
+ with self._transaction() as connection:
+ if run.idempotency_key is not None:
+ existing = connection.execute(
+ """
+ SELECT * FROM runs
+ WHERE tenant_id = ? AND idempotency_key = ?
+ """,
+ (run.tenant_id, run.idempotency_key),
+ ).fetchone()
+ if existing is not None:
+ if existing["request_fingerprint"] != fingerprint:
+ raise ConflictError(
+ "idempotency key was already used for a different request"
+ )
+ return self._run_from_row(existing)
+ try:
+ connection.execute(
+ """
+ INSERT INTO runs(
+ id, plan_id, revision_id, session_id, tenant_id, status,
+ state_json, next_nodes_json, idempotency_key, context_json,
+ priority,
+ request_fingerprint, created_at, updated_at, version
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(run.id),
+ str(run.plan_id),
+ str(run.revision_id),
+ str(run.session_id),
+ run.tenant_id,
+ run.status.value,
+ _dump(run.state),
+ _dump(run.next_nodes),
+ run.idempotency_key,
+ _dump(run.context),
+ run.priority,
+ fingerprint,
+ run.created_at.isoformat(),
+ run.updated_at.isoformat(),
+ run.version,
+ ),
+ )
+ except sqlite3.IntegrityError as exc:
+ raise ConflictError("run already exists") from exc
+ self._append_event(
+ connection,
+ run.id,
+ "run.created",
+ {"status": run.status.value},
+ )
+ return run
+
+ def get_run(self, run_id: UUID) -> Run:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ "SELECT * FROM runs WHERE id = ?",
+ (str(run_id),),
+ ).fetchone()
+ finally:
+ connection.close()
+ if row is None:
+ raise KeyError(str(run_id))
+ return self._run_from_row(row)
+
+ def list_runs(
+ self,
+ *,
+ tenant_id: str,
+ after: UUID | None = None,
+ limit: int | None = None,
+ session_id: UUID | None = None,
+ statuses: tuple[RunStatus, ...] | None = None,
+ ) -> tuple[Run, ...]:
+ if limit is not None and limit < 1:
+ raise ValueError("limit must be positive")
+ connection = self._connect()
+ try:
+ clauses = ["tenant_id = ?"]
+ parameters: list[object] = [tenant_id]
+ if after is not None:
+ cursor = connection.execute(
+ "SELECT created_at, id FROM runs WHERE id = ? AND tenant_id = ?",
+ (str(after), tenant_id),
+ ).fetchone()
+ if cursor is None:
+ raise KeyError(str(after))
+ clauses.append("(created_at, id) > (?, ?)")
+ parameters.extend((cursor["created_at"], cursor["id"]))
+ if session_id is not None:
+ clauses.append("session_id = ?")
+ parameters.append(str(session_id))
+ if statuses:
+ placeholders = ", ".join("?" for _ in statuses)
+ clauses.append(f"status IN ({placeholders})")
+ parameters.extend(item.value for item in statuses)
+ suffix = " LIMIT ?" if limit is not None else ""
+ if limit is not None:
+ parameters.append(limit)
+ rows = connection.execute(
+ f"""
+ SELECT * FROM runs WHERE {" AND ".join(clauses)}
+ ORDER BY created_at, id{suffix}
+ """,
+ parameters,
+ ).fetchall()
+ finally:
+ connection.close()
+ return tuple(self._run_from_row(row) for row in rows)
+
+ def count_runs(
+ self,
+ *,
+ status: RunStatus,
+ tenant_id: str | None = None,
+ ) -> int:
+ connection = self._connect()
+ try:
+ if tenant_id is None:
+ row = connection.execute(
+ "SELECT COUNT(*) AS value FROM runs WHERE status = ?",
+ (status.value,),
+ ).fetchone()
+ else:
+ row = connection.execute(
+ """
+ SELECT COUNT(*) AS value FROM runs
+ WHERE status = ? AND tenant_id = ?
+ """,
+ (status.value, tenant_id),
+ ).fetchone()
+ finally:
+ connection.close()
+ return int(row["value"])
+
+ def transition_run(
+ self,
+ run_id: UUID,
+ *,
+ expected_version: int,
+ target: RunStatus,
+ state: Mapping[str, object] | None = None,
+ next_nodes: tuple[str, ...] | None = None,
+ ) -> Run:
+ with self._transaction() as connection:
+ row = self._required_run_row(connection, run_id)
+ current = self._run_from_row(row)
+ if current.version != expected_version:
+ raise ConflictError(
+ "run version conflict",
+ details={
+ "expected_version": expected_version,
+ "actual_version": current.version,
+ },
+ )
+ assert_transition(current.status, target)
+ updated_at = _now()
+ next_state = state if state is not None else current.state
+ next_queue = next_nodes if next_nodes is not None else current.next_nodes
+ cursor = connection.execute(
+ """
+ UPDATE runs
+ SET status = ?, state_json = ?, next_nodes_json = ?,
+ updated_at = ?, version = version + 1
+ WHERE id = ? AND version = ?
+ """,
+ (
+ target.value,
+ _dump(next_state),
+ _dump(next_queue),
+ updated_at.isoformat(),
+ str(run_id),
+ expected_version,
+ ),
+ )
+ if cursor.rowcount != 1:
+ raise ConflictError("run version conflict")
+ self._append_event(
+ connection,
+ run_id,
+ "run.state.changed",
+ {"from": current.status.value, "to": target.value},
+ )
+ updated_row = self._required_run_row(connection, run_id)
+ return self._run_from_row(updated_row)
+
+ def list_run_events(
+ self,
+ run_id: UUID,
+ *,
+ after_sequence: int = 0,
+ limit: int | None = None,
+ ) -> tuple[RunEvent, ...]:
+ if after_sequence < 0:
+ raise ValueError("after_sequence must not be negative")
+ if limit is not None and limit < 1:
+ raise ValueError("limit must be positive")
+ connection = self._connect()
+ try:
+ suffix = " LIMIT ?" if limit is not None else ""
+ parameters: list[object] = [str(run_id), after_sequence]
+ if limit is not None:
+ parameters.append(limit)
+ rows = connection.execute(
+ f"""
+ SELECT * FROM run_events
+ WHERE run_id = ? AND sequence > ? ORDER BY sequence{suffix}
+ """,
+ parameters,
+ ).fetchall()
+ finally:
+ connection.close()
+ return tuple(
+ RunEvent(
+ run_id=UUID(row["run_id"]),
+ sequence=int(row["sequence"]),
+ type=str(row["type"]),
+ data=_load(row["data_json"]), # type: ignore[arg-type]
+ created_at=_parse_time(row["created_at"]),
+ )
+ for row in rows
+ )
+
+ def append_run_event(
+ self,
+ run_id: UUID,
+ type: str,
+ data: Mapping[str, object],
+ ) -> RunEvent:
+ with self._transaction() as connection:
+ self._required_run_row(connection, run_id)
+ return self._append_event(connection, run_id, type, data)
+
+ def append_checkpoint(self, checkpoint: Checkpoint) -> None:
+ with self._transaction() as connection:
+ self._required_run_row(connection, checkpoint.run_id)
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(sequence), 0) AS sequence
+ FROM checkpoints WHERE run_id = ?
+ """,
+ (str(checkpoint.run_id),),
+ ).fetchone()
+ expected = int(row["sequence"]) + 1
+ if checkpoint.sequence != expected:
+ raise ConflictError(
+ f"checkpoint sequence must be {expected}, got {checkpoint.sequence}"
+ )
+ connection.execute(
+ """
+ INSERT INTO checkpoints(
+ id, run_id, sequence, plan_hash, state_json,
+ next_nodes_json, pending_interrupts_json,
+ effect_watermark, created_at
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(checkpoint.id),
+ str(checkpoint.run_id),
+ checkpoint.sequence,
+ checkpoint.plan_hash,
+ _dump(checkpoint.state),
+ _dump(checkpoint.next_nodes),
+ _dump(tuple(str(item) for item in checkpoint.pending_interrupts)),
+ checkpoint.effect_watermark,
+ checkpoint.created_at.isoformat(),
+ ),
+ )
+ self._append_event(
+ connection,
+ checkpoint.run_id,
+ "run.checkpoint.created",
+ {
+ "checkpoint_id": str(checkpoint.id),
+ "sequence": checkpoint.sequence,
+ },
+ )
+
+ def latest_checkpoint(self, run_id: UUID) -> Checkpoint | None:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ """
+ SELECT * FROM checkpoints
+ WHERE run_id = ? ORDER BY sequence DESC LIMIT 1
+ """,
+ (str(run_id),),
+ ).fetchone()
+ finally:
+ connection.close()
+ return None if row is None else self._checkpoint_from_row(row)
+
+ def list_checkpoints(self, run_id: UUID) -> tuple[Checkpoint, ...]:
+ connection = self._connect()
+ try:
+ rows = connection.execute(
+ """
+ SELECT * FROM checkpoints
+ WHERE run_id = ? ORDER BY sequence
+ """,
+ (str(run_id),),
+ ).fetchall()
+ finally:
+ connection.close()
+ return tuple(self._checkpoint_from_row(row) for row in rows)
+
+ def commit_checkpoint(
+ self,
+ checkpoint: Checkpoint,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ ) -> Run:
+ with self._transaction() as connection:
+ self._required_lease(
+ connection,
+ checkpoint.run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ current = self._run_from_row(
+ self._required_run_row(connection, checkpoint.run_id)
+ )
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ if current.status is not RunStatus.RUNNING:
+ raise ConflictError("checkpoint requires a running run")
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(sequence), 0) AS sequence
+ FROM checkpoints WHERE run_id = ?
+ """,
+ (str(checkpoint.run_id),),
+ ).fetchone()
+ expected_sequence = int(row["sequence"]) + 1
+ if checkpoint.sequence != expected_sequence:
+ raise ConflictError(
+ f"checkpoint sequence must be {expected_sequence}, "
+ f"got {checkpoint.sequence}"
+ )
+ self._insert_checkpoint(connection, checkpoint)
+ connection.execute(
+ """
+ UPDATE runs
+ SET state_json = ?, next_nodes_json = ?, updated_at = ?,
+ version = version + 1
+ WHERE id = ? AND version = ?
+ """,
+ (
+ _dump(checkpoint.state),
+ _dump(checkpoint.next_nodes),
+ checkpoint.created_at.isoformat(),
+ str(checkpoint.run_id),
+ expected_run_version,
+ ),
+ )
+ self._append_event(
+ connection,
+ checkpoint.run_id,
+ "run.checkpoint.created",
+ {
+ "checkpoint_id": str(checkpoint.id),
+ "sequence": checkpoint.sequence,
+ },
+ )
+ return self._run_from_row(
+ self._required_run_row(connection, checkpoint.run_id)
+ )
+
+ def finish_claim(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ target: RunStatus,
+ event_type: str = "run.execution.completed",
+ event_data: Mapping[str, object] | None = None,
+ ) -> Run:
+ with self._transaction() as connection:
+ self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ current = self._run_from_row(self._required_run_row(connection, run_id))
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, target)
+ self._update_status(
+ connection,
+ current,
+ target=target,
+ expected_version=expected_run_version,
+ )
+ connection.execute(
+ """
+ UPDATE run_leases SET active = 0, updated_at = ?
+ WHERE run_id = ?
+ """,
+ (_now().isoformat(), str(run_id)),
+ )
+ self._append_event(
+ connection,
+ run_id,
+ event_type,
+ event_data or {"status": target.value},
+ )
+ return self._run_from_row(self._required_run_row(connection, run_id))
+
+ def create_interrupt(
+ self,
+ interrupt: Interrupt,
+ *,
+ expected_run_version: int,
+ ) -> Run:
+ with self._transaction() as connection:
+ row = self._required_run_row(connection, interrupt.run_id)
+ current = self._run_from_row(row)
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, RunStatus.WAITING)
+ connection.execute(
+ """
+ INSERT INTO interrupts(
+ id, run_id, kind, request_json, created_at, expires_at
+ ) VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(interrupt.id),
+ str(interrupt.run_id),
+ interrupt.kind.value,
+ _dump(interrupt.request),
+ interrupt.created_at.isoformat(),
+ (
+ interrupt.expires_at.isoformat()
+ if interrupt.expires_at is not None
+ else None
+ ),
+ ),
+ )
+ self._update_status(
+ connection,
+ current,
+ target=RunStatus.WAITING,
+ expected_version=expected_run_version,
+ )
+ connection.execute(
+ """
+ UPDATE run_leases SET active = 0, updated_at = ?
+ WHERE run_id = ?
+ """,
+ (interrupt.created_at.isoformat(), str(interrupt.run_id)),
+ )
+ self._append_event(
+ connection,
+ interrupt.run_id,
+ "run.interrupt.created",
+ {"interrupt_id": str(interrupt.id), "kind": interrupt.kind.value},
+ )
+ return self._run_from_row(
+ self._required_run_row(connection, interrupt.run_id)
+ )
+
+ def get_interrupt(self, interrupt_id: UUID) -> Interrupt:
+ connection = self._connect()
+ try:
+ row = connection.execute(
+ "SELECT * FROM interrupts WHERE id = ?",
+ (str(interrupt_id),),
+ ).fetchone()
+ finally:
+ connection.close()
+ if row is None:
+ raise KeyError(str(interrupt_id))
+ return self._interrupt_from_row(row)
+
+ def list_interrupts(
+ self,
+ *,
+ tenant_id: str,
+ pending_only: bool = True,
+ ) -> tuple[Interrupt, ...]:
+ pending_clause = "AND i.decided_at IS NULL" if pending_only else ""
+ with self._connect() as connection:
+ rows = connection.execute(
+ f"""
+ SELECT i.* FROM interrupts AS i
+ JOIN runs AS r ON r.id = i.run_id
+ WHERE r.tenant_id = ? {pending_clause}
+ ORDER BY i.created_at, i.id
+ """,
+ (tenant_id,),
+ ).fetchall()
+ return tuple(self._interrupt_from_row(row) for row in rows)
+
+ def expire_interrupts(
+ self,
+ *,
+ now: datetime | None = None,
+ ) -> tuple[UUID, ...]:
+ expired_at = now or _now()
+ if expired_at.tzinfo is None:
+ raise ValueError("now must be timezone-aware")
+ expired: list[UUID] = []
+ with self._transaction() as connection:
+ rows = connection.execute(
+ """
+ SELECT i.*, r.version AS run_version, r.status AS run_status
+ FROM interrupts AS i
+ JOIN runs AS r ON r.id = i.run_id
+ WHERE i.decided_at IS NULL
+ AND i.expires_at IS NOT NULL
+ AND i.expires_at <= ?
+ ORDER BY i.expires_at, i.id
+ """,
+ (expired_at.isoformat(),),
+ ).fetchall()
+ for row in rows:
+ run_id = UUID(row["run_id"])
+ connection.execute(
+ """
+ UPDATE interrupts SET decision_kind = ?,
+ decision_actor_id = ?, decision_reason = ?,
+ decision_payload_json = ?, decided_at = ?
+ WHERE id = ? AND decided_at IS NULL
+ """,
+ (
+ ApprovalDecisionKind.REJECT.value,
+ "openrath-system",
+ "interrupt deadline expired",
+ _dump({}),
+ expired_at.isoformat(),
+ row["id"],
+ ),
+ )
+ if RunStatus(row["run_status"]) is RunStatus.WAITING:
+ current = self._run_from_row(
+ self._required_run_row(connection, run_id)
+ )
+ self._update_status(
+ connection,
+ current,
+ target=RunStatus.TIMED_OUT,
+ expected_version=int(row["run_version"]),
+ )
+ self._append_event(
+ connection,
+ run_id,
+ "run.interrupt.expired",
+ {"interrupt_id": row["id"]},
+ )
+ expired.append(UUID(row["id"]))
+ return tuple(expired)
+
+ def decide_interrupt(
+ self,
+ interrupt_id: UUID,
+ *,
+ decision: ApprovalDecision,
+ expected_run_version: int,
+ ) -> Run:
+ with self._transaction() as connection:
+ row = connection.execute(
+ "SELECT * FROM interrupts WHERE id = ?",
+ (str(interrupt_id),),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(interrupt_id))
+ if row["decision_kind"] is not None:
+ raise ConflictError("interrupt was already decided")
+ run_id = UUID(row["run_id"])
+ current = self._run_from_row(self._required_run_row(connection, run_id))
+ if current.version != expected_run_version:
+ raise ConflictError("run version conflict")
+ assert_transition(current.status, RunStatus.QUEUED)
+ decided_at = _now()
+ connection.execute(
+ """
+ UPDATE interrupts
+ SET decision_kind = ?, decision_actor_id = ?,
+ decision_reason = ?, decision_payload_json = ?,
+ decided_at = ?
+ WHERE id = ? AND decision_kind IS NULL
+ """,
+ (
+ decision.kind.value,
+ decision.actor_id,
+ decision.reason,
+ _dump(decision.payload),
+ decided_at.isoformat(),
+ str(interrupt_id),
+ ),
+ )
+ self._update_status(
+ connection,
+ current,
+ target=RunStatus.QUEUED,
+ expected_version=expected_run_version,
+ )
+ self._append_event(
+ connection,
+ run_id,
+ "run.interrupt.decided",
+ {
+ "interrupt_id": str(interrupt_id),
+ "decision": decision.kind.value,
+ "actor_id": decision.actor_id,
+ },
+ )
+ return self._run_from_row(self._required_run_row(connection, run_id))
+
+ def claim_next(
+ self,
+ *,
+ worker_id: str,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ClaimedRun | None:
+ if not worker_id.strip():
+ raise ValueError("worker_id must not be empty")
+ if lease_seconds <= 0:
+ raise ValueError("lease_seconds must be greater than zero")
+ claimed_at = now or _now()
+ if claimed_at.tzinfo is None:
+ raise ValueError("now must be timezone-aware")
+ with self._transaction() as connection:
+ row = connection.execute(
+ """
+ SELECT * FROM runs
+ WHERE status = ?
+ ORDER BY priority DESC, created_at, id
+ LIMIT 1
+ """,
+ (RunStatus.QUEUED.value,),
+ ).fetchone()
+ if row is None:
+ return None
+ current = self._run_from_row(row)
+ assert_transition(current.status, RunStatus.RUNNING)
+ cursor = connection.execute(
+ """
+ UPDATE runs
+ SET status = ?, updated_at = ?, version = version + 1
+ WHERE id = ? AND version = ? AND status = ?
+ """,
+ (
+ RunStatus.RUNNING.value,
+ claimed_at.isoformat(),
+ str(current.id),
+ current.version,
+ RunStatus.QUEUED.value,
+ ),
+ )
+ if cursor.rowcount != 1:
+ raise ConflictError("run claim conflict")
+ previous = connection.execute(
+ "SELECT * FROM run_leases WHERE run_id = ?",
+ (str(current.id),),
+ ).fetchone()
+ lease_id = (
+ UUID(previous["id"])
+ if previous is not None
+ else UUID(
+ bytes=hashlib.sha256(str(current.id).encode("utf-8")).digest()[:16]
+ )
+ )
+ token = int(previous["fencing_token"]) + 1 if previous is not None else 1
+ created_at = (
+ _parse_time(previous["created_at"])
+ if previous is not None
+ else claimed_at
+ )
+ expires_at = claimed_at + timedelta(seconds=lease_seconds)
+ connection.execute(
+ """
+ INSERT INTO run_leases(
+ id, run_id, holder_worker_id, expires_at, fencing_token,
+ active, created_at, updated_at
+ ) VALUES (?, ?, ?, ?, ?, 1, ?, ?)
+ ON CONFLICT(run_id) DO UPDATE SET
+ holder_worker_id = excluded.holder_worker_id,
+ expires_at = excluded.expires_at,
+ fencing_token = excluded.fencing_token,
+ active = 1,
+ updated_at = excluded.updated_at
+ """,
+ (
+ str(lease_id),
+ str(current.id),
+ worker_id,
+ expires_at.isoformat(),
+ token,
+ created_at.isoformat(),
+ claimed_at.isoformat(),
+ ),
+ )
+ self._append_event(
+ connection,
+ current.id,
+ "run.claimed",
+ {"worker_id": worker_id, "fencing_token": token},
+ )
+ run = self._run_from_row(self._required_run_row(connection, current.id))
+ return ClaimedRun(
+ run=run,
+ lease=ResourceLease(
+ id=lease_id,
+ resource_type="run",
+ resource_id=str(current.id),
+ owner_run_id=current.id,
+ holder_worker_id=worker_id,
+ expires_at=expires_at,
+ fencing_token=token,
+ created_at=created_at,
+ updated_at=claimed_at,
+ ),
+ )
+
+ def renew_lease(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ResourceLease:
+ if lease_seconds <= 0:
+ raise ValueError("lease_seconds must be greater than zero")
+ renewed_at = now or _now()
+ expires_at = renewed_at + timedelta(seconds=lease_seconds)
+ with self._transaction() as connection:
+ row = self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ connection.execute(
+ """
+ UPDATE run_leases
+ SET expires_at = ?, updated_at = ?
+ WHERE run_id = ?
+ """,
+ (expires_at.isoformat(), renewed_at.isoformat(), str(run_id)),
+ )
+ return ResourceLease(
+ id=UUID(row["id"]),
+ resource_type="run",
+ resource_id=str(run_id),
+ owner_run_id=run_id,
+ holder_worker_id=worker_id,
+ expires_at=expires_at,
+ fencing_token=fencing_token,
+ created_at=_parse_time(row["created_at"]),
+ updated_at=renewed_at,
+ )
+
+ def assert_fencing_token(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ ) -> None:
+ connection = self._connect()
+ try:
+ self._required_lease(
+ connection,
+ run_id,
+ worker_id=worker_id,
+ fencing_token=fencing_token,
+ )
+ finally:
+ connection.close()
+
+ def requeue_expired_leases(
+ self,
+ *,
+ now: datetime | None = None,
+ ) -> tuple[UUID, ...]:
+ recovered_at = now or _now()
+ with self._transaction() as connection:
+ rows = connection.execute(
+ """
+ SELECT l.*, r.status, r.version
+ FROM run_leases l
+ JOIN runs r ON r.id = l.run_id
+ WHERE l.active = 1 AND l.expires_at <= ?
+ ORDER BY l.expires_at, l.run_id
+ """,
+ (recovered_at.isoformat(),),
+ ).fetchall()
+ recovered: list[UUID] = []
+ for row in rows:
+ run_id = UUID(row["run_id"])
+ if RunStatus(row["status"]) is not RunStatus.RUNNING:
+ connection.execute(
+ "UPDATE run_leases SET active = 0 WHERE run_id = ?",
+ (str(run_id),),
+ )
+ continue
+ connection.execute(
+ """
+ UPDATE runs
+ SET status = ?, updated_at = ?, version = version + 1
+ WHERE id = ? AND version = ?
+ """,
+ (
+ RunStatus.QUEUED.value,
+ recovered_at.isoformat(),
+ str(run_id),
+ int(row["version"]),
+ ),
+ )
+ connection.execute(
+ """
+ UPDATE run_leases
+ SET active = 0, updated_at = ?
+ WHERE run_id = ?
+ """,
+ (recovered_at.isoformat(), str(run_id)),
+ )
+ self._append_event(
+ connection,
+ run_id,
+ "run.lease.expired",
+ {"fencing_token": int(row["fencing_token"])},
+ )
+ recovered.append(run_id)
+ return tuple(recovered)
+
+ def _update_status(
+ self,
+ connection: sqlite3.Connection,
+ current: Run,
+ *,
+ target: RunStatus,
+ expected_version: int,
+ ) -> None:
+ cursor = connection.execute(
+ """
+ UPDATE runs
+ SET status = ?, updated_at = ?, version = version + 1
+ WHERE id = ? AND version = ?
+ """,
+ (
+ target.value,
+ _now().isoformat(),
+ str(current.id),
+ expected_version,
+ ),
+ )
+ if cursor.rowcount != 1:
+ raise ConflictError("run version conflict")
+
+ def _insert_checkpoint(
+ self,
+ connection: sqlite3.Connection,
+ checkpoint: Checkpoint,
+ ) -> None:
+ connection.execute(
+ """
+ INSERT INTO checkpoints(
+ id, run_id, sequence, plan_hash, state_json,
+ next_nodes_json, pending_interrupts_json,
+ effect_watermark, created_at
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(checkpoint.id),
+ str(checkpoint.run_id),
+ checkpoint.sequence,
+ checkpoint.plan_hash,
+ _dump(checkpoint.state),
+ _dump(checkpoint.next_nodes),
+ _dump(tuple(str(item) for item in checkpoint.pending_interrupts)),
+ checkpoint.effect_watermark,
+ checkpoint.created_at.isoformat(),
+ ),
+ )
+
+ def _append_event(
+ self,
+ connection: sqlite3.Connection,
+ run_id: UUID,
+ type: str,
+ data: Mapping[str, object],
+ ) -> RunEvent:
+ row = connection.execute(
+ """
+ SELECT COALESCE(MAX(sequence), 0) AS sequence
+ FROM run_events WHERE run_id = ?
+ """,
+ (str(run_id),),
+ ).fetchone()
+ sequence = int(row["sequence"]) + 1
+ created_at = _now()
+ connection.execute(
+ """
+ INSERT INTO run_events(run_id, sequence, type, data_json, created_at)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (str(run_id), sequence, type, _dump(data), created_at.isoformat()),
+ )
+ return RunEvent(
+ run_id=run_id,
+ sequence=sequence,
+ type=type,
+ data=freeze_json(data, field="run event data"), # type: ignore[arg-type]
+ created_at=created_at,
+ )
+
+ def _required_run_row(
+ self,
+ connection: sqlite3.Connection,
+ run_id: UUID,
+ ) -> sqlite3.Row:
+ row = connection.execute(
+ "SELECT * FROM runs WHERE id = ?",
+ (str(run_id),),
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(run_id))
+ return cast(sqlite3.Row, row)
+
+ def _required_lease(
+ self,
+ connection: sqlite3.Connection,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ ) -> sqlite3.Row:
+ row = connection.execute(
+ "SELECT * FROM run_leases WHERE run_id = ?",
+ (str(run_id),),
+ ).fetchone()
+ if (
+ row is None
+ or not bool(row["active"])
+ or row["holder_worker_id"] != worker_id
+ or int(row["fencing_token"]) != fencing_token
+ or _parse_time(row["expires_at"]) <= _now()
+ ):
+ raise ConflictError("lease fencing token is stale or not owned")
+ return cast(sqlite3.Row, row)
+
+ def _fingerprint(self, run: Run) -> str:
+ payload = _dump(
+ {
+ "plan_id": str(run.plan_id),
+ "revision_id": str(run.revision_id),
+ "session_id": str(run.session_id),
+ "tenant_id": run.tenant_id,
+ "state": run.state,
+ "next_nodes": run.next_nodes,
+ "priority": run.priority,
+ }
+ )
+ return hashlib.sha256(payload.encode("utf-8")).hexdigest()
+
+ def _run_from_row(self, row: sqlite3.Row) -> Run:
+ state = _load(row["state_json"])
+ next_nodes = _load(row["next_nodes_json"])
+ context = _load(row["context_json"])
+ assert isinstance(state, dict)
+ assert isinstance(next_nodes, list)
+ assert isinstance(context, dict)
+ return Run(
+ id=UUID(row["id"]),
+ plan_id=UUID(row["plan_id"]),
+ revision_id=UUID(row["revision_id"]),
+ session_id=UUID(row["session_id"]),
+ tenant_id=row["tenant_id"],
+ status=RunStatus(row["status"]),
+ state=state,
+ next_nodes=tuple(str(item) for item in next_nodes),
+ idempotency_key=row["idempotency_key"],
+ context=context,
+ priority=int(row["priority"]),
+ created_at=_parse_time(row["created_at"]),
+ updated_at=_parse_time(row["updated_at"]),
+ version=int(row["version"]),
+ )
+
+ def _checkpoint_from_row(self, row: sqlite3.Row) -> Checkpoint:
+ state = _load(row["state_json"])
+ next_nodes = _load(row["next_nodes_json"])
+ pending = _load(row["pending_interrupts_json"])
+ assert isinstance(state, dict)
+ assert isinstance(next_nodes, list)
+ assert isinstance(pending, list)
+ return Checkpoint(
+ id=UUID(row["id"]),
+ run_id=UUID(row["run_id"]),
+ sequence=int(row["sequence"]),
+ plan_hash=row["plan_hash"],
+ state=state,
+ next_nodes=tuple(str(item) for item in next_nodes),
+ pending_interrupts=tuple(UUID(str(item)) for item in pending),
+ effect_watermark=int(row["effect_watermark"]),
+ created_at=_parse_time(row["created_at"]),
+ )
+
+ def _interrupt_from_row(self, row: sqlite3.Row) -> Interrupt:
+ request = _load(row["request_json"])
+ assert isinstance(request, dict)
+ decision: ApprovalDecision | None = None
+ if row["decision_kind"] is not None:
+ payload = _load(row["decision_payload_json"])
+ assert isinstance(payload, dict)
+ decision = ApprovalDecision(
+ kind=ApprovalDecisionKind(row["decision_kind"]),
+ actor_id=row["decision_actor_id"],
+ reason=row["decision_reason"],
+ payload=payload,
+ )
+ return Interrupt(
+ id=UUID(row["id"]),
+ run_id=UUID(row["run_id"]),
+ kind=InterruptKind(row["kind"]),
+ request=request,
+ created_at=_parse_time(row["created_at"]),
+ expires_at=(
+ _parse_time(row["expires_at"])
+ if row["expires_at"] is not None
+ else None
+ ),
+ decision=decision,
+ decided_at=(
+ _parse_time(row["decided_at"])
+ if row["decided_at"] is not None
+ else None
+ ),
+ )
diff --git a/src/rath/runtime/store.py b/src/rath/runtime/store.py
new file mode 100644
index 0000000..3279505
--- /dev/null
+++ b/src/rath/runtime/store.py
@@ -0,0 +1,161 @@
+"""Persistence protocol shared by embedded and production Run stores."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from datetime import datetime
+from typing import Protocol, runtime_checkable
+from uuid import UUID
+
+from rath.runtime.models import (
+ ApprovalDecision,
+ Checkpoint,
+ ClaimedRun,
+ Interrupt,
+ ResourceLease,
+ Run,
+ RunEvent,
+ RunStatus,
+)
+
+__all__ = ["RunStore"]
+
+
+@runtime_checkable
+class RunStore(Protocol):
+ def create_run(self, run: Run) -> Run: ...
+
+ def get_run(self, run_id: UUID) -> Run: ...
+
+ def list_runs(
+ self,
+ *,
+ tenant_id: str,
+ after: UUID | None = None,
+ limit: int | None = None,
+ session_id: UUID | None = None,
+ statuses: tuple[RunStatus, ...] | None = None,
+ ) -> tuple[Run, ...]: ...
+
+ def count_runs(
+ self,
+ *,
+ status: RunStatus,
+ tenant_id: str | None = None,
+ ) -> int: ...
+
+ def transition_run(
+ self,
+ run_id: UUID,
+ *,
+ expected_version: int,
+ target: RunStatus,
+ state: Mapping[str, object] | None = None,
+ next_nodes: tuple[str, ...] | None = None,
+ ) -> Run: ...
+
+ def list_run_events(
+ self,
+ run_id: UUID,
+ *,
+ after_sequence: int = 0,
+ limit: int | None = None,
+ ) -> tuple[RunEvent, ...]: ...
+
+ def append_run_event(
+ self,
+ run_id: UUID,
+ type: str,
+ data: Mapping[str, object],
+ ) -> RunEvent: ...
+
+ def append_checkpoint(self, checkpoint: Checkpoint) -> None: ...
+
+ def latest_checkpoint(self, run_id: UUID) -> Checkpoint | None: ...
+
+ def list_checkpoints(self, run_id: UUID) -> tuple[Checkpoint, ...]: ...
+
+ def commit_checkpoint(
+ self,
+ checkpoint: Checkpoint,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ ) -> Run: ...
+
+ def create_interrupt(
+ self,
+ interrupt: Interrupt,
+ *,
+ expected_run_version: int,
+ ) -> Run: ...
+
+ def get_interrupt(self, interrupt_id: UUID) -> Interrupt: ...
+
+ def list_interrupts(
+ self,
+ *,
+ tenant_id: str,
+ pending_only: bool = True,
+ ) -> tuple[Interrupt, ...]: ...
+
+ def expire_interrupts(
+ self,
+ *,
+ now: datetime | None = None,
+ ) -> tuple[UUID, ...]: ...
+
+ def decide_interrupt(
+ self,
+ interrupt_id: UUID,
+ *,
+ decision: ApprovalDecision,
+ expected_run_version: int,
+ ) -> Run: ...
+
+ def claim_next(
+ self,
+ *,
+ worker_id: str,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ClaimedRun | None: ...
+
+ def renew_lease(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ lease_seconds: float,
+ now: datetime | None = None,
+ ) -> ResourceLease: ...
+
+ def assert_fencing_token(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ ) -> None: ...
+
+ def requeue_expired_leases(
+ self,
+ *,
+ now: datetime | None = None,
+ ) -> tuple[UUID, ...]: ...
+
+ def finish_claim(
+ self,
+ run_id: UUID,
+ *,
+ worker_id: str,
+ fencing_token: int,
+ expected_run_version: int,
+ target: RunStatus,
+ event_type: str = "run.execution.completed",
+ event_data: Mapping[str, object] | None = None,
+ ) -> Run: ...
+
+ def close(self) -> None: ...
diff --git a/src/rath/security/__init__.py b/src/rath/security/__init__.py
new file mode 100644
index 0000000..8eca7ba
--- /dev/null
+++ b/src/rath/security/__init__.py
@@ -0,0 +1,59 @@
+"""Public security contracts for identity, policy, secrets, and audit."""
+
+from rath.security.audit import (
+ AuditEvent,
+ AuditKind,
+ AuditSink,
+ InMemoryAuditSink,
+ StructuredAuditSink,
+)
+from rath.security.context import (
+ Principal,
+ PrincipalKind,
+ Provenance,
+ SecurityContext,
+ TrustLevel,
+)
+from rath.security.policy import (
+ Action,
+ ApprovalRequiredError,
+ AuthorizationError,
+ DenyAllPolicy,
+ LocalTrustedPolicy,
+ PolicyConstraints,
+ PolicyDecision,
+ PolicyEffect,
+ PolicyEngine,
+ PolicyEvaluationError,
+ ResourceRef,
+ authorize,
+)
+from rath.security.secrets import ResolvedSecret, SecretRef, SecretResolver
+
+__all__ = [
+ "Action",
+ "ApprovalRequiredError",
+ "AuditEvent",
+ "AuditKind",
+ "AuditSink",
+ "AuthorizationError",
+ "authorize",
+ "DenyAllPolicy",
+ "InMemoryAuditSink",
+ "LocalTrustedPolicy",
+ "PolicyConstraints",
+ "PolicyDecision",
+ "PolicyEffect",
+ "PolicyEngine",
+ "PolicyEvaluationError",
+ "Principal",
+ "PrincipalKind",
+ "Provenance",
+ "ResolvedSecret",
+ "ResourceRef",
+ "SecretRef",
+ "SecretResolver",
+ "SecurityContext",
+ "StructuredAuditSink",
+ "TrustLevel",
+]
diff --git a/src/rath/security/audit.py b/src/rath/security/audit.py
new file mode 100644
index 0000000..1cef910
--- /dev/null
+++ b/src/rath/security/audit.py
@@ -0,0 +1,182 @@
+"""Security audit events kept distinct from diagnostic traces."""
+
+from __future__ import annotations
+
+import json
+import sys
+import threading
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from datetime import datetime, timezone
+from enum import Enum
+from typing import TYPE_CHECKING, Callable, Protocol, runtime_checkable
+from uuid import UUID, uuid4
+
+from rath._json import JSONValue, freeze_mapping
+from rath.security.policy import Action, PolicyDecision, ResourceRef
+
+if TYPE_CHECKING:
+ from rath.context import RunContext
+
+__all__ = [
+ "AuditEvent",
+ "AuditKind",
+ "AuditSink",
+ "InMemoryAuditSink",
+ "StructuredAuditSink",
+]
+
+_SENSITIVE_AUDIT_FIELDS = frozenset(
+ {"api_key", "authorization", "cookie", "password", "secret", "token"}
+)
+
+
+def _redact_audit(value: object) -> object:
+ if isinstance(value, Mapping):
+ return {
+ str(key): (
+ ""
+ if any(part in str(key).lower() for part in _SENSITIVE_AUDIT_FIELDS)
+ else _redact_audit(item)
+ )
+ for key, item in value.items()
+ }
+ if isinstance(value, (list, tuple)):
+ return [_redact_audit(item) for item in value]
+ return value
+
+
+class AuditKind(str, Enum):
+ AUTHENTICATION = "authentication"
+ POLICY_DECISION = "policy_decision"
+ SECRET_RESOLUTION = "secret_resolution"
+ TOOL_ACCESS = "tool_access"
+ SANDBOX_ACCESS = "sandbox_access"
+ MEMORY_ACCESS = "memory_access"
+ RUN_CONTROL = "run_control"
+ OPERATOR_OVERRIDE = "operator_override"
+
+
+@dataclass(frozen=True, slots=True)
+class AuditEvent:
+ id: UUID
+ kind: AuditKind
+ occurred_at: datetime
+ tenant_id: str
+ principal_id: str
+ request_id: UUID
+ trace_id: str
+ action: str
+ resource_kind: str
+ resource_id: str
+ outcome: str
+ reason: str
+ policy_id: str | None = None
+ attributes: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ if self.occurred_at.tzinfo is None:
+ raise ValueError("audit occurred_at must be timezone-aware")
+ object.__setattr__(
+ self,
+ "attributes",
+ freeze_mapping(self.attributes, field="audit.attributes"),
+ )
+
+ @classmethod
+ def for_policy_decision(
+ cls,
+ *,
+ kind: AuditKind,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+ decision: PolicyDecision,
+ attributes: Mapping[str, object] | None = None,
+ ) -> "AuditEvent":
+ return cls(
+ id=uuid4(),
+ kind=kind,
+ occurred_at=datetime.now(timezone.utc),
+ tenant_id=context.security.tenant_id,
+ principal_id=context.security.principal.id,
+ request_id=context.request_id,
+ trace_id=context.trace_context.trace_id,
+ action=action.name,
+ resource_kind=resource.kind,
+ resource_id=resource.id,
+ outcome=decision.effect.value,
+ reason=decision.reason,
+ policy_id=decision.policy_id,
+ attributes=freeze_mapping(attributes, field="audit.attributes"),
+ )
+
+
+@runtime_checkable
+class AuditSink(Protocol):
+ async def emit(self, event: AuditEvent) -> None: ...
+
+
+class InMemoryAuditSink:
+ """Deterministic reference sink for embedded mode and contract tests."""
+
+ def __init__(self) -> None:
+ self._events: list[AuditEvent] = []
+ self._lock = threading.Lock()
+
+ @property
+ def events(self) -> tuple[AuditEvent, ...]:
+ with self._lock:
+ return tuple(self._events)
+
+ async def emit(self, event: AuditEvent) -> None:
+ with self._lock:
+ self._events.append(event)
+
+
+class StructuredAuditSink:
+ """Emit redacted, newline-delimited JSON security audit records.
+
+ The default sink writes and flushes stdout so container log collectors can
+ retain the security stream independently from diagnostic traces. Sink
+ failures deliberately propagate: a production reference deployment must
+ not silently discard an audit record.
+ """
+
+ def __init__(self, sink: Callable[[str], None] | None = None) -> None:
+ self._sink = sink or self._write_stdout
+
+ @staticmethod
+ def _write_stdout(line: str) -> None:
+ sys.stdout.write(line + "\n")
+ sys.stdout.flush()
+
+ async def emit(self, event: AuditEvent) -> None:
+ record: dict[str, object] = {
+ "schema": "openrath.security-audit/1",
+ "id": str(event.id),
+ "kind": event.kind.value,
+ "occurred_at": event.occurred_at.isoformat(),
+ "tenant_id": event.tenant_id,
+ "principal_id": event.principal_id,
+ "request_id": str(event.request_id),
+ "trace_id": event.trace_id,
+ "action": event.action,
+ "resource_kind": event.resource_kind,
+ "resource_id": event.resource_id,
+ "outcome": event.outcome,
+ "reason": event.reason,
+ "policy_id": event.policy_id,
+ "attributes": dict(event.attributes),
+ }
+ safe = _redact_audit(record)
+ assert isinstance(safe, dict)
+ self._sink(
+ json.dumps(
+ safe,
+ ensure_ascii=False,
+ sort_keys=True,
+ separators=(",", ":"),
+ default=str,
+ )
+ )
diff --git a/src/rath/security/context.py b/src/rath/security/context.py
new file mode 100644
index 0000000..57ffd3c
--- /dev/null
+++ b/src/rath/security/context.py
@@ -0,0 +1,135 @@
+"""Identity, tenancy, trust, and provenance contracts."""
+
+from __future__ import annotations
+
+from collections.abc import Iterable, Mapping
+from dataclasses import dataclass, field
+from enum import Enum
+
+from rath._json import JSONValue, freeze_mapping
+
+__all__ = [
+ "Principal",
+ "PrincipalKind",
+ "Provenance",
+ "SecurityContext",
+ "TrustLevel",
+]
+
+
+class PrincipalKind(str, Enum):
+ USER = "user"
+ SERVICE = "service"
+ SYSTEM = "system"
+
+
+class TrustLevel(str, Enum):
+ UNTRUSTED = "untrusted"
+ TRUSTED = "trusted"
+ SYSTEM = "system"
+
+
+def _required(value: str, *, field_name: str) -> str:
+ normalized = value.strip()
+ if not normalized:
+ raise ValueError(f"{field_name} must not be empty")
+ return normalized
+
+
+@dataclass(frozen=True, slots=True)
+class Principal:
+ """Authenticated caller identity detached from transport concerns."""
+
+ id: str
+ kind: PrincipalKind
+ claims: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(self, "id", _required(self.id, field_name="principal.id"))
+ object.__setattr__(
+ self,
+ "claims",
+ freeze_mapping(self.claims, field="principal.claims"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class SecurityContext:
+ """Run-scoped identity and tenant boundary."""
+
+ principal: Principal
+ tenant_id: str
+ project_id: str | None = None
+ grants: frozenset[str] = field(default_factory=frozenset)
+ attributes: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "tenant_id",
+ _required(self.tenant_id, field_name="tenant_id"),
+ )
+ if self.project_id is not None:
+ object.__setattr__(
+ self,
+ "project_id",
+ _required(self.project_id, field_name="project_id"),
+ )
+ object.__setattr__(
+ self,
+ "grants",
+ frozenset(_required(item, field_name="grant") for item in self.grants),
+ )
+ object.__setattr__(
+ self,
+ "attributes",
+ freeze_mapping(self.attributes, field="security.attributes"),
+ )
+
+ @classmethod
+ def local(
+ cls,
+ *,
+ grants: Iterable[str] = ("trusted_host",),
+ ) -> "SecurityContext":
+ """Create the explicit trusted-process context for embedded local mode."""
+ return cls(
+ principal=Principal(
+ id="local-process",
+ kind=PrincipalKind.SYSTEM,
+ claims={"mode": "embedded"},
+ ),
+ tenant_id="local",
+ grants=frozenset(grants),
+ attributes={"deployment_mode": "embedded"},
+ )
+
+ def has_grant(self, grant: str) -> bool:
+ return grant in self.grants
+
+
+@dataclass(frozen=True, slots=True)
+class Provenance:
+ """Origin metadata carried by untrusted and trusted content."""
+
+ source_type: str
+ source_id: str
+ producer: str | None = None
+ metadata: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "source_type",
+ _required(self.source_type, field_name="source_type"),
+ )
+ object.__setattr__(
+ self,
+ "source_id",
+ _required(self.source_id, field_name="source_id"),
+ )
+ object.__setattr__(
+ self,
+ "metadata",
+ freeze_mapping(self.metadata, field="provenance.metadata"),
+ )
diff --git a/src/rath/security/policy.py b/src/rath/security/policy.py
new file mode 100644
index 0000000..6b392ad
--- /dev/null
+++ b/src/rath/security/policy.py
@@ -0,0 +1,226 @@
+"""Fail-closed authorization contracts and reference policies."""
+
+from __future__ import annotations
+
+from collections.abc import Mapping
+from dataclasses import dataclass, field
+from enum import Enum
+from typing import TYPE_CHECKING, Protocol, runtime_checkable
+
+from rath._json import JSONValue, freeze_mapping
+from rath.errors import ErrorCode, RathError
+
+if TYPE_CHECKING:
+ from rath.context import RunContext
+
+__all__ = [
+ "Action",
+ "ApprovalRequiredError",
+ "AuthorizationError",
+ "DenyAllPolicy",
+ "LocalTrustedPolicy",
+ "PolicyConstraints",
+ "PolicyDecision",
+ "PolicyEffect",
+ "PolicyEngine",
+ "PolicyEvaluationError",
+ "ResourceRef",
+ "authorize",
+]
+
+
+def _required(value: str, *, field_name: str) -> str:
+ normalized = value.strip()
+ if not normalized:
+ raise ValueError(f"{field_name} must not be empty")
+ return normalized
+
+
+@dataclass(frozen=True, slots=True)
+class Action:
+ name: str
+
+ def __post_init__(self) -> None:
+ object.__setattr__(self, "name", _required(self.name, field_name="action"))
+
+ def __str__(self) -> str:
+ return self.name
+
+
+@dataclass(frozen=True, slots=True)
+class ResourceRef:
+ kind: str
+ id: str
+ tenant_id: str | None = None
+ attributes: Mapping[str, JSONValue] = field(default_factory=dict)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "kind",
+ _required(self.kind, field_name="resource.kind"),
+ )
+ object.__setattr__(
+ self,
+ "id",
+ _required(self.id, field_name="resource.id"),
+ )
+ object.__setattr__(
+ self,
+ "attributes",
+ freeze_mapping(self.attributes, field="resource.attributes"),
+ )
+
+
+@dataclass(frozen=True, slots=True)
+class PolicyConstraints:
+ timeout_seconds: float | None = None
+ max_output_bytes: int | None = None
+ allowed_network_hosts: frozenset[str] = field(default_factory=frozenset)
+ filesystem_root: str | None = None
+ read_only: bool = False
+ redactions: frozenset[str] = field(default_factory=frozenset)
+
+ def __post_init__(self) -> None:
+ if self.timeout_seconds is not None and self.timeout_seconds <= 0:
+ raise ValueError("timeout_seconds must be greater than zero")
+ if self.max_output_bytes is not None and self.max_output_bytes <= 0:
+ raise ValueError("max_output_bytes must be greater than zero")
+ object.__setattr__(
+ self,
+ "allowed_network_hosts",
+ frozenset(host.lower() for host in self.allowed_network_hosts),
+ )
+ object.__setattr__(self, "redactions", frozenset(self.redactions))
+
+
+class PolicyEffect(str, Enum):
+ ALLOW = "allow"
+ DENY = "deny"
+ REQUIRE_APPROVAL = "require_approval"
+ ALLOW_WITH_CONSTRAINTS = "allow_with_constraints"
+
+
+@dataclass(frozen=True, slots=True)
+class PolicyDecision:
+ effect: PolicyEffect
+ reason: str
+ policy_id: str
+ constraints: PolicyConstraints = field(default_factory=PolicyConstraints)
+
+ def __post_init__(self) -> None:
+ object.__setattr__(
+ self,
+ "reason",
+ _required(self.reason, field_name="policy reason"),
+ )
+ object.__setattr__(
+ self,
+ "policy_id",
+ _required(self.policy_id, field_name="policy_id"),
+ )
+
+
+@runtime_checkable
+class PolicyEngine(Protocol):
+ async def evaluate(
+ self,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+ ) -> PolicyDecision: ...
+
+
+class AuthorizationError(RathError):
+ def __init__(self, decision: PolicyDecision) -> None:
+ super().__init__(
+ ErrorCode.FORBIDDEN,
+ decision.reason,
+ retryable=False,
+ details={
+ "effect": decision.effect.value,
+ "policy_id": decision.policy_id,
+ },
+ )
+ self.decision = decision
+
+
+class ApprovalRequiredError(RathError):
+ def __init__(self, decision: PolicyDecision) -> None:
+ super().__init__(
+ ErrorCode.APPROVAL_REQUIRED,
+ decision.reason,
+ retryable=False,
+ details={"policy_id": decision.policy_id},
+ )
+ self.decision = decision
+
+
+class PolicyEvaluationError(RathError):
+ def __init__(self) -> None:
+ super().__init__(
+ ErrorCode.POLICY_ERROR,
+ "policy evaluation failed closed",
+ retryable=False,
+ )
+
+
+class DenyAllPolicy:
+ """Safe default for service and untrusted deployment profiles."""
+
+ async def evaluate(
+ self,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+ ) -> PolicyDecision:
+ return PolicyDecision(
+ effect=PolicyEffect.DENY,
+ reason="no policy grant allows this action",
+ policy_id="deny-all",
+ )
+
+
+class LocalTrustedPolicy:
+ """Explicit opt-in policy for the embedded trusted-process profile."""
+
+ async def evaluate(
+ self,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+ ) -> PolicyDecision:
+ allowed = context.security.tenant_id == "local" and context.security.has_grant(
+ "trusted_host"
+ )
+ return PolicyDecision(
+ effect=PolicyEffect.ALLOW if allowed else PolicyEffect.DENY,
+ reason=(
+ "explicit embedded trusted-host context"
+ if allowed
+ else "trusted-host policy is restricted to embedded local context"
+ ),
+ policy_id="local-trusted",
+ )
+
+
+async def authorize(
+ engine: PolicyEngine,
+ *,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+) -> PolicyDecision:
+ """Evaluate a policy and turn non-allow effects into stable exceptions."""
+ context.ensure_active()
+ try:
+ decision = await engine.evaluate(action, resource, context)
+ except RathError:
+ raise
+ except Exception as exc:
+ raise PolicyEvaluationError() from exc
+ if decision.effect is PolicyEffect.DENY:
+ raise AuthorizationError(decision)
+ if decision.effect is PolicyEffect.REQUIRE_APPROVAL:
+ raise ApprovalRequiredError(decision)
+ return decision
diff --git a/src/rath/security/secrets.py b/src/rath/security/secrets.py
new file mode 100644
index 0000000..5d25775
--- /dev/null
+++ b/src/rath/security/secrets.py
@@ -0,0 +1,64 @@
+"""Secret references and explicit resolution boundaries."""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import TYPE_CHECKING, Protocol, runtime_checkable
+
+if TYPE_CHECKING:
+ from rath.context import RunContext
+
+__all__ = [
+ "ResolvedSecret",
+ "SecretRef",
+ "SecretResolver",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class SecretRef:
+ provider: str
+ key: str
+ version: str | None = None
+
+ def __post_init__(self) -> None:
+ if not self.provider.strip():
+ raise ValueError("secret provider must not be empty")
+ if not self.key.strip():
+ raise ValueError("secret key must not be empty")
+
+ def __str__(self) -> str:
+ version = f"@{self.version}" if self.version else ""
+ return f"{self.provider}:{self.key}{version}"
+
+
+@dataclass(frozen=True, slots=True, repr=False)
+class ResolvedSecret:
+ """Short-lived secret value whose representation is always redacted."""
+
+ ref: SecretRef
+ value: str
+
+ def __post_init__(self) -> None:
+ if not self.value:
+ raise ValueError("resolved secret value must not be empty")
+
+ def __repr__(self) -> str:
+ return f"ResolvedSecret(ref={self.ref!s}, value=)"
+
+ def __str__(self) -> str:
+ return f""
+
+ def reveal(self) -> str:
+ """Return the value at the adapter boundary; callers must not log it."""
+ return self.value
+
+
+@runtime_checkable
+class SecretResolver(Protocol):
+ async def resolve(
+ self,
+ ref: SecretRef,
+ *,
+ context: RunContext,
+ ) -> ResolvedSecret: ...
diff --git a/src/rath/server/__init__.py b/src/rath/server/__init__.py
new file mode 100644
index 0000000..a574b85
--- /dev/null
+++ b/src/rath/server/__init__.py
@@ -0,0 +1,25 @@
+from rath.server.app import AgentServer, create_app
+from rath.server.auth import AuthProvider, StaticTokenAuth
+from rath.server.resources import (
+ AssistantRecord,
+ FeedbackRecord,
+ InMemoryResourceStore,
+ PostgresResourceStore,
+ ResourceStore,
+ SessionRecord,
+ SQLiteResourceStore,
+)
+
+__all__ = [
+ "AgentServer",
+ "AuthProvider",
+ "AssistantRecord",
+ "FeedbackRecord",
+ "InMemoryResourceStore",
+ "PostgresResourceStore",
+ "ResourceStore",
+ "SQLiteResourceStore",
+ "SessionRecord",
+ "StaticTokenAuth",
+ "create_app",
+]
diff --git a/src/rath/server/app.py b/src/rath/server/app.py
new file mode 100644
index 0000000..2b53c1b
--- /dev/null
+++ b/src/rath/server/app.py
@@ -0,0 +1,1698 @@
+"""Starlette Agent Server exposing durable Run resources and SSE replay."""
+
+from __future__ import annotations
+
+import asyncio
+import json
+from collections.abc import AsyncIterator, Mapping
+from contextlib import asynccontextmanager
+from dataclasses import dataclass
+from datetime import datetime, timezone
+from importlib.metadata import PackageNotFoundError, version
+from typing import Any, cast
+from uuid import UUID, uuid4
+
+from starlette.applications import Starlette
+from starlette.middleware.base import BaseHTTPMiddleware
+from starlette.requests import Request
+from starlette.responses import JSONResponse, Response, StreamingResponse
+from starlette.routing import Route
+
+from rath._json import JSONValue, thaw_json
+from rath.adapters import (
+ AdapterRequestContext,
+ MemoryExecutor,
+ MemoryHandler,
+ MemoryNamespace,
+)
+from rath.context import RunContext
+from rath.errors import ErrorCode, RathError
+from rath.runtime import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Interrupt,
+ LocalRuntime,
+ Run,
+ RunSignal,
+ RunStatus,
+ RunStore,
+ SignalBus,
+ SignalKind,
+)
+from rath.security import (
+ AuditEvent,
+ AuditKind,
+ AuditSink,
+ PolicyConstraints,
+ SecurityContext,
+ TrustLevel,
+)
+from rath.server.auth import AuthProvider
+from rath.server.authorization import allows, project_allows
+from rath.server.resources import ResourceStore, default_resource_store
+
+__all__ = ["AgentServer", "create_app"]
+
+
+class _SecurityHeadersMiddleware(BaseHTTPMiddleware):
+ async def dispatch(self, request: Request, call_next: Any) -> Response:
+ requested = request.headers.get("x-request-id")
+ try:
+ request_id = str(UUID(requested)) if requested else str(uuid4())
+ except ValueError:
+ request_id = str(uuid4())
+ request.state.request_id = request_id
+ response = await call_next(request)
+ response.headers["X-Request-ID"] = request_id
+ response.headers["X-Content-Type-Options"] = "nosniff"
+ response.headers["X-Frame-Options"] = "DENY"
+ response.headers["Referrer-Policy"] = "no-referrer"
+ response.headers["Cache-Control"] = response.headers.get(
+ "Cache-Control", "no-store"
+ )
+ return cast(Response, response)
+
+
+def _run_json(run: Run) -> dict[str, object]:
+ context = thaw_json(run.context)
+ correlation = context if isinstance(context, dict) else {}
+ return {
+ "id": str(run.id),
+ "plan_id": str(run.plan_id),
+ "revision_id": str(run.revision_id),
+ "session_id": str(run.session_id),
+ "tenant_id": run.tenant_id,
+ "status": run.status.value,
+ "state": thaw_json(run.state),
+ "next_nodes": list(run.next_nodes),
+ "version": run.version,
+ "priority": run.priority,
+ "request_id": correlation.get("request_id"),
+ "trace_id": correlation.get("trace_id"),
+ "created_at": run.created_at.isoformat(),
+ "updated_at": run.updated_at.isoformat(),
+ }
+
+
+def _interrupt_json(value: Interrupt) -> dict[str, object]:
+ return {
+ "id": str(value.id),
+ "run_id": str(value.run_id),
+ "kind": value.kind.value,
+ "request": thaw_json(value.request),
+ "created_at": value.created_at.isoformat(),
+ "expires_at": (
+ value.expires_at.isoformat() if value.expires_at is not None else None
+ ),
+ "decision": (
+ {
+ "kind": value.decision.kind.value,
+ "actor_id": value.decision.actor_id,
+ "reason": value.decision.reason,
+ "payload": thaw_json(value.decision.payload),
+ }
+ if value.decision is not None
+ else None
+ ),
+ "decided_at": (
+ value.decided_at.isoformat() if value.decided_at is not None else None
+ ),
+ }
+
+
+@dataclass(frozen=True, slots=True)
+class _Assistant:
+ id: str
+ workflow: object
+ revision_id: UUID
+
+
+def _openapi_document(
+ package_version: str, *, store_enabled: bool
+) -> dict[str, object]:
+ secured: list[dict[str, list[object]]] = [{"bearerAuth": []}]
+ error_content = {
+ "application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}
+ }
+
+ def operation(
+ operation_id: str,
+ summary: str,
+ *,
+ action: str | None = None,
+ success: str = "200",
+ response_schema: str | None = None,
+ request_schema: str | None = None,
+ parameters: list[dict[str, object]] | None = None,
+ media_type: str = "application/json",
+ ) -> dict[str, object]:
+ success_schema: dict[str, object] = (
+ {"$ref": f"#/components/schemas/{response_schema}"}
+ if response_schema
+ else {"type": "object"}
+ )
+ value: dict[str, object] = {
+ "operationId": operation_id,
+ "summary": summary,
+ "x-openrath-stability": "beta",
+ "x-openrath-action": action,
+ "security": secured if action is not None else [],
+ "responses": {
+ success: {
+ "description": "Success",
+ "content": {media_type: {"schema": success_schema}},
+ },
+ "400": {"description": "Invalid request", "content": error_content},
+ "401": {"description": "Unauthenticated", "content": error_content},
+ "403": {"description": "Forbidden", "content": error_content},
+ "404": {"description": "Not found", "content": error_content},
+ "409": {"description": "Conflict", "content": error_content},
+ "429": {"description": "Resource exhausted", "content": error_content},
+ },
+ }
+ if request_schema is not None:
+ value["requestBody"] = {
+ "required": True,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": f"#/components/schemas/{request_schema}",
+ }
+ }
+ },
+ }
+ if parameters:
+ value["parameters"] = parameters
+ return value
+
+ def path_parameter(name: str) -> dict[str, object]:
+ schema: dict[str, object] = {"type": "string"}
+ if name in {"session_id", "run_id", "interrupt_id"}:
+ schema["format"] = "uuid"
+ return {
+ "name": name,
+ "in": "path",
+ "required": True,
+ "schema": schema,
+ }
+
+ cursor_parameters = [
+ {
+ "name": "after",
+ "in": "query",
+ "required": False,
+ "schema": {"type": "string"},
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "required": False,
+ "schema": {"type": "integer", "minimum": 1, "maximum": 200},
+ },
+ ]
+ paths: dict[str, object] = {
+ "/health/live": {
+ "get": operation("live", "Process liveness", response_schema="Health")
+ },
+ "/health/ready": {
+ "get": operation("ready", "Dependency readiness", response_schema="Health")
+ },
+ "/info": {
+ "get": operation("info", "Server capabilities", response_schema="Info")
+ },
+ "/metrics": {
+ "get": operation(
+ "metrics",
+ "Prometheus metrics",
+ action="metrics.read",
+ media_type="text/plain",
+ )
+ },
+ "/v1/assistants": {
+ "get": operation(
+ "listAssistants",
+ "List deployment templates and tenant aliases",
+ action="assistant.read",
+ response_schema="ItemPage",
+ ),
+ "post": operation(
+ "createAssistantAlias",
+ "Create a tenant assistant alias",
+ action="assistant.create",
+ success="201",
+ request_schema="CreateAssistantRequest",
+ response_schema="Assistant",
+ ),
+ },
+ "/v1/assistants/{assistant_id}": {
+ "get": operation(
+ "getAssistant",
+ "Get an assistant template or alias",
+ action="assistant.read",
+ response_schema="Assistant",
+ parameters=[path_parameter("assistant_id")],
+ )
+ },
+ "/v1/sessions": {
+ "post": operation(
+ "createSession",
+ "Create a durable session",
+ action="session.create",
+ success="201",
+ response_schema="Session",
+ )
+ },
+ "/v1/sessions/{session_id}": {
+ "get": operation(
+ "getSession",
+ "Get a durable session",
+ action="session.read",
+ response_schema="Session",
+ parameters=[path_parameter("session_id")],
+ )
+ },
+ "/v1/sessions/{session_id}/runs": {
+ "post": operation(
+ "createSessionRun",
+ "Create a run in an existing session",
+ action="run.create",
+ success="201",
+ request_schema="CreateSessionRunRequest",
+ response_schema="Run",
+ parameters=[path_parameter("session_id")],
+ )
+ },
+ "/v1/runs": {
+ "get": operation(
+ "listRuns",
+ "List runs by cursor",
+ action="run.read",
+ response_schema="ItemPage",
+ parameters=cursor_parameters,
+ ),
+ "post": operation(
+ "createRun",
+ "Create a durable run",
+ action="run.create",
+ success="201",
+ request_schema="CreateRunRequest",
+ response_schema="Run",
+ ),
+ },
+ "/v1/runs/{run_id}": {
+ "get": operation(
+ "getRun",
+ "Get a durable run",
+ action="run.read",
+ response_schema="Run",
+ parameters=[path_parameter("run_id")],
+ )
+ },
+ "/v1/runs/{run_id}/cancel": {
+ "post": operation(
+ "cancelRun",
+ "Cancel a run",
+ action="run.cancel",
+ response_schema="Run",
+ parameters=[path_parameter("run_id")],
+ )
+ },
+ "/v1/runs/{run_id}/resume": {
+ "post": operation(
+ "resumeRun",
+ "Resume a run requiring operator review",
+ action="run.resume",
+ request_schema="ResumeRunRequest",
+ response_schema="Run",
+ parameters=[path_parameter("run_id")],
+ )
+ },
+ "/v1/runs/{run_id}/events": {
+ "get": operation(
+ "listRunEvents",
+ "Replay ordered durable run events",
+ action="run.read",
+ response_schema="ItemPage",
+ parameters=[path_parameter("run_id"), *cursor_parameters],
+ )
+ },
+ "/v1/runs/{run_id}/stream": {
+ "get": operation(
+ "streamRunEvents",
+ "Stream ordered run events with cursor resume",
+ action="run.read",
+ media_type="text/event-stream",
+ parameters=[path_parameter("run_id"), *cursor_parameters],
+ )
+ },
+ "/v1/interrupts": {
+ "get": operation(
+ "listInterrupts",
+ "List pending durable interrupts",
+ action="interrupt.read",
+ response_schema="ItemPage",
+ parameters=cursor_parameters,
+ )
+ },
+ "/v1/interrupts/{interrupt_id}/decision": {
+ "post": operation(
+ "decideInterrupt",
+ "Submit a durable interrupt decision",
+ action="interrupt.decide",
+ request_schema="InterruptDecisionRequest",
+ response_schema="Run",
+ parameters=[path_parameter("interrupt_id")],
+ )
+ },
+ "/v1/feedback": {
+ "post": operation(
+ "createFeedback",
+ "Create run feedback",
+ action="feedback.create",
+ success="201",
+ request_schema="FeedbackRequest",
+ response_schema="Feedback",
+ )
+ },
+ }
+ if store_enabled:
+ paths.update(
+ {
+ "/v1/store/items": {
+ "post": operation(
+ "putStoreItem",
+ "Write a governed memory item",
+ action="memory.put",
+ request_schema="MemoryRequest",
+ ),
+ "delete": operation(
+ "deleteStoreItem",
+ "Delete a governed memory item",
+ action="memory.delete",
+ request_schema="MemoryRequest",
+ ),
+ },
+ "/v1/store/search": {
+ "post": operation(
+ "searchStore",
+ "Search governed memory",
+ action="memory.search",
+ request_schema="MemoryRequest",
+ )
+ },
+ }
+ )
+ identifier = {"type": "string", "format": "uuid"}
+ schemas: dict[str, object] = {
+ "Health": {
+ "type": "object",
+ "required": ["status"],
+ "properties": {"status": {"type": "string"}},
+ },
+ "Info": {"type": "object", "additionalProperties": True},
+ "ErrorResponse": {
+ "type": "object",
+ "required": ["error"],
+ "properties": {
+ "error": {
+ "type": "object",
+ "required": ["code", "message"],
+ "properties": {
+ "code": {"type": "string"},
+ "message": {"type": "string"},
+ },
+ }
+ },
+ },
+ "Assistant": {
+ "type": "object",
+ "required": ["id", "template_id", "revision_id", "kind"],
+ "properties": {
+ "id": {"type": "string"},
+ "template_id": {"type": "string"},
+ "revision_id": identifier,
+ "kind": {"type": "string", "enum": ["template", "alias"]},
+ },
+ },
+ "Session": {
+ "type": "object",
+ "required": ["id", "tenant_id", "created_at"],
+ "properties": {
+ "id": identifier,
+ "tenant_id": {"type": "string"},
+ "created_at": {"type": "string", "format": "date-time"},
+ "runs": {
+ "type": "array",
+ "items": {"$ref": "#/components/schemas/Run"},
+ },
+ },
+ },
+ "Run": {
+ "type": "object",
+ "required": [
+ "id",
+ "plan_id",
+ "revision_id",
+ "session_id",
+ "status",
+ "version",
+ ],
+ "properties": {
+ "id": identifier,
+ "plan_id": identifier,
+ "revision_id": identifier,
+ "session_id": identifier,
+ "status": {
+ "type": "string",
+ "enum": [item.value for item in RunStatus],
+ },
+ "state": {"type": "object"},
+ "next_nodes": {"type": "array", "items": {"type": "string"}},
+ "version": {"type": "integer", "minimum": 0},
+ },
+ },
+ "Feedback": {"type": "object", "additionalProperties": True},
+ "ItemPage": {
+ "type": "object",
+ "required": ["items", "next"],
+ "properties": {
+ "items": {"type": "array", "items": {}},
+ "next": {"type": ["string", "null"]},
+ },
+ },
+ "CreateAssistantRequest": {
+ "type": "object",
+ "required": ["id", "template_id"],
+ "properties": {
+ "id": {"type": "string"},
+ "template_id": {"type": "string"},
+ },
+ "additionalProperties": False,
+ },
+ "CreateRunRequest": {
+ "type": "object",
+ "required": ["assistant_id", "session_id"],
+ "properties": {
+ "assistant_id": {"type": "string"},
+ "session_id": identifier,
+ "state": {"type": "object"},
+ "priority": {"type": "integer"},
+ },
+ "additionalProperties": False,
+ },
+ "CreateSessionRunRequest": {
+ "type": "object",
+ "required": ["assistant_id"],
+ "properties": {
+ "assistant_id": {"type": "string"},
+ "state": {"type": "object"},
+ "priority": {"type": "integer"},
+ },
+ "additionalProperties": False,
+ },
+ "ResumeRunRequest": {
+ "type": "object",
+ "required": ["confirm"],
+ "properties": {"confirm": {"const": True}},
+ "additionalProperties": False,
+ },
+ "InterruptDecisionRequest": {
+ "type": "object",
+ "required": ["kind", "reason"],
+ "properties": {
+ "kind": {"type": "string", "enum": ["approve", "edit", "reject"]},
+ "reason": {"type": "string"},
+ "payload": {"type": "object"},
+ },
+ "additionalProperties": False,
+ },
+ "FeedbackRequest": {
+ "type": "object",
+ "required": ["run_id", "key"],
+ "properties": {
+ "run_id": identifier,
+ "key": {"type": "string"},
+ "score": {"type": ["number", "null"], "minimum": -1, "maximum": 1},
+ "value": {"type": ["string", "null"]},
+ },
+ "additionalProperties": False,
+ },
+ "MemoryRequest": {
+ "type": "object",
+ "properties": {
+ "tenant_id": {"type": "string"},
+ "user_id": {"type": "string"},
+ "agent_id": {"type": "string"},
+ "session_id": {"type": "string"},
+ "payload": {"type": "object"},
+ },
+ "additionalProperties": False,
+ },
+ }
+ return {
+ "openapi": "3.1.0",
+ "info": {
+ "title": "OpenRath Agent Server",
+ "version": package_version,
+ "description": "Beta v2 durable Agent Server API.",
+ },
+ "paths": paths,
+ "components": {
+ "securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer"}},
+ "schemas": schemas,
+ },
+ }
+
+
+class AgentServer:
+ def __init__(
+ self,
+ store: RunStore,
+ runtime: LocalRuntime,
+ *,
+ auth: AuthProvider,
+ resources: ResourceStore | None = None,
+ embedded_worker: bool = False,
+ worker_id: str = "agent-server",
+ signals: SignalBus | None = None,
+ worker_lease_seconds: float = 30.0,
+ max_queued_runs_per_tenant: int = 1000,
+ memory_executor: MemoryExecutor | None = None,
+ memory_handler: MemoryHandler | None = None,
+ audit_sink: AuditSink | None = None,
+ ) -> None:
+ self.store = store
+ self.runtime = runtime
+ # Agent Server is the durable service profile. It must reject timeout
+ # declarations that cannot be enforced before an assistant is exposed.
+ self.runtime.production_mode = True
+ self.auth = auth
+ self.assistants: dict[str, _Assistant] = {}
+ self.resources = resources or default_resource_store(store)
+ self.embedded_worker = embedded_worker
+ self.worker_id = worker_id
+ self.signals = signals
+ if worker_lease_seconds <= 0:
+ raise ValueError("worker_lease_seconds must be positive")
+ self.worker_lease_seconds = worker_lease_seconds
+ if max_queued_runs_per_tenant < 1:
+ raise ValueError("max_queued_runs_per_tenant must be positive")
+ self.max_queued_runs_per_tenant = max_queued_runs_per_tenant
+ if (memory_executor is None) != (memory_handler is None):
+ raise ValueError(
+ "memory_executor and memory_handler must be configured together"
+ )
+ self.memory_executor = memory_executor
+ self.memory_handler = memory_handler
+ self.audit_sink = audit_sink
+ self.app = create_app(self)
+
+ def register_assistant(
+ self,
+ assistant_id: str,
+ workflow: object,
+ *,
+ revision_id: UUID,
+ ) -> None:
+ if not assistant_id:
+ raise ValueError("assistant_id is required")
+ self.runtime.register(workflow, revision_id=revision_id)
+ self.assistants[assistant_id] = _Assistant(
+ id=assistant_id,
+ workflow=workflow,
+ revision_id=revision_id,
+ )
+
+
+def create_app(server: AgentServer) -> Starlette:
+ try:
+ package_version = version("openrath")
+ except PackageNotFoundError:
+ package_version = "0+unknown"
+
+ def error_response(code: str, message: str, status: int) -> JSONResponse:
+ return JSONResponse(
+ {"error": {"code": code, "message": message}}, status_code=status
+ )
+
+ async def audit_action(
+ request: Request,
+ context: SecurityContext,
+ *,
+ kind: AuditKind,
+ action: str,
+ resource_kind: str,
+ resource_id: str,
+ ) -> None:
+ if server.audit_sink is None:
+ return
+ request_id = UUID(str(request.state.request_id))
+ await server.audit_sink.emit(
+ AuditEvent(
+ id=uuid4(),
+ kind=kind,
+ occurred_at=datetime.now(timezone.utc),
+ tenant_id=context.tenant_id,
+ principal_id=context.principal.id,
+ request_id=request_id,
+ trace_id=request_id.hex,
+ action=action,
+ resource_kind=resource_kind,
+ resource_id=resource_id,
+ outcome="allowed",
+ reason="endpoint action grant and object scope validated",
+ attributes={
+ "project_id": context.project_id,
+ },
+ )
+ )
+
+ async def json_body(request: Request) -> dict[str, object]:
+ maximum = 1024 * 1024
+ content_length = request.headers.get("content-length")
+ if content_length is not None and int(content_length) > maximum:
+ raise ValueError("request body exceeds 1 MiB")
+ body = bytearray()
+ async for chunk in request.stream():
+ body.extend(chunk)
+ if len(body) > maximum:
+ raise ValueError("request body exceeds 1 MiB")
+ value = json.loads(body or b"{}")
+ if not isinstance(value, dict):
+ raise ValueError("request body must be a JSON object")
+ return value
+
+ async def authenticate(
+ request: Request,
+ action: str | None = None,
+ ) -> tuple[SecurityContext | None, JSONResponse | None]:
+ context = await server.auth.authenticate(request.headers.get("authorization"))
+ if context is None:
+ return None, JSONResponse(
+ {
+ "error": {
+ "code": "security.unauthenticated",
+ "message": "unauthenticated",
+ }
+ },
+ status_code=401,
+ )
+ if action is not None and not allows(context, action):
+ return None, JSONResponse(
+ {
+ "error": {
+ "code": "security.forbidden",
+ "message": f"missing grant: {action}",
+ }
+ },
+ status_code=403,
+ )
+ return context, None
+
+ def run_visible(context: SecurityContext, run: Run) -> bool:
+ if run.tenant_id != context.tenant_id:
+ return False
+ run_context = thaw_json(run.context)
+ return not isinstance(run_context, Mapping) or project_allows(
+ context,
+ run_context.get("project_id"),
+ )
+
+ async def live(request: Request) -> Response:
+ return JSONResponse({"status": "ok"})
+
+ async def ready(request: Request) -> Response:
+ try:
+ server.store.list_runs(tenant_id="__readiness__")
+ except Exception:
+ return JSONResponse({"status": "not_ready"}, status_code=503)
+ return JSONResponse({"status": "ready"})
+
+ async def info(request: Request) -> Response:
+ return JSONResponse(
+ {
+ "name": "openrath-agent-server",
+ "api_version": "v1",
+ "version": package_version,
+ "capabilities": [
+ "assistants",
+ "sessions",
+ "runs",
+ "events",
+ "sse",
+ "interrupts",
+ "feedback",
+ ]
+ + (["store"] if server.memory_handler is not None else []),
+ }
+ )
+
+ async def openapi(request: Request) -> Response:
+ return JSONResponse(
+ _openapi_document(
+ package_version,
+ store_enabled=server.memory_handler is not None,
+ )
+ )
+
+ secured: list[dict[str, list[object]]] = [{"bearerAuth": []}]
+
+ def operation(
+ operation_id: str,
+ summary: str,
+ *,
+ success: str = "200",
+ media_type: str = "application/json",
+ ) -> dict[str, object]:
+ return {
+ "operationId": operation_id,
+ "summary": summary,
+ "security": secured,
+ "responses": {
+ success: {
+ "description": "Success",
+ "content": {media_type: {"schema": {"type": "object"}}},
+ },
+ "400": {"description": "Invalid request"},
+ "401": {"description": "Unauthenticated"},
+ "403": {"description": "Forbidden"},
+ "404": {"description": "Not found"},
+ "409": {"description": "Conflict"},
+ },
+ }
+
+ return JSONResponse(
+ {
+ "openapi": "3.1.0",
+ "info": {
+ "title": "OpenRath Agent Server",
+ "version": package_version,
+ },
+ "paths": {
+ "/v1/assistants": {
+ "get": operation(
+ "listAssistants",
+ "List deployment templates and tenant aliases",
+ ),
+ "post": operation(
+ "createAssistantAlias",
+ "Create a tenant assistant alias",
+ success="201",
+ ),
+ },
+ "/v1/assistants/{assistant_id}": {
+ "get": operation(
+ "getAssistant",
+ "Get an assistant template or alias",
+ )
+ },
+ "/v1/sessions": {
+ "post": operation(
+ "createSession",
+ "Create a durable session",
+ success="201",
+ )
+ },
+ "/v1/sessions/{session_id}": {
+ "get": operation("getSession", "Get a durable session")
+ },
+ "/v1/sessions/{session_id}/runs": {
+ "post": operation(
+ "createSessionRun",
+ "Create a run in an existing session",
+ success="201",
+ )
+ },
+ "/v1/runs": {
+ "get": operation("listRuns", "List runs by cursor"),
+ "post": operation(
+ "createRun",
+ "Create a durable run",
+ success="201",
+ ),
+ },
+ "/v1/runs/{run_id}": {
+ "get": operation("getRun", "Get a durable run")
+ },
+ "/v1/runs/{run_id}/cancel": {
+ "post": operation("cancelRun", "Cancel a run")
+ },
+ "/v1/runs/{run_id}/resume": {
+ "post": operation(
+ "resumeRun",
+ "Resume a run requiring operator review",
+ )
+ },
+ "/v1/runs/{run_id}/events": {
+ "get": operation(
+ "listRunEvents",
+ "Replay ordered durable run events",
+ )
+ },
+ "/v1/runs/{run_id}/stream": {
+ "get": operation(
+ "streamRunEvents",
+ "Stream ordered run events with cursor resume",
+ media_type="text/event-stream",
+ )
+ },
+ "/v1/interrupts/{interrupt_id}/decision": {
+ "post": operation(
+ "decideInterrupt",
+ "Submit a durable interrupt decision",
+ )
+ },
+ "/v1/interrupts": {
+ "get": operation(
+ "listInterrupts",
+ "List pending durable interrupts",
+ )
+ },
+ "/v1/feedback": {
+ "post": operation(
+ "createFeedback",
+ "Create run feedback",
+ success="201",
+ )
+ },
+ "/v1/store/items": {
+ "post": operation(
+ "putStoreItem",
+ "Write a governed memory item",
+ ),
+ "delete": operation(
+ "deleteStoreItem",
+ "Delete a governed memory item",
+ ),
+ },
+ "/v1/store/search": {
+ "post": operation(
+ "searchStore",
+ "Search governed memory",
+ )
+ },
+ },
+ "components": {
+ "securitySchemes": {
+ "bearerAuth": {
+ "type": "http",
+ "scheme": "bearer",
+ }
+ }
+ },
+ }
+ )
+
+ async def metrics(request: Request) -> Response:
+ context, error = await authenticate(request, "metrics.read")
+ if error:
+ return error
+ assert context is not None
+ queued, running = await asyncio.gather(
+ asyncio.to_thread(server.store.count_runs, status=RunStatus.QUEUED),
+ asyncio.to_thread(server.store.count_runs, status=RunStatus.RUNNING),
+ )
+ body = (
+ "# TYPE openrath_runs gauge\n"
+ f'openrath_runs{{status="queued"}} {queued}\n'
+ f'openrath_runs{{status="running"}} {running}\n'
+ )
+ return Response(body, media_type="text/plain; version=0.0.4")
+
+ async def list_assistants(request: Request) -> Response:
+ context, error = await authenticate(request, "assistant.read")
+ if error:
+ return error
+ assert context is not None
+ templates = [
+ {
+ "id": item.id,
+ "template_id": item.id,
+ "revision_id": str(item.revision_id),
+ "kind": "template",
+ }
+ for item in server.assistants.values()
+ ]
+ aliases = [
+ {
+ "id": item.id,
+ "template_id": item.template_id,
+ "revision_id": str(item.revision_id),
+ "kind": "alias",
+ }
+ for item in server.resources.list_assistants(context.tenant_id)
+ ]
+ return JSONResponse({"items": templates + aliases})
+
+ async def create_assistant(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "assistant.create")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ body = await json_body(request)
+ assistant_id = str(body["id"]).strip()
+ template_id = str(body["template_id"]).strip()
+ if not assistant_id or not template_id:
+ raise ValueError("id and template_id are required")
+ if assistant_id in server.assistants:
+ raise ValueError("assistant id is reserved by a deployment template")
+ template = server.assistants[template_id]
+ await audit_action(
+ request,
+ context,
+ kind=AuditKind.RUN_CONTROL,
+ action="assistant.create",
+ resource_kind="assistant",
+ resource_id=assistant_id,
+ )
+ item = server.resources.create_assistant(
+ tenant_id=context.tenant_id,
+ id=assistant_id,
+ template_id=template_id,
+ revision_id=template.revision_id,
+ )
+ return JSONResponse(
+ {
+ "id": item.id,
+ "template_id": item.template_id,
+ "revision_id": str(item.revision_id),
+ "kind": "alias",
+ "created_at": item.created_at.isoformat(),
+ },
+ status_code=201,
+ )
+ except KeyError as exc:
+ return error_response(
+ "request.invalid_argument",
+ f"unknown deployment template: {exc}",
+ 400,
+ )
+ except (ValueError, TypeError) as exc:
+ return error_response("request.invalid_argument", str(exc), 400)
+
+ async def get_assistant(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "assistant.read")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ assistant_id = request.path_params["assistant_id"]
+ try:
+ item = server.assistants[assistant_id]
+ return JSONResponse(
+ {
+ "id": item.id,
+ "template_id": item.id,
+ "revision_id": str(item.revision_id),
+ "kind": "template",
+ }
+ )
+ except KeyError:
+ try:
+ alias = server.resources.get_assistant(context.tenant_id, assistant_id)
+ except KeyError:
+ return error_response("resource.not_found", "assistant not found", 404)
+ return JSONResponse(
+ {
+ "id": alias.id,
+ "template_id": alias.template_id,
+ "revision_id": str(alias.revision_id),
+ "kind": "alias",
+ "created_at": alias.created_at.isoformat(),
+ }
+ )
+
+ async def create_session(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "session.create")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ session = server.resources.create_session(context.tenant_id)
+ return JSONResponse(
+ {
+ "id": str(session.id),
+ "tenant_id": session.tenant_id,
+ "created_at": session.created_at.isoformat(),
+ },
+ status_code=201,
+ )
+
+ async def get_session(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "session.read")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ session = server.resources.get_session(
+ UUID(request.path_params["session_id"])
+ )
+ if session.tenant_id != context.tenant_id:
+ raise KeyError
+ except (KeyError, ValueError):
+ return error_response("resource.not_found", "session not found", 404)
+ runs = [
+ _run_json(run)
+ for run in server.store.list_runs(
+ tenant_id=context.tenant_id,
+ session_id=session.id,
+ limit=201,
+ )
+ ]
+ return JSONResponse(
+ {
+ "id": str(session.id),
+ "tenant_id": session.tenant_id,
+ "created_at": session.created_at.isoformat(),
+ "runs": runs,
+ }
+ )
+
+ async def create_run(request: Request) -> Response:
+ context, error = await authenticate(request, "run.create")
+ if error:
+ return error
+ assert context is not None
+ try:
+ body = await json_body(request)
+ assistant_id = str(body["assistant_id"])
+ assistant = server.assistants.get(assistant_id)
+ if assistant is None:
+ alias = server.resources.get_assistant(context.tenant_id, assistant_id)
+ assistant = server.assistants.get(alias.template_id)
+ if assistant is None or assistant.revision_id != alias.revision_id:
+ raise ValueError("assistant deployment revision is unavailable")
+ session_id = UUID(str(body["session_id"]))
+ try:
+ known_session = server.resources.get_session(session_id)
+ except KeyError:
+ raise KeyError("session_id") from None
+ if known_session.tenant_id != context.tenant_id:
+ raise KeyError("session_id")
+ run_context = RunContext(
+ security=context,
+ revision_id=assistant.revision_id,
+ )
+ state = body.get("state") or {}
+ if not isinstance(state, Mapping):
+ raise ValueError("state must be a JSON object")
+ queued = len(
+ server.store.list_runs(
+ tenant_id=context.tenant_id,
+ statuses=(RunStatus.QUEUED,),
+ limit=server.max_queued_runs_per_tenant,
+ )
+ )
+ if queued >= server.max_queued_runs_per_tenant:
+ return error_response(
+ "resource.exhausted",
+ "tenant run queue is at capacity",
+ 429,
+ )
+ run = server.runtime.submit(
+ assistant.workflow,
+ session_id=session_id,
+ context=run_context,
+ state=cast(Mapping[str, object], state),
+ idempotency_key=request.headers.get("idempotency-key"),
+ priority=int(str(body.get("priority", 0))),
+ )
+ if server.signals is not None:
+ server.signals.publish(
+ RunSignal(
+ kind=SignalKind.WAKE,
+ run_id=run.id,
+ tenant_id=run.tenant_id,
+ created_at=run.updated_at,
+ )
+ )
+ return JSONResponse(_run_json(run), status_code=201)
+ except KeyError as exc:
+ return JSONResponse(
+ {"error": {"code": "request.invalid_argument", "message": str(exc)}},
+ status_code=400,
+ )
+ except (ValueError, TypeError) as exc:
+ return JSONResponse(
+ {"error": {"code": "request.invalid_argument", "message": str(exc)}},
+ status_code=400,
+ )
+ except RathError as exc:
+ return JSONResponse({"error": exc.to_dict()}, status_code=409)
+
+ async def create_session_run(request: Request) -> Response:
+ try:
+ session_id = UUID(request.path_params["session_id"])
+ body = await json_body(request)
+ except (ValueError, TypeError):
+ return error_response(
+ "request.invalid_argument", "invalid session or body", 400
+ )
+ body["session_id"] = str(session_id)
+ request._body = json.dumps(body).encode() # noqa: SLF001
+ return await create_run(request)
+
+ async def list_runs(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "run.read")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ limit = min(max(int(request.query_params.get("limit", "50")), 1), 200)
+ after = request.query_params.get("after")
+ after_id = UUID(after) if after else None
+ except ValueError:
+ return error_response(
+ "request.invalid_argument", "invalid pagination cursor", 400
+ )
+ try:
+ values = await asyncio.to_thread(
+ server.store.list_runs,
+ tenant_id=context.tenant_id,
+ after=after_id,
+ limit=limit + 1,
+ )
+ except KeyError:
+ return error_response(
+ "request.invalid_argument", "unknown pagination cursor", 400
+ )
+ page = values[:limit]
+ next_cursor = str(page[-1].id) if len(values) > limit else None
+ return JSONResponse(
+ {"items": [_run_json(item) for item in page], "next": next_cursor}
+ )
+
+ async def get_run(request: Request) -> Response:
+ context, error = await authenticate(request, "run.read")
+ if error:
+ return error
+ assert context is not None
+ try:
+ run = server.store.get_run(UUID(request.path_params["run_id"]))
+ except (KeyError, ValueError):
+ return JSONResponse(
+ {"error": {"code": "resource.not_found", "message": "run not found"}},
+ status_code=404,
+ )
+ if not run_visible(context, run):
+ return JSONResponse(
+ {"error": {"code": "resource.not_found", "message": "run not found"}},
+ status_code=404,
+ )
+ return JSONResponse(_run_json(run))
+
+ async def cancel_run(request: Request) -> Response:
+ context, error = await authenticate(request, "run.cancel")
+ if error:
+ return error
+ assert context is not None
+ try:
+ run = server.store.get_run(UUID(request.path_params["run_id"]))
+ if not run_visible(context, run):
+ raise KeyError
+ await audit_action(
+ request,
+ context,
+ kind=AuditKind.RUN_CONTROL,
+ action="run.cancel",
+ resource_kind="run",
+ resource_id=str(run.id),
+ )
+ cancelled = server.store.transition_run(
+ run.id,
+ expected_version=run.version,
+ target=RunStatus.CANCELLED,
+ )
+ if server.signals is not None:
+ server.signals.publish(
+ RunSignal(
+ kind=SignalKind.CANCEL,
+ run_id=run.id,
+ tenant_id=run.tenant_id,
+ created_at=cancelled.updated_at,
+ )
+ )
+ return JSONResponse(_run_json(cancelled))
+ except (KeyError, ValueError):
+ return JSONResponse(
+ {"error": {"code": "resource.not_found", "message": "run not found"}},
+ status_code=404,
+ )
+ except RathError as exc:
+ return JSONResponse({"error": exc.to_dict()}, status_code=409)
+
+ async def resume_run(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "run.resume")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ run = server.store.get_run(UUID(request.path_params["run_id"]))
+ if not run_visible(context, run):
+ raise KeyError
+ body = await json_body(request)
+ if (
+ run.status is not RunStatus.NEEDS_REVIEW
+ or body.get("confirm") is not True
+ ):
+ return error_response(
+ "request.invalid_argument",
+ "resume requires NEEDS_REVIEW status and confirm=true",
+ 400,
+ )
+ await audit_action(
+ request,
+ context,
+ kind=AuditKind.OPERATOR_OVERRIDE,
+ action="run.resume",
+ resource_kind="run",
+ resource_id=str(run.id),
+ )
+ resumed = server.store.transition_run(
+ run.id,
+ expected_version=run.version,
+ target=RunStatus.QUEUED,
+ )
+ return JSONResponse(_run_json(resumed))
+ except (KeyError, ValueError):
+ return error_response("resource.not_found", "run not found", 404)
+ except RathError as exc:
+ return JSONResponse({"error": exc.to_dict()}, status_code=409)
+
+ async def events(request: Request) -> Response:
+ context, error = await authenticate(request, "run.read")
+ if error:
+ return error
+ assert context is not None
+ try:
+ run_id = UUID(request.path_params["run_id"])
+ run = server.store.get_run(run_id)
+ if not run_visible(context, run):
+ raise KeyError
+ except (KeyError, ValueError):
+ return JSONResponse(
+ {"error": {"code": "resource.not_found", "message": "run not found"}},
+ status_code=404,
+ )
+ try:
+ cursor_value = request.query_params.get("after")
+ if cursor_value is None:
+ cursor_value = request.headers.get("last-event-id", "0")
+ after = int(cursor_value)
+ if after < 0:
+ raise ValueError
+ limit = min(max(int(request.query_params.get("limit", "200")), 1), 1000)
+ except ValueError:
+ return error_response(
+ "request.invalid_argument", "invalid event cursor", 400
+ )
+ items = [
+ {
+ "id": str(event.sequence),
+ "run_id": str(event.run_id),
+ "sequence": event.sequence,
+ "type": event.type,
+ "time": event.created_at.isoformat(),
+ "data": thaw_json(event.data),
+ }
+ for event in await asyncio.to_thread(
+ server.store.list_run_events,
+ run_id,
+ after_sequence=after,
+ limit=limit,
+ )
+ ]
+ return JSONResponse(
+ {
+ "items": items,
+ "next": str(items[-1]["sequence"]) if len(items) == limit else None,
+ }
+ )
+
+ async def stream(request: Request) -> Response:
+ last_event = request.headers.get("last-event-id")
+ response = await events(request)
+ if response.status_code != 200:
+ return response
+ payload = json.loads(bytes(response.body))
+ follow = request.query_params.get("follow", "false").lower() == "true"
+ run_id = UUID(request.path_params["run_id"])
+
+ async def generate() -> AsyncIterator[str]:
+ cursor = int(last_event or request.query_params.get("after", "0"))
+ initial = payload["items"]
+ idle_delay = 0.1
+ while True:
+ emitted = False
+ durable_events = (
+ ()
+ if initial
+ else await asyncio.to_thread(
+ server.store.list_run_events,
+ run_id,
+ after_sequence=cursor,
+ limit=200,
+ )
+ )
+ items = initial or [
+ {
+ "sequence": event.sequence,
+ "type": event.type,
+ "run_id": str(event.run_id),
+ "time": event.created_at.isoformat(),
+ "data": thaw_json(event.data),
+ }
+ for event in durable_events
+ ]
+ initial = []
+ for item in items:
+ emitted = True
+ idle_delay = 0.1
+ cursor = int(item["sequence"])
+ yield (
+ f"id: {cursor}\nevent: {item['type']}\n"
+ f"data: {json.dumps(item, separators=(',', ':'))}\n\n"
+ )
+ if not follow:
+ break
+ if await request.is_disconnected():
+ break
+ run = await asyncio.to_thread(server.store.get_run, run_id)
+ if (
+ run.status
+ in {
+ RunStatus.SUCCEEDED,
+ RunStatus.FAILED,
+ RunStatus.CANCELLED,
+ RunStatus.TIMED_OUT,
+ }
+ and not emitted
+ ):
+ break
+ if not emitted:
+ yield ": keep-alive\n\n"
+ idle_delay = min(idle_delay * 2, 2.0)
+ await asyncio.sleep(idle_delay)
+
+ return StreamingResponse(
+ generate(),
+ media_type="text/event-stream",
+ headers={
+ "Cache-Control": "no-cache",
+ "X-Accel-Buffering": "no",
+ },
+ )
+
+ async def decide_interrupt(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "interrupt.decide")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ interrupt_id = UUID(request.path_params["interrupt_id"])
+ interrupt = server.store.get_interrupt(interrupt_id)
+ run = server.store.get_run(interrupt.run_id)
+ if not run_visible(context, run):
+ raise KeyError
+ body = await json_body(request)
+ payload = body.get("payload") or {}
+ if not isinstance(payload, Mapping):
+ raise ValueError("decision payload must be a JSON object")
+ decision = ApprovalDecision(
+ kind=ApprovalDecisionKind(str(body["kind"])),
+ actor_id=context.principal.id,
+ reason=str(body["reason"]),
+ payload=cast(Mapping[str, JSONValue], payload),
+ )
+ await audit_action(
+ request,
+ context,
+ kind=AuditKind.OPERATOR_OVERRIDE,
+ action="interrupt.decide",
+ resource_kind="interrupt",
+ resource_id=str(interrupt_id),
+ )
+ updated = server.store.decide_interrupt(
+ interrupt_id,
+ decision=decision,
+ expected_run_version=run.version,
+ )
+ return JSONResponse(_run_json(updated))
+ except (KeyError, ValueError, TypeError) as exc:
+ return error_response("request.invalid_argument", str(exc), 400)
+ except RathError as exc:
+ return JSONResponse({"error": exc.to_dict()}, status_code=409)
+
+ async def list_interrupts(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "interrupt.read")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ limit = min(max(int(request.query_params.get("limit", "50")), 1), 200)
+ pending_only = (
+ request.query_params.get("pending", "true").lower() != "false"
+ )
+ except ValueError:
+ return error_response(
+ "request.invalid_argument", "invalid pagination limit", 400
+ )
+ values = server.store.list_interrupts(
+ tenant_id=context.tenant_id,
+ pending_only=pending_only,
+ )
+ return JSONResponse(
+ {
+ "items": [_interrupt_json(item) for item in values[:limit]],
+ "next": (str(values[limit - 1].id) if len(values) > limit else None),
+ }
+ )
+
+ async def create_feedback(request: Request) -> Response:
+ context, auth_error = await authenticate(request, "feedback.create")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ try:
+ body = await json_body(request)
+ run = server.store.get_run(UUID(str(body["run_id"])))
+ if not run_visible(context, run):
+ raise KeyError
+ score = body.get("score")
+ numeric_score = float(str(score)) if score is not None else None
+ if numeric_score is not None and not -1 <= numeric_score <= 1:
+ raise ValueError("score must be between -1 and 1")
+ key = str(body["key"])
+ if not key:
+ raise ValueError("feedback key is required")
+ feedback = server.resources.create_feedback(
+ tenant_id=context.tenant_id,
+ run_id=run.id,
+ key=key,
+ score=numeric_score,
+ value=str(body["value"]) if body.get("value") is not None else None,
+ )
+ return JSONResponse(
+ {
+ "id": str(feedback.id),
+ "run_id": str(feedback.run_id),
+ "key": feedback.key,
+ "score": feedback.score,
+ "value": feedback.value,
+ "created_at": feedback.created_at.isoformat(),
+ },
+ status_code=201,
+ )
+ except (KeyError, ValueError, TypeError) as exc:
+ return error_response("request.invalid_argument", str(exc), 400)
+
+ async def execute_store_operation(
+ request: Request,
+ operation: str,
+ ) -> Response:
+ context, auth_error = await authenticate(request, f"memory.{operation}")
+ if auth_error:
+ return auth_error
+ assert context is not None
+ if server.memory_executor is None or server.memory_handler is None:
+ return error_response(
+ "runtime.unavailable",
+ "store capability is not configured",
+ 501,
+ )
+ try:
+ body = await json_body(request)
+ requested_tenant = body.get("tenant_id")
+ if (
+ requested_tenant is not None
+ and str(requested_tenant) != context.tenant_id
+ ):
+ raise PermissionError("memory namespace tenant mismatch")
+ requested_user = (
+ str(body["user_id"]) if body.get("user_id") is not None else None
+ )
+ if (
+ requested_user is not None
+ and requested_user != context.principal.id
+ and not allows(context, "memory.admin")
+ ):
+ raise PermissionError("memory namespace owner mismatch")
+ namespace = MemoryNamespace(
+ tenant_id=context.tenant_id,
+ user_id=requested_user,
+ agent_id=(
+ str(body["agent_id"]) if body.get("agent_id") is not None else None
+ ),
+ session_id=(
+ str(body["session_id"])
+ if body.get("session_id") is not None
+ else None
+ ),
+ # HTTP input never upgrades memory trust.
+ trust=TrustLevel.UNTRUSTED,
+ )
+ payload = body.get("payload", {})
+ if not isinstance(payload, Mapping):
+ raise ValueError("payload must be a JSON object")
+ run_context = RunContext(
+ security=context,
+ revision_id=UUID(int=0),
+ )
+ adapter_context = AdapterRequestContext(
+ run_id=uuid4(),
+ node_id=f"store.{operation}",
+ tenant_id=context.tenant_id,
+ deadline=None,
+ trace_context=run_context.trace_context,
+ idempotency_key=request.headers.get("idempotency-key"),
+ policy_constraints=PolicyConstraints(),
+ )
+ await audit_action(
+ request,
+ context,
+ kind=AuditKind.MEMORY_ACCESS,
+ action=f"memory.{operation}",
+ resource_kind="memory_namespace",
+ resource_id=":".join(
+ item
+ for item in (
+ namespace.tenant_id,
+ namespace.user_id,
+ namespace.agent_id,
+ namespace.session_id,
+ )
+ if item is not None
+ ),
+ )
+ result = await server.memory_executor.execute(
+ server.memory_handler,
+ cast(Any, operation),
+ namespace,
+ cast(Mapping[str, object], payload),
+ adapter_context=adapter_context,
+ run_context=run_context,
+ )
+ return JSONResponse({"result": result})
+ except PermissionError as exc:
+ return error_response("security.forbidden", str(exc), 403)
+ except (KeyError, ValueError, TypeError) as exc:
+ return error_response("request.invalid_argument", str(exc), 400)
+ except RathError as exc:
+ status = (
+ 403
+ if exc.code
+ in {
+ ErrorCode.FORBIDDEN,
+ ErrorCode.APPROVAL_REQUIRED,
+ ErrorCode.POLICY_ERROR,
+ }
+ else 409
+ )
+ return JSONResponse({"error": exc.to_dict()}, status_code=status)
+
+ async def put_store_item(request: Request) -> Response:
+ return await execute_store_operation(request, "put")
+
+ async def search_store(request: Request) -> Response:
+ return await execute_store_operation(request, "search")
+
+ async def delete_store_item(request: Request) -> Response:
+ return await execute_store_operation(request, "delete")
+
+ async def worker_loop() -> None:
+ while True:
+ await asyncio.to_thread(server.store.expire_interrupts)
+ await asyncio.to_thread(server.runtime.reconcile_effects)
+ await asyncio.to_thread(server.store.requeue_expired_leases)
+ result = await asyncio.to_thread(
+ server.runtime.work_once,
+ worker_id=server.worker_id,
+ lease_seconds=server.worker_lease_seconds,
+ )
+ if result is not None:
+ await asyncio.sleep(0)
+ elif server.signals is not None:
+ await asyncio.to_thread(
+ server.signals.receive,
+ timeout_seconds=0.1,
+ )
+ else:
+ await asyncio.sleep(0.1)
+
+ @asynccontextmanager
+ async def lifespan(app: Starlette) -> AsyncIterator[None]:
+ task = (
+ asyncio.create_task(worker_loop(), name="openrath-embedded-worker")
+ if server.embedded_worker
+ else None
+ )
+ try:
+ yield
+ finally:
+ if task is not None:
+ task.cancel()
+ try:
+ await task
+ except asyncio.CancelledError:
+ pass
+
+ app = Starlette(
+ routes=[
+ Route("/health/live", live),
+ Route("/health/ready", ready),
+ Route("/info", info),
+ Route("/openapi.json", openapi),
+ Route("/metrics", metrics),
+ Route("/v1/assistants", list_assistants, methods=["GET"]),
+ Route("/v1/assistants", create_assistant, methods=["POST"]),
+ Route("/v1/assistants/{assistant_id}", get_assistant),
+ Route("/v1/sessions", create_session, methods=["POST"]),
+ Route("/v1/sessions/{session_id}", get_session),
+ Route(
+ "/v1/sessions/{session_id}/runs",
+ create_session_run,
+ methods=["POST"],
+ ),
+ Route("/v1/runs", create_run, methods=["POST"]),
+ Route("/v1/runs", list_runs, methods=["GET"]),
+ Route("/v1/runs/{run_id}", get_run),
+ Route("/v1/runs/{run_id}/cancel", cancel_run, methods=["POST"]),
+ Route("/v1/runs/{run_id}/resume", resume_run, methods=["POST"]),
+ Route("/v1/runs/{run_id}/events", events),
+ Route("/v1/runs/{run_id}/stream", stream),
+ Route("/v1/interrupts", list_interrupts, methods=["GET"]),
+ Route(
+ "/v1/interrupts/{interrupt_id}/decision",
+ decide_interrupt,
+ methods=["POST"],
+ ),
+ Route("/v1/feedback", create_feedback, methods=["POST"]),
+ Route("/v1/store/items", put_store_item, methods=["POST"]),
+ Route("/v1/store/items", delete_store_item, methods=["DELETE"]),
+ Route("/v1/store/search", search_store, methods=["POST"]),
+ ],
+ lifespan=lifespan,
+ )
+
+ app.add_middleware(_SecurityHeadersMiddleware)
+
+ return app
diff --git a/src/rath/server/auth.py b/src/rath/server/auth.py
new file mode 100644
index 0000000..4c5d48e
--- /dev/null
+++ b/src/rath/server/auth.py
@@ -0,0 +1,41 @@
+"""Pluggable Agent Server authentication."""
+
+from __future__ import annotations
+
+import hashlib
+import hmac
+from typing import Protocol, runtime_checkable
+
+from rath.security import SecurityContext
+
+__all__ = ["AuthProvider", "StaticTokenAuth"]
+
+
+@runtime_checkable
+class AuthProvider(Protocol):
+ async def authenticate(
+ self, authorization: str | None
+ ) -> SecurityContext | None: ...
+
+
+class StaticTokenAuth:
+ """Reference bearer-token provider for self-hosted deployments and tests."""
+
+ def __init__(self, tokens: dict[str, SecurityContext]) -> None:
+ if not tokens:
+ raise ValueError("at least one authentication token is required")
+ self._tokens = {
+ hashlib.sha256(token.encode()).digest(): context
+ for token, context in tokens.items()
+ }
+
+ async def authenticate(self, authorization: str | None) -> SecurityContext | None:
+ if not authorization or not authorization.startswith("Bearer "):
+ return None
+ supplied = hashlib.sha256(
+ authorization.removeprefix("Bearer ").strip().encode()
+ ).digest()
+ for expected, context in self._tokens.items():
+ if hmac.compare_digest(supplied, expected):
+ return context
+ return None
diff --git a/src/rath/server/authorization.py b/src/rath/server/authorization.py
new file mode 100644
index 0000000..b713a22
--- /dev/null
+++ b/src/rath/server/authorization.py
@@ -0,0 +1,34 @@
+"""Fail-closed action authorization for the Agent Server."""
+
+from __future__ import annotations
+
+from rath.security import SecurityContext
+
+__all__ = ["allows", "project_allows"]
+
+
+def allows(context: SecurityContext, action: str) -> bool:
+ """Return whether an explicit grant permits an action.
+
+ Grants support an exact action, a namespace wildcard such as ``run.*``,
+ or the explicit administrative ``*`` grant.
+ """
+
+ if "*" in context.grants or action in context.grants:
+ return True
+ namespace, _, _ = action.partition(".")
+ return f"{namespace}.*" in context.grants
+
+
+def project_allows(
+ context: SecurityContext,
+ resource_project_id: object | None,
+) -> bool:
+ """Enforce project isolation when either side declares project scope."""
+
+ if resource_project_id is None:
+ return True
+ return (
+ context.project_id is not None
+ and str(resource_project_id) == context.project_id
+ )
diff --git a/src/rath/server/cli.py b/src/rath/server/cli.py
new file mode 100644
index 0000000..fef3dcd
--- /dev/null
+++ b/src/rath/server/cli.py
@@ -0,0 +1,131 @@
+"""Agent Server and schema migration command-line entry points."""
+
+from __future__ import annotations
+
+import argparse
+import contextlib
+import importlib
+import os
+import signal
+import threading
+from typing import Any
+
+
+def _load_reference(reference: str) -> Any:
+ if ":" not in reference:
+ raise ValueError("OPENRATH_APP must use module:attribute syntax")
+ module_name, attribute = reference.split(":", 1)
+ value = getattr(importlib.import_module(module_name), attribute)
+ if callable(value) and not hasattr(value, "router"):
+ value = value()
+ return value
+
+
+def _load_app(reference: str) -> Any:
+ value = _load_reference(reference)
+ return getattr(value, "app", value)
+
+
+def server_main() -> None:
+ parser = argparse.ArgumentParser(prog="openrath-server")
+ parser.add_argument(
+ "--app",
+ default=os.getenv("OPENRATH_APP"),
+ help="ASGI application factory or object as module:attribute",
+ )
+ parser.add_argument("--host", default=os.getenv("OPENRATH_HOST", "0.0.0.0"))
+ parser.add_argument(
+ "--port", type=int, default=int(os.getenv("OPENRATH_PORT", "8000"))
+ )
+ parser.add_argument(
+ "--workers", type=int, default=int(os.getenv("OPENRATH_WEB_WORKERS", "1"))
+ )
+ arguments = parser.parse_args()
+ if not arguments.app:
+ parser.error("--app or OPENRATH_APP is required")
+ if arguments.workers != 1:
+ parser.error(
+ "process workers must be 1; scale OpenRath with container replicas"
+ )
+ import uvicorn
+
+ uvicorn.run(
+ _load_app(arguments.app),
+ host=arguments.host,
+ port=arguments.port,
+ workers=arguments.workers,
+ proxy_headers=False,
+ server_header=False,
+ )
+
+
+def migrate_main() -> None:
+ parser = argparse.ArgumentParser(prog="openrath-migrate")
+ parser.add_argument(
+ "--dsn",
+ default=os.getenv("OPENRATH_POSTGRES_DSN"),
+ help="PostgreSQL DSN; defaults to OPENRATH_POSTGRES_DSN",
+ )
+ parser.add_argument("--schema", default=os.getenv("OPENRATH_DB_SCHEMA", "openrath"))
+ parser.add_argument(
+ "--check",
+ action="store_true",
+ help="verify the current schema without applying changes",
+ )
+ arguments = parser.parse_args()
+ if not arguments.dsn:
+ parser.error("--dsn or OPENRATH_POSTGRES_DSN is required")
+ if arguments.check:
+ from rath.runtime import PostgresRunStore
+
+ PostgresRunStore.verify_schema(arguments.dsn, schema=arguments.schema)
+ return
+ from rath.runtime import PostgresRunStore
+
+ PostgresRunStore.migrate(arguments.dsn, schema=arguments.schema)
+
+
+def worker_main() -> None:
+ parser = argparse.ArgumentParser(prog="openrath-worker")
+ parser.add_argument(
+ "--app",
+ default=os.getenv("OPENRATH_APP"),
+ help="AgentServer object or factory as module:attribute",
+ )
+ parser.add_argument(
+ "--worker-id",
+ default=os.getenv("OPENRATH_WORKER_ID", os.getenv("HOSTNAME", "worker")),
+ )
+ parser.add_argument(
+ "--lease-seconds",
+ type=float,
+ default=float(os.getenv("OPENRATH_WORKER_LEASE_SECONDS", "30")),
+ )
+ arguments = parser.parse_args()
+ if not arguments.app:
+ parser.error("--app or OPENRATH_APP is required")
+ server = _load_reference(arguments.app)
+ if not hasattr(server, "runtime") or not hasattr(server, "store"):
+ parser.error("worker application reference must resolve to AgentServer")
+ stopped = threading.Event()
+
+ def stop(signum: int, frame: object) -> None:
+ stopped.set()
+
+ for name in ("SIGINT", "SIGTERM"):
+ with contextlib.suppress(AttributeError):
+ signal.signal(getattr(signal, name), stop)
+ while not stopped.is_set():
+ server.store.expire_interrupts()
+ server.runtime.reconcile_effects()
+ server.store.requeue_expired_leases()
+ result = server.runtime.work_once(
+ worker_id=arguments.worker_id,
+ lease_seconds=arguments.lease_seconds,
+ )
+ if result is not None:
+ continue
+ if getattr(server, "signals", None) is not None:
+ server.signals.receive(timeout_seconds=0.1)
+ else:
+ stopped.wait(0.1)
diff --git a/src/rath/server/resources.py b/src/rath/server/resources.py
new file mode 100644
index 0000000..debf045
--- /dev/null
+++ b/src/rath/server/resources.py
@@ -0,0 +1,486 @@
+"""Durable Session and Feedback resource persistence."""
+
+from __future__ import annotations
+
+import sqlite3
+from dataclasses import dataclass
+from datetime import datetime, timezone
+from typing import Protocol, runtime_checkable
+from uuid import UUID, uuid4
+
+from rath.runtime import PostgresRunStore, RunStore, SQLiteRunStore
+
+__all__ = [
+ "AssistantRecord",
+ "FeedbackRecord",
+ "InMemoryResourceStore",
+ "PostgresResourceStore",
+ "ResourceStore",
+ "SQLiteResourceStore",
+ "SessionRecord",
+ "default_resource_store",
+]
+
+
+@dataclass(frozen=True, slots=True)
+class AssistantRecord:
+ id: str
+ tenant_id: str
+ template_id: str
+ revision_id: UUID
+ created_at: datetime
+
+
+@dataclass(frozen=True, slots=True)
+class SessionRecord:
+ id: UUID
+ tenant_id: str
+ created_at: datetime
+
+
+@dataclass(frozen=True, slots=True)
+class FeedbackRecord:
+ id: UUID
+ tenant_id: str
+ run_id: UUID
+ key: str
+ score: float | None
+ value: str | None
+ created_at: datetime
+
+
+@runtime_checkable
+class ResourceStore(Protocol):
+ def create_assistant(
+ self,
+ *,
+ tenant_id: str,
+ id: str,
+ template_id: str,
+ revision_id: UUID,
+ ) -> AssistantRecord: ...
+
+ def get_assistant(self, tenant_id: str, id: str) -> AssistantRecord: ...
+
+ def list_assistants(self, tenant_id: str) -> tuple[AssistantRecord, ...]: ...
+
+ def create_session(self, tenant_id: str) -> SessionRecord: ...
+
+ def get_session(self, session_id: UUID) -> SessionRecord: ...
+
+ def ensure_session(self, session: SessionRecord) -> SessionRecord: ...
+
+ def count_tenants(self) -> tuple[str, ...]: ...
+
+ def create_feedback(
+ self,
+ *,
+ tenant_id: str,
+ run_id: UUID,
+ key: str,
+ score: float | None,
+ value: str | None,
+ ) -> FeedbackRecord: ...
+
+
+class InMemoryResourceStore:
+ def __init__(self) -> None:
+ self.sessions: dict[UUID, SessionRecord] = {}
+ self.feedback: dict[UUID, FeedbackRecord] = {}
+ self.assistants: dict[tuple[str, str], AssistantRecord] = {}
+
+ def create_assistant(
+ self,
+ *,
+ tenant_id: str,
+ id: str,
+ template_id: str,
+ revision_id: UUID,
+ ) -> AssistantRecord:
+ key = (tenant_id, id)
+ item = AssistantRecord(
+ id, tenant_id, template_id, revision_id, datetime.now(timezone.utc)
+ )
+ existing = self.assistants.setdefault(key, item)
+ if existing.template_id != template_id or existing.revision_id != revision_id:
+ raise ValueError("assistant id already has a different revision")
+ return existing
+
+ def get_assistant(self, tenant_id: str, id: str) -> AssistantRecord:
+ try:
+ return self.assistants[(tenant_id, id)]
+ except KeyError as exc:
+ raise KeyError(id) from exc
+
+ def list_assistants(self, tenant_id: str) -> tuple[AssistantRecord, ...]:
+ return tuple(
+ value
+ for (owner, _), value in sorted(self.assistants.items())
+ if owner == tenant_id
+ )
+
+ def create_session(self, tenant_id: str) -> SessionRecord:
+ value = SessionRecord(uuid4(), tenant_id, datetime.now(timezone.utc))
+ self.sessions[value.id] = value
+ return value
+
+ def get_session(self, session_id: UUID) -> SessionRecord:
+ try:
+ return self.sessions[session_id]
+ except KeyError as exc:
+ raise KeyError(str(session_id)) from exc
+
+ def ensure_session(self, session: SessionRecord) -> SessionRecord:
+ existing = self.sessions.setdefault(session.id, session)
+ if existing.tenant_id != session.tenant_id:
+ raise ValueError("session tenant mismatch")
+ return existing
+
+ def count_tenants(self) -> tuple[str, ...]:
+ return tuple(sorted({item.tenant_id for item in self.sessions.values()}))
+
+ def create_feedback(
+ self,
+ *,
+ tenant_id: str,
+ run_id: UUID,
+ key: str,
+ score: float | None,
+ value: str | None,
+ ) -> FeedbackRecord:
+ item = FeedbackRecord(
+ uuid4(),
+ tenant_id,
+ run_id,
+ key,
+ score,
+ value,
+ datetime.now(timezone.utc),
+ )
+ self.feedback[item.id] = item
+ return item
+
+
+class SQLiteResourceStore:
+ """Resource store sharing the embedded Run database."""
+
+ def __init__(self, run_store: SQLiteRunStore) -> None:
+ self.path = str(run_store.path)
+
+ def _connect(self) -> sqlite3.Connection:
+ connection = sqlite3.connect(self.path)
+ connection.row_factory = sqlite3.Row
+ connection.execute("PRAGMA foreign_keys = ON")
+ return connection
+
+ def create_assistant(
+ self,
+ *,
+ tenant_id: str,
+ id: str,
+ template_id: str,
+ revision_id: UUID,
+ ) -> AssistantRecord:
+ item = AssistantRecord(
+ id, tenant_id, template_id, revision_id, datetime.now(timezone.utc)
+ )
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT OR IGNORE INTO server_assistants(
+ tenant_id, id, template_id, revision_id, created_at
+ ) VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ tenant_id,
+ id,
+ template_id,
+ str(revision_id),
+ item.created_at.isoformat(),
+ ),
+ )
+ existing = self.get_assistant(tenant_id, id)
+ if existing.template_id != template_id or existing.revision_id != revision_id:
+ raise ValueError("assistant id already has a different revision")
+ return existing
+
+ def get_assistant(self, tenant_id: str, id: str) -> AssistantRecord:
+ with self._connect() as connection:
+ row = connection.execute(
+ """
+ SELECT * FROM server_assistants
+ WHERE tenant_id = ? AND id = ?
+ """,
+ (tenant_id, id),
+ ).fetchone()
+ if row is None:
+ raise KeyError(id)
+ return AssistantRecord(
+ row["id"],
+ row["tenant_id"],
+ row["template_id"],
+ UUID(row["revision_id"]),
+ datetime.fromisoformat(row["created_at"]),
+ )
+
+ def list_assistants(self, tenant_id: str) -> tuple[AssistantRecord, ...]:
+ with self._connect() as connection:
+ rows = connection.execute(
+ """
+ SELECT * FROM server_assistants
+ WHERE tenant_id = ? ORDER BY created_at, id
+ """,
+ (tenant_id,),
+ ).fetchall()
+ return tuple(
+ AssistantRecord(
+ row["id"],
+ row["tenant_id"],
+ row["template_id"],
+ UUID(row["revision_id"]),
+ datetime.fromisoformat(row["created_at"]),
+ )
+ for row in rows
+ )
+
+ def create_session(self, tenant_id: str) -> SessionRecord:
+ value = SessionRecord(uuid4(), tenant_id, datetime.now(timezone.utc))
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT INTO server_sessions(id, tenant_id, created_at)
+ VALUES (?, ?, ?)
+ """,
+ (str(value.id), value.tenant_id, value.created_at.isoformat()),
+ )
+ return value
+
+ def get_session(self, session_id: UUID) -> SessionRecord:
+ with self._connect() as connection:
+ row = connection.execute(
+ "SELECT * FROM server_sessions WHERE id = ?", (str(session_id),)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(session_id))
+ return SessionRecord(
+ UUID(row["id"]),
+ row["tenant_id"],
+ datetime.fromisoformat(row["created_at"]),
+ )
+
+ def ensure_session(self, session: SessionRecord) -> SessionRecord:
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT OR IGNORE INTO server_sessions(id, tenant_id, created_at)
+ VALUES (?, ?, ?)
+ """,
+ (str(session.id), session.tenant_id, session.created_at.isoformat()),
+ )
+ existing = self.get_session(session.id)
+ if existing.tenant_id != session.tenant_id:
+ raise ValueError("session tenant mismatch")
+ return existing
+
+ def count_tenants(self) -> tuple[str, ...]:
+ with self._connect() as connection:
+ rows = connection.execute(
+ "SELECT DISTINCT tenant_id FROM server_sessions ORDER BY tenant_id"
+ ).fetchall()
+ return tuple(row["tenant_id"] for row in rows)
+
+ def create_feedback(
+ self,
+ *,
+ tenant_id: str,
+ run_id: UUID,
+ key: str,
+ score: float | None,
+ value: str | None,
+ ) -> FeedbackRecord:
+ item = FeedbackRecord(
+ uuid4(),
+ tenant_id,
+ run_id,
+ key,
+ score,
+ value,
+ datetime.now(timezone.utc),
+ )
+ with self._connect() as connection:
+ connection.execute(
+ """
+ INSERT INTO feedback(
+ id, tenant_id, run_id, key, score, value, created_at
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ str(item.id),
+ item.tenant_id,
+ str(item.run_id),
+ item.key,
+ item.score,
+ item.value,
+ item.created_at.isoformat(),
+ ),
+ )
+ return item
+
+
+class PostgresResourceStore:
+ """Multi-replica resource store sharing the production Run schema."""
+
+ def __init__(self, run_store: PostgresRunStore) -> None:
+ self.run_store = run_store
+
+ def create_assistant(
+ self,
+ *,
+ tenant_id: str,
+ id: str,
+ template_id: str,
+ revision_id: UUID,
+ ) -> AssistantRecord:
+ item = AssistantRecord(
+ id, tenant_id, template_id, revision_id, datetime.now(timezone.utc)
+ )
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO server_assistants(
+ tenant_id, id, template_id, revision_id, created_at
+ ) VALUES (%s, %s, %s, %s, %s)
+ ON CONFLICT (tenant_id, id) DO NOTHING
+ """,
+ (tenant_id, id, template_id, revision_id, item.created_at),
+ )
+ existing = self.get_assistant(tenant_id, id)
+ if existing.template_id != template_id or existing.revision_id != revision_id:
+ raise ValueError("assistant id already has a different revision")
+ return existing
+
+ def get_assistant(self, tenant_id: str, id: str) -> AssistantRecord:
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ """
+ SELECT * FROM server_assistants
+ WHERE tenant_id = %s AND id = %s
+ """,
+ (tenant_id, id),
+ ).fetchone()
+ if row is None:
+ raise KeyError(id)
+ return AssistantRecord(
+ row["id"],
+ row["tenant_id"],
+ row["template_id"],
+ row["revision_id"],
+ row["created_at"],
+ )
+
+ def list_assistants(self, tenant_id: str) -> tuple[AssistantRecord, ...]:
+ with self.run_store.connection() as connection:
+ rows = connection.execute(
+ """
+ SELECT * FROM server_assistants
+ WHERE tenant_id = %s ORDER BY created_at, id
+ """,
+ (tenant_id,),
+ ).fetchall()
+ return tuple(
+ AssistantRecord(
+ row["id"],
+ row["tenant_id"],
+ row["template_id"],
+ row["revision_id"],
+ row["created_at"],
+ )
+ for row in rows
+ )
+
+ def create_session(self, tenant_id: str) -> SessionRecord:
+ value = SessionRecord(uuid4(), tenant_id, datetime.now(timezone.utc))
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO server_sessions(id, tenant_id, created_at)
+ VALUES (%s, %s, %s)
+ """,
+ (value.id, value.tenant_id, value.created_at),
+ )
+ return value
+
+ def get_session(self, session_id: UUID) -> SessionRecord:
+ with self.run_store.connection() as connection:
+ row = connection.execute(
+ "SELECT * FROM server_sessions WHERE id = %s", (session_id,)
+ ).fetchone()
+ if row is None:
+ raise KeyError(str(session_id))
+ return SessionRecord(row["id"], row["tenant_id"], row["created_at"])
+
+ def ensure_session(self, session: SessionRecord) -> SessionRecord:
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO server_sessions(id, tenant_id, created_at)
+ VALUES (%s, %s, %s) ON CONFLICT (id) DO NOTHING
+ """,
+ (session.id, session.tenant_id, session.created_at),
+ )
+ existing = self.get_session(session.id)
+ if existing.tenant_id != session.tenant_id:
+ raise ValueError("session tenant mismatch")
+ return existing
+
+ def count_tenants(self) -> tuple[str, ...]:
+ with self.run_store.connection() as connection:
+ rows = connection.execute(
+ "SELECT DISTINCT tenant_id FROM server_sessions ORDER BY tenant_id"
+ ).fetchall()
+ return tuple(row["tenant_id"] for row in rows)
+
+ def create_feedback(
+ self,
+ *,
+ tenant_id: str,
+ run_id: UUID,
+ key: str,
+ score: float | None,
+ value: str | None,
+ ) -> FeedbackRecord:
+ item = FeedbackRecord(
+ uuid4(),
+ tenant_id,
+ run_id,
+ key,
+ score,
+ value,
+ datetime.now(timezone.utc),
+ )
+ with self.run_store.connection() as connection:
+ connection.execute(
+ """
+ INSERT INTO feedback(
+ id, tenant_id, run_id, key, score, value, created_at
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s)
+ """,
+ (
+ item.id,
+ item.tenant_id,
+ item.run_id,
+ item.key,
+ item.score,
+ item.value,
+ item.created_at,
+ ),
+ )
+ return item
+
+
+def default_resource_store(run_store: RunStore) -> ResourceStore:
+ if isinstance(run_store, SQLiteRunStore):
+ return SQLiteResourceStore(run_store)
+ if isinstance(run_store, PostgresRunStore):
+ return PostgresResourceStore(run_store)
+ return InMemoryResourceStore()
diff --git a/src/rath/session/persistence/paths.py b/src/rath/session/persistence/paths.py
index 1a15eb9..0ce9fa0 100644
--- a/src/rath/session/persistence/paths.py
+++ b/src/rath/session/persistence/paths.py
@@ -14,6 +14,7 @@
from uuid import UUID
from rath.config.paths import resolve_config_dir
+from rath.utils.ids import coerce_uuid_str
__all__ = [
"SESSIONS_DIR_NAME",
@@ -41,7 +42,8 @@ def session_file(session_id: UUID | str) -> Path:
Accepts either a :class:`uuid.UUID` or a string; both are normalized via
``str(id)`` so callers don't have to think about it.
"""
- return sessions_dir() / f"{session_id}{SESSION_FILE_SUFFIX}"
+ sid = coerce_uuid_str(session_id, field="session_id")
+ return sessions_dir() / f"{sid}{SESSION_FILE_SUFFIX}"
def session_partial_file(session_id: UUID | str) -> Path:
@@ -53,7 +55,8 @@ def session_partial_file(session_id: UUID | str) -> Path:
writing process crashed mid-session (or that the runtime drain timed
out and abandoned the writer).
"""
- return sessions_dir() / f"{session_id}{SESSION_PARTIAL_SUFFIX}"
+ sid = coerce_uuid_str(session_id, field="session_id")
+ return sessions_dir() / f"{sid}{SESSION_PARTIAL_SUFFIX}"
def ensure_sessions_dir() -> Path:
diff --git a/src/rath/utils/ids.py b/src/rath/utils/ids.py
new file mode 100644
index 0000000..48500f7
--- /dev/null
+++ b/src/rath/utils/ids.py
@@ -0,0 +1,23 @@
+"""Identifier normalization helpers for filesystem-backed persistence."""
+
+from __future__ import annotations
+
+from uuid import UUID
+
+__all__ = ["coerce_uuid_str"]
+
+
+def coerce_uuid_str(value: UUID | str, *, field: str = "id") -> str:
+ """Return ``value`` as a canonical UUID string or raise ``ValueError``.
+
+ Persistence identifiers are used as path components. Accepting arbitrary
+ strings here would make path traversal possible, so string inputs must be
+ parseable UUIDs before they can reach filesystem helpers.
+ """
+
+ if isinstance(value, UUID):
+ return str(value)
+ try:
+ return str(UUID(str(value)))
+ except ValueError as exc:
+ raise ValueError(f"{field} must be a UUID") from exc
diff --git a/tests/artifacts/test_artifact_store.py b/tests/artifacts/test_artifact_store.py
new file mode 100644
index 0000000..ded914e
--- /dev/null
+++ b/tests/artifacts/test_artifact_store.py
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+import io
+from pathlib import Path
+
+import pytest
+
+from rath.artifacts import ArtifactNotFound, LocalArtifactStore, S3ArtifactStore
+
+
+def test_local_artifact_is_content_addressed_and_tenant_scoped(
+ tmp_path: Path,
+) -> None:
+ store = LocalArtifactStore(tmp_path / "artifacts")
+ first = store.put(
+ "tenant-a",
+ io.BytesIO(b"durable result"),
+ media_type="text/plain",
+ metadata={"run_id": "run-1"},
+ )
+ duplicate = store.put("tenant-a", b"durable result", media_type="text/plain")
+
+ assert first.digest == duplicate.digest
+ assert first.uri.startswith("artifact://tenant-a/")
+ assert store.get("tenant-a", first.digest) == b"durable result"
+ with pytest.raises(ArtifactNotFound):
+ store.get("tenant-b", first.digest)
+
+
+def test_local_artifact_enforces_size_identity_and_deletion(tmp_path: Path) -> None:
+ store = LocalArtifactStore(tmp_path / "artifacts", max_bytes=3)
+ with pytest.raises(ValueError, match="size"):
+ store.put("tenant", b"four")
+ with pytest.raises(ValueError, match="unsafe"):
+ store.put("../tenant", b"x")
+
+ artifact = store.put("tenant", b"one")
+ payload = tmp_path / "artifacts" / "tenant" / artifact.digest[:2] / artifact.digest
+ payload.write_bytes(b"corrupt")
+ with pytest.raises(OSError, match="verification"):
+ store.get("tenant", artifact.digest)
+ assert store.delete("tenant", artifact.digest)
+ assert not store.delete("tenant", artifact.digest)
+
+
+def test_s3_artifact_stops_reading_after_configured_limit() -> None:
+ class _Client:
+ def put_object(self, **kwargs): # type: ignore[no-untyped-def]
+ raise AssertionError("oversized content must not be uploaded")
+
+ class _Stream:
+ def __init__(self) -> None:
+ self.reads = 0
+
+ def read(self, size: int) -> bytes:
+ self.reads += 1
+ return b"x" * size
+
+ stream = _Stream()
+ store = S3ArtifactStore(
+ "bucket",
+ client=_Client(),
+ max_bytes=3,
+ )
+
+ with pytest.raises(ValueError, match="size"):
+ store.put("tenant", stream)
+ assert stream.reads == 1
+
+
+def test_s3_artifact_streams_staged_payload_and_cleans_orphan() -> None:
+ class _Client:
+ def __init__(self) -> None:
+ self.calls = 0
+ self.deleted: list[str] = []
+
+ def put_object(self, **kwargs): # type: ignore[no-untyped-def]
+ self.calls += 1
+ if self.calls == 1:
+ body = kwargs["Body"]
+ assert not isinstance(body, bytes)
+ assert body.read() == b"streamed"
+ return {}
+ raise RuntimeError("manifest failed")
+
+ def delete_objects(self, **kwargs): # type: ignore[no-untyped-def]
+ self.deleted.extend(item["Key"] for item in kwargs["Delete"]["Objects"])
+
+ client = _Client()
+ store = S3ArtifactStore("bucket", client=client)
+
+ with pytest.raises(RuntimeError, match="manifest"):
+ store.put("tenant", io.BytesIO(b"streamed"))
+
+ assert len(client.deleted) == 1
+ assert not client.deleted[0].endswith(".json")
diff --git a/tests/backends/persistence/test_registry_gc.py b/tests/backends/persistence/test_registry_gc.py
index 812d1d6..5649099 100644
--- a/tests/backends/persistence/test_registry_gc.py
+++ b/tests/backends/persistence/test_registry_gc.py
@@ -56,6 +56,17 @@ def test_ensure_local_idempotent(_isolate_openrath_home: Path) -> None:
assert first.is_dir()
+@pytest.mark.parametrize("bad_id", ["../escape", "/tmp/escape", "not-a-uuid"])
+def test_sandbox_paths_reject_path_like_ids(
+ _isolate_openrath_home: Path,
+ bad_id: str,
+) -> None:
+ with pytest.raises(ValueError, match="sandbox_id must be a UUID"):
+ local_sandbox_dir(bad_id)
+ with pytest.raises(ValueError, match="sandbox_id must be a UUID"):
+ opensandbox_index_path(bad_id)
+
+
def test_list_local_enumerates_uuid_dirs(_isolate_openrath_home: Path) -> None:
reg = PersistentSandboxRegistry()
ids = {reg.alloc_local_id() for _ in range(3)}
diff --git a/tests/backends/test_local.py b/tests/backends/test_local.py
index 30cc7b2..9702de7 100644
--- a/tests/backends/test_local.py
+++ b/tests/backends/test_local.py
@@ -19,7 +19,7 @@
ToolExecutionFailure,
get,
)
-from rath.backend.local import LocalBackend
+from rath.backend.local import LocalBackend, TrustedHostBackend
def test_is_available_is_true() -> None:
@@ -53,6 +53,13 @@ def test_local_is_registered_under_name_local() -> None:
assert inst.name == "local"
+def test_trusted_host_is_the_canonical_explicit_backend_name() -> None:
+ inst = get("trusted-host")
+ assert isinstance(inst, TrustedHostBackend)
+ assert not isinstance(inst, LocalBackend)
+ assert inst.name == "trusted-host"
+
+
def test_handle_is_a_real_working_directory() -> None:
backend = get("local")
sb = backend.open()
@@ -98,6 +105,90 @@ def test_close_does_not_remove_user_supplied_working_dir(tmp_path: object) -> No
assert sentinel.read_text(encoding="utf-8") == "do not delete me"
+def test_filesystem_calls_reject_absolute_paths_outside_workspace(
+ tmp_path: object,
+) -> None:
+ import pathlib
+
+ root = pathlib.Path(str(tmp_path)) / "workspace" # type: ignore[arg-type]
+ outside = pathlib.Path(str(tmp_path)) / "outside.txt" # type: ignore[arg-type]
+ root.mkdir()
+ outside.write_text("secret", encoding="utf-8")
+ backend = LocalBackend()
+ sb = backend.open(BackendSandboxSpec(working_dir=str(root)))
+ try:
+ result = sb.dispatch(BackendToolFilesRead(path=str(outside)))
+ finally:
+ backend.close(sb)
+
+ assert isinstance(result, ToolExecutionFailure)
+ assert result.kind == "path_violation"
+ assert "outside sandbox workspace" in result.message
+
+
+def test_filesystem_calls_reject_parent_traversal(tmp_path: object) -> None:
+ import pathlib
+
+ root = pathlib.Path(str(tmp_path)) / "workspace" # type: ignore[arg-type]
+ root.mkdir()
+ backend = LocalBackend()
+ sb = backend.open(BackendSandboxSpec(working_dir=str(root)))
+ try:
+ result = sb.dispatch(BackendToolFilesWrite(path="../escape.txt", data="x"))
+ finally:
+ backend.close(sb)
+
+ assert isinstance(result, ToolExecutionFailure)
+ assert result.kind == "path_violation"
+ assert not (root.parent / "escape.txt").exists()
+
+
+def test_command_cwd_must_remain_in_workspace(tmp_path: object) -> None:
+ import pathlib
+
+ root = pathlib.Path(str(tmp_path)) / "workspace" # type: ignore[arg-type]
+ root.mkdir()
+ backend = LocalBackend()
+ sb = backend.open(BackendSandboxSpec(working_dir=str(root)))
+ try:
+ result = sb.dispatch(
+ BackendToolCommandRun(
+ cmd=[sys.executable, "-c", "print('should not run')"],
+ cwd="..",
+ )
+ )
+ finally:
+ backend.close(sb)
+
+ assert isinstance(result, ToolExecutionFailure)
+ assert result.kind == "path_violation"
+
+
+def test_symlink_escape_is_rejected_when_supported(tmp_path: object) -> None:
+ import pathlib
+
+ root = pathlib.Path(str(tmp_path)) / "workspace" # type: ignore[arg-type]
+ outside = pathlib.Path(str(tmp_path)) / "outside" # type: ignore[arg-type]
+ root.mkdir()
+ outside.mkdir()
+ (outside / "secret.txt").write_text("secret", encoding="utf-8")
+ link = root / "link"
+ try:
+ link.symlink_to(outside, target_is_directory=True)
+ except OSError:
+ pytest.skip("symlink creation is unavailable")
+
+ backend = LocalBackend()
+ sb = backend.open(BackendSandboxSpec(working_dir=str(root)))
+ try:
+ result = sb.dispatch(BackendToolFilesRead(path="link/secret.txt"))
+ finally:
+ backend.close(sb)
+
+ assert isinstance(result, ToolExecutionFailure)
+ assert result.kind == "path_violation"
+
+
def test_command_missing_executable_returns_failure() -> None:
backend = get("local")
with backend.open() as sb:
diff --git a/tests/backends/test_opensandbox_async.py b/tests/backends/test_opensandbox_async.py
index 0992878..6d55ed5 100644
--- a/tests/backends/test_opensandbox_async.py
+++ b/tests/backends/test_opensandbox_async.py
@@ -6,8 +6,8 @@
per-sandbox exec lock.
- Concurrent ``files.write`` to the *same* path serialise behind the
per-path fs lock (last-writer-wins is deterministic; no torn payloads).
-- Concurrent ``files.write`` to *distinct* paths run in parallel.
-- Concurrent reads do not serialise behind any lock.
+- Concurrent ``files.write`` to *distinct* paths do not clobber one another.
+- Concurrent reads return complete payloads under thread contention.
These tests require a reachable opensandbox-server (see ``conftest.py``'s
``opensandbox_real`` marker). There is no ``FakeSandbox`` fallback — the suite
@@ -29,7 +29,7 @@
from rath.backend.opensandbox import OpenSandboxBackend
from tests.conftest import opensandbox_real
-pytestmark = opensandbox_real
+pytestmark = [opensandbox_real, pytest.mark.opensandbox]
@pytest.fixture
@@ -47,8 +47,8 @@ def os_sandbox():
backend.close(sb)
-def test_concurrent_distinct_path_writes_run_in_parallel(os_sandbox) -> None:
- """Writes to N distinct paths complete in < None:
+ """Concurrent writes to N distinct paths all commit their own payload."""
backend, sb = os_sandbox
n = 8
payloads = {f"distinct_{i}.txt": f"v{i}".encode() for i in range(n)}
@@ -57,23 +57,10 @@ def write_one(name: str) -> int:
r = sb.dispatch(BackendToolFilesWrite(path=name, data=payloads[name]))
return getattr(r, "bytes_written", -1)
- # Warm-up one write so we have a per-call baseline.
- t0 = time.perf_counter()
- write_one(next(iter(payloads.keys())))
- per_call = time.perf_counter() - t0
-
- start = time.perf_counter()
with ThreadPoolExecutor(max_workers=n) as pool:
results = list(pool.map(write_one, payloads.keys()))
- elapsed = time.perf_counter() - start
assert all(r > 0 for r in results)
- # If they serialised, we'd expect ~n × per_call. Parallel should beat
- # serial by at least 2×. Generous to avoid CI flake against a real server.
- assert elapsed < per_call * n * 0.7, (
- f"distinct-path writes did not run in parallel: "
- f"per-call ≈ {per_call:.2f}s, {n} parallel took {elapsed:.2f}s"
- )
for name, want in payloads.items():
r = sb.dispatch(BackendToolFilesRead(path=name, encoding=None))
@@ -135,8 +122,8 @@ def run_one(tag: str) -> tuple[str, int]:
assert "BEGIN" in out and "END" in out
-def test_concurrent_reads_do_not_serialise(os_sandbox) -> None:
- """Reads share no lock — N parallel reads complete much faster than serial."""
+def test_concurrent_reads_return_complete_payloads(os_sandbox) -> None:
+ """N concurrent reads all return the complete payload."""
backend, sb = os_sandbox
# Seed a file to read.
@@ -148,22 +135,7 @@ def read_one(_: int) -> bytes:
r = sb.dispatch(BackendToolFilesRead(path="readable.txt", encoding=None))
return getattr(r, "data", b"")
- # Baseline.
- t0 = time.perf_counter()
- read_one(0)
- per_call = time.perf_counter() - t0
-
- start = time.perf_counter()
with ThreadPoolExecutor(max_workers=n) as pool:
results = list(pool.map(read_one, range(n)))
- elapsed = time.perf_counter() - start
assert all(r == b"hello" for r in results)
- # Generous bound: parallel reads should be at most ~2× a single read.
- # Skip the overlap assertion when per-call latency is sub-ms (the
- # serial baseline is dominated by fixed overhead, not the lock).
- if per_call > 0.01:
- assert elapsed < per_call * n * 0.7, (
- f"reads appear serialised: per-call ≈ {per_call:.2f}s, "
- f"{n} parallel took {elapsed:.2f}s"
- )
diff --git a/tests/backends/test_opensandbox_ci_stability.py b/tests/backends/test_opensandbox_ci_stability.py
index 3b82b7f..9cc42ca 100644
--- a/tests/backends/test_opensandbox_ci_stability.py
+++ b/tests/backends/test_opensandbox_ci_stability.py
@@ -2,18 +2,23 @@
from __future__ import annotations
+import asyncio
from pathlib import Path
+from types import SimpleNamespace
import pytest
+import rath.backend.opensandbox as opensandbox_adapter
from rath.backend.opensandbox import (
_command_stdout_rerun_allowed,
_is_transient_code_run_result,
_is_transient_sandbox_create_error,
+ _run_code_with_retry,
_should_retry_command_for_empty_stdout,
)
pytest.importorskip("opensandbox")
+from code_interpreter import CodeInterpreter # noqa: E402
from opensandbox.exceptions import SandboxInternalException # noqa: E402
from opensandbox.models.execd import ( # noqa: E402
Execution,
@@ -73,8 +78,6 @@ def test_command_stdout_rerun_limited_to_print_probes() -> None:
def test_transient_code_run_detects_busy_session() -> None:
- from types import SimpleNamespace
-
execution = SimpleNamespace(
error=SimpleNamespace(value="error running codes session is busy")
)
@@ -82,14 +85,41 @@ def test_transient_code_run_detects_busy_session() -> None:
def test_transient_code_run_ignores_real_failures() -> None:
- from types import SimpleNamespace
-
execution = SimpleNamespace(
error=SimpleNamespace(value="SyntaxError: invalid syntax"),
)
assert not _is_transient_code_run_result(execution)
+def test_busy_result_after_client_timeout_stays_a_timeout(monkeypatch) -> None:
+ calls = 0
+ busy = SimpleNamespace(
+ error=SimpleNamespace(value="error running codes session is busy")
+ )
+
+ class FakeCodes:
+ async def run(self, source, *, language): # type: ignore[no-untyped-def]
+ return None
+
+ async def fake_create(native): # type: ignore[no-untyped-def]
+ return SimpleNamespace(codes=FakeCodes())
+
+ async def fake_await(awaitable, timeout): # type: ignore[no-untyped-def]
+ nonlocal calls
+ await awaitable
+ calls += 1
+ if calls == 1:
+ raise TimeoutError("client deadline")
+ return busy
+
+ monkeypatch.setattr(CodeInterpreter, "create", staticmethod(fake_create))
+ monkeypatch.setattr(opensandbox_adapter, "_await_maybe_timeout", fake_await)
+ monkeypatch.setattr(opensandbox_adapter, "_CODE_RUN_BACKOFF_S", (0.0,))
+
+ with pytest.raises(TimeoutError, match="remained busy after timeout"):
+ asyncio.run(_run_code_with_retry(object(), "pass", "python", 0.5))
+
+
def test_transient_create_error_rejects_bind_rejection() -> None:
exc = ValueError("host path not under any allowed prefix")
assert not _is_transient_sandbox_create_error(exc)
diff --git a/tests/chaos/test_runtime_failures.py b/tests/chaos/test_runtime_failures.py
new file mode 100644
index 0000000..d3731f3
--- /dev/null
+++ b/tests/chaos/test_runtime_failures.py
@@ -0,0 +1,87 @@
+from __future__ import annotations
+
+import threading
+from concurrent.futures import ThreadPoolExecutor
+from pathlib import Path
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import LocalRuntime, RunStatus, SQLiteRunStore
+from rath.session import Session
+
+
+def test_cancel_wins_over_late_worker_checkpoint(tmp_path: Path) -> None:
+ entered = threading.Event()
+ release = threading.Event()
+
+ class _Blocked(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def wait(self, state, context): # type: ignore[no-untyped-def]
+ entered.set()
+ release.wait(timeout=5)
+ return {"late": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ submitted = runtime.submit(
+ _Blocked(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ with ThreadPoolExecutor(max_workers=1) as pool:
+ worker = pool.submit(runtime.work_once, worker_id="worker", lease_seconds=1)
+ assert entered.wait(timeout=2)
+ running = store.get_run(submitted.id)
+ cancelled = store.transition_run(
+ running.id,
+ expected_version=running.version,
+ target=RunStatus.CANCELLED,
+ )
+ release.set()
+ result = worker.result(timeout=5)
+
+ assert result is not None
+ assert result.status is RunStatus.CANCELLED
+ assert store.get_run(submitted.id) == cancelled
+ assert store.latest_checkpoint(submitted.id) is None
+
+
+def test_duplicate_submission_does_not_duplicate_execution(tmp_path: Path) -> None:
+ executions = 0
+
+ class _Count(Workflow):
+ @step(entry=True, effects=EffectClass.IDEMPOTENT)
+ def count(self, state, context): # type: ignore[no-untyped-def]
+ nonlocal executions
+ executions += 1
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ context = RunContext.local(revision_id=uuid4())
+ workflow = _Count()
+ session_id = uuid4()
+ first = runtime.submit(
+ workflow,
+ session_id=session_id,
+ context=context,
+ idempotency_key="delivery-1",
+ )
+ second = runtime.submit(
+ workflow,
+ session_id=session_id,
+ context=context,
+ idempotency_key="delivery-1",
+ )
+ runtime.work_once(worker_id="worker")
+
+ assert first.id == second.id
+ assert executions == 1
diff --git a/tests/config/test_credentials_split.py b/tests/config/test_credentials_split.py
index f007a62..c488336 100644
--- a/tests/config/test_credentials_split.py
+++ b/tests/config/test_credentials_split.py
@@ -146,3 +146,23 @@ def test_inline_key_takes_precedence_over_credentials(
)
store = ConfigStore.load()
assert store.get_llm_provider("main").api_key == "sk-inline"
+
+
+def test_removing_last_key_deletes_stale_credentials_sidecar(
+ _isolate_openrath_home: Path,
+) -> None:
+ store = ConfigStore(path=resolve_config_path())
+ store.config.llm.providers["main"] = LLMProviderConfig(
+ provider_kind="openai",
+ model="gpt-5",
+ api_key="sk-remove-me",
+ )
+ store.save()
+ assert _credentials_path().is_file()
+
+ store.config.llm.providers["main"].api_key = None
+ store.save()
+
+ assert not _credentials_path().exists()
+ reloaded = ConfigStore(path=resolve_config_path())
+ assert reloaded.get_llm_provider("main").api_key is None
diff --git a/tests/conformance/v2/test_adapter_contracts.py b/tests/conformance/v2/test_adapter_contracts.py
new file mode 100644
index 0000000..096f399
--- /dev/null
+++ b/tests/conformance/v2/test_adapter_contracts.py
@@ -0,0 +1,327 @@
+from __future__ import annotations
+
+import asyncio
+from uuid import uuid4
+
+import pytest
+
+from rath.adapters import (
+ AdapterRequestContext,
+ ApprovalGrant,
+ MemoryExecutor,
+ MemoryNamespace,
+ ProviderCapability,
+ ProviderExecutor,
+ ProviderSpec,
+ SandboxExecutor,
+ SandboxIsolation,
+ SandboxSpec,
+ SchemaValidationError,
+ ToolExecutor,
+ ToolOutputTooLarge,
+ ToolSpec,
+)
+from rath.artifacts import LocalArtifactStore
+from rath.context import RunContext
+from rath.definition import EffectClass
+from rath.runtime import arguments_digest
+from rath.security import (
+ LocalTrustedPolicy,
+ PolicyConstraints,
+ PolicyDecision,
+ PolicyEffect,
+ TrustLevel,
+)
+
+
+def _contexts(): # type: ignore[no-untyped-def]
+ run = RunContext.local(revision_id=uuid4())
+ adapter = AdapterRequestContext(
+ run_id=uuid4(),
+ node_id="tool",
+ tenant_id="local",
+ deadline=None,
+ trace_context=run.trace_context,
+ idempotency_key="key",
+ policy_constraints=PolicyConstraints(max_output_bytes=32),
+ )
+ return run, adapter
+
+
+def test_tool_schema_is_validated_before_handler() -> None:
+ called = False
+
+ def handler(arguments, context): # type: ignore[no-untyped-def]
+ nonlocal called
+ called = True
+ return {"ok": True}
+
+ run, adapter = _contexts()
+ spec = ToolSpec(
+ name="search",
+ version="1",
+ input_schema={
+ "type": "object",
+ "required": ["query"],
+ "properties": {"query": {"type": "string"}},
+ "additionalProperties": False,
+ },
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ )
+ with pytest.raises(SchemaValidationError):
+ asyncio.run(
+ ToolExecutor(LocalTrustedPolicy()).execute(
+ spec,
+ handler,
+ {"unknown": True},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ )
+ assert called is False
+
+
+def test_tool_output_budget_is_enforced() -> None:
+ run, adapter = _contexts()
+ spec = ToolSpec(
+ name="large",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ )
+ with pytest.raises(ToolOutputTooLarge):
+ asyncio.run(
+ ToolExecutor(LocalTrustedPolicy()).execute(
+ spec,
+ lambda arguments, context: {"data": "x" * 100},
+ {},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ )
+
+
+def test_large_output_can_be_externalized_to_artifact_store(tmp_path) -> None:
+ run, adapter = _contexts()
+ spec = ToolSpec(
+ name="report",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ )
+ result = asyncio.run(
+ ToolExecutor(
+ LocalTrustedPolicy(),
+ artifact_store=LocalArtifactStore(tmp_path / "artifacts"),
+ ).execute(
+ spec,
+ lambda arguments, context: {"data": "x" * 100},
+ {},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ )
+
+ assert result["artifact_uri"].startswith("artifact://local/")
+ assert result["size"] > 32
+
+
+def test_tool_rejects_adapter_tenant_mismatch() -> None:
+ run, adapter = _contexts()
+ mismatched = AdapterRequestContext(
+ run_id=adapter.run_id,
+ node_id=adapter.node_id,
+ tenant_id="other-tenant",
+ deadline=adapter.deadline,
+ trace_context=adapter.trace_context,
+ idempotency_key=adapter.idempotency_key,
+ policy_constraints=adapter.policy_constraints,
+ )
+ spec = ToolSpec(
+ name="lookup",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ )
+
+ with pytest.raises(PermissionError, match="tenant mismatch"):
+ asyncio.run(
+ ToolExecutor(LocalTrustedPolicy()).execute(
+ spec,
+ lambda arguments, context: {},
+ {},
+ adapter_context=mismatched,
+ run_context=run,
+ )
+ )
+
+
+def test_tool_enforces_declared_async_timeout() -> None:
+ run, adapter = _contexts()
+ spec = ToolSpec(
+ name="slow",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ timeout_seconds=0.01,
+ )
+
+ async def slow(arguments, context): # type: ignore[no-untyped-def]
+ await asyncio.sleep(1)
+ return {}
+
+ with pytest.raises(asyncio.TimeoutError):
+ asyncio.run(
+ ToolExecutor(LocalTrustedPolicy()).execute(
+ spec,
+ slow,
+ {},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ )
+
+
+def test_tool_requires_a_verified_durable_approval_grant() -> None:
+ run, adapter = _contexts()
+ spec = ToolSpec(
+ name="charge",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.NON_IDEMPOTENT,
+ risk="high",
+ )
+ arguments = {"amount": 10}
+ grant = ApprovalGrant(
+ decision_id=uuid4(),
+ run_id=adapter.run_id,
+ node_id=adapter.node_id,
+ tenant_id=adapter.tenant_id,
+ tool_id="charge@1",
+ arguments_digest=arguments_digest(arguments),
+ actor_id="reviewer",
+ )
+
+ with pytest.raises(PermissionError, match="cannot be verified"):
+ asyncio.run(
+ ToolExecutor(LocalTrustedPolicy()).execute(
+ spec,
+ lambda values, context: {"charged": True},
+ arguments,
+ adapter_context=adapter,
+ run_context=run,
+ approval=grant,
+ )
+ )
+
+ result = asyncio.run(
+ ToolExecutor(
+ LocalTrustedPolicy(),
+ approval_validator=lambda value: value.decision_id == grant.decision_id,
+ ).execute(
+ spec,
+ lambda values, context: {"charged": True},
+ arguments,
+ adapter_context=adapter,
+ run_context=run,
+ approval=grant,
+ )
+ )
+ assert result == {"charged": True}
+
+
+def test_provider_sandbox_and_memory_share_context_policy_timeout_contract() -> None:
+ async def exercise() -> None:
+ run, adapter = _contexts()
+ policy = LocalTrustedPolicy()
+ provider_result = await ProviderExecutor(policy).execute(
+ ProviderSpec(
+ id="chat",
+ kind="openai",
+ model="gpt",
+ capabilities=frozenset({ProviderCapability.CHAT}),
+ ),
+ lambda request, spec, context: {"text": "ok"},
+ {"messages": []},
+ capability=ProviderCapability.CHAT,
+ adapter_context=adapter,
+ run_context=run,
+ )
+ sandbox_result = await SandboxExecutor(policy).execute(
+ SandboxSpec(
+ id="local",
+ isolation=SandboxIsolation.TRUSTED_HOST,
+ network="deny",
+ ),
+ lambda operation, payload, spec, context: {"exit_code": 0},
+ "command",
+ {"argv": ["true"]},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ memory_result = await MemoryExecutor(policy).execute(
+ lambda operation, namespace, payload, context: {"items": []},
+ "search",
+ MemoryNamespace(tenant_id="local", trust=TrustLevel.UNTRUSTED),
+ {"query": "q"},
+ adapter_context=adapter,
+ run_context=run,
+ )
+
+ assert provider_result == {"text": "ok"}
+ assert sandbox_result == {"exit_code": 0}
+ assert memory_result == {"items": []}
+
+ asyncio.run(exercise())
+
+
+def test_evaluated_policy_constraints_reach_adapter_handler() -> None:
+ class _ConstrainedPolicy:
+ async def evaluate(self, action, resource, context): # type: ignore[no-untyped-def]
+ return PolicyDecision(
+ effect=PolicyEffect.ALLOW_WITH_CONSTRAINTS,
+ reason="bounded",
+ policy_id="test",
+ constraints=PolicyConstraints(
+ timeout_seconds=1,
+ max_output_bytes=8,
+ read_only=True,
+ redactions=frozenset({"secret"}),
+ ),
+ )
+
+ seen: PolicyConstraints | None = None
+
+ def handler(arguments, context): # type: ignore[no-untyped-def]
+ nonlocal seen
+ seen = context.policy_constraints
+ return {}
+
+ run, adapter = _contexts()
+ asyncio.run(
+ ToolExecutor(_ConstrainedPolicy()).execute(
+ ToolSpec(
+ name="bounded",
+ version="1",
+ input_schema={"type": "object"},
+ effects=EffectClass.READ_ONLY,
+ risk="low",
+ timeout_seconds=10,
+ ),
+ handler,
+ {},
+ adapter_context=adapter,
+ run_context=run,
+ )
+ )
+
+ assert seen is not None
+ assert seen.timeout_seconds == 1
+ assert seen.max_output_bytes == 8
+ assert seen.read_only is True
+ assert seen.redactions == frozenset({"secret"})
diff --git a/tests/core/test_events.py b/tests/core/test_events.py
new file mode 100644
index 0000000..2780325
--- /dev/null
+++ b/tests/core/test_events.py
@@ -0,0 +1,68 @@
+from __future__ import annotations
+
+from datetime import datetime
+from uuid import uuid4
+
+import pytest
+
+from rath.events import Event, EventKind, ProducerRef, SessionEventLog
+from rath.security import Provenance, TrustLevel
+
+
+def _event(*, session_id, sequence: int, payload=None) -> Event: # type: ignore[no-untyped-def]
+ return Event.create(
+ session_id=session_id,
+ sequence=sequence,
+ kind=EventKind.MESSAGE_CREATED,
+ payload=payload or {"content": "hello"},
+ producer=ProducerRef(kind="user", id="user-1"),
+ trust=TrustLevel.UNTRUSTED,
+ provenance=Provenance(source_type="user", source_id="user-1"),
+ )
+
+
+def test_event_payload_is_deeply_immutable() -> None:
+ session_id = uuid4()
+ payload = {"parts": [{"text": "hello"}]}
+ event = _event(session_id=session_id, sequence=1, payload=payload)
+
+ payload["parts"][0]["text"] = "changed"
+
+ assert event.payload["parts"][0]["text"] == "hello" # type: ignore[index]
+ with pytest.raises(TypeError):
+ event.payload["new"] = True # type: ignore[index]
+ assert event.created_at.tzinfo is not None
+
+
+def test_session_event_log_requires_monotonic_contiguous_sequence() -> None:
+ session_id = uuid4()
+ first = _event(session_id=session_id, sequence=1)
+ third = _event(session_id=session_id, sequence=3)
+
+ with pytest.raises(ValueError, match="contiguous"):
+ SessionEventLog(id=session_id, events=(first, third))
+
+
+def test_session_event_log_rejects_cross_session_event() -> None:
+ session_id = uuid4()
+ with pytest.raises(ValueError, match="session_id"):
+ SessionEventLog(
+ id=session_id,
+ events=(_event(session_id=uuid4(), sequence=1),),
+ )
+
+
+def test_append_assigns_next_sequence_without_mutating_original() -> None:
+ session_id = uuid4()
+ log = SessionEventLog(id=session_id)
+ updated = log.append(
+ kind=EventKind.MESSAGE_CREATED,
+ payload={"content": "hello"},
+ producer=ProducerRef(kind="user", id="user-1"),
+ trust=TrustLevel.UNTRUSTED,
+ provenance=Provenance(source_type="user", source_id="user-1"),
+ )
+
+ assert log.events == ()
+ assert updated.events[0].sequence == 1
+ assert isinstance(updated.events[0].created_at, datetime)
diff --git a/tests/definition/test_compiler_v2.py b/tests/definition/test_compiler_v2.py
new file mode 100644
index 0000000..3f8cef4
--- /dev/null
+++ b/tests/definition/test_compiler_v2.py
@@ -0,0 +1,145 @@
+from __future__ import annotations
+
+from uuid import uuid4
+
+import pytest
+
+from rath.definition import (
+ DefinitionError,
+ EffectClass,
+ NodeKind,
+ RetryPolicy,
+ WorkflowCompiler,
+ router,
+ step,
+)
+from rath.flow import Workflow
+from rath.session import Session
+
+
+class _Research(Workflow):
+ @step(
+ entry=True,
+ successors=("route",),
+ retry=RetryPolicy(max_attempts=3),
+ effects=EffectClass.READ_ONLY,
+ )
+ async def search(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ @router(successors=("write", "review"))
+ def route(self, state): # type: ignore[no-untyped-def]
+ return "write"
+
+ @step()
+ def review(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ @step()
+ def write(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def test_compiler_produces_deterministic_immutable_plan() -> None:
+ revision_id = uuid4()
+ first = WorkflowCompiler().compile(_Research(), revision_id=revision_id)
+ second = WorkflowCompiler().compile(_Research(), revision_id=revision_id)
+
+ assert first.id == second.id
+ assert first.definition_hash == second.definition_hash
+ assert first.revision_id == revision_id
+ assert tuple(node.id for node in first.nodes) == (
+ "review",
+ "route",
+ "search",
+ "write",
+ )
+ route_node = next(node for node in first.nodes if node.id == "route")
+ assert route_node.kind is NodeKind.ROUTER
+ assert route_node.successors == ("write", "review")
+ search_node = next(node for node in first.nodes if node.id == "search")
+ assert search_node.retry.max_attempts == 3
+ assert search_node.effects is EffectClass.READ_ONLY
+ assert first.durable is True
+
+
+def test_workflow_compile_plan_is_public_convenience_api() -> None:
+ plan = _Research().compile_plan(revision_id=uuid4())
+ assert plan.definition.entrypoint == "search"
+ assert plan.definition.version == "1"
+
+
+def test_unknown_router_successor_fails_compile() -> None:
+ class _Broken(Workflow):
+ @router(entry=True, successors=("missing",))
+ def route(self, state): # type: ignore[no-untyped-def]
+ return "missing"
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ with pytest.raises(DefinitionError, match="unknown successor"):
+ WorkflowCompiler().compile(_Broken(), revision_id=uuid4())
+
+
+def test_multiple_entry_steps_fail_compile() -> None:
+ class _Broken(Workflow):
+ @step(entry=True)
+ def one(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ @step(entry=True)
+ def two(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ with pytest.raises(DefinitionError, match="exactly one entrypoint"):
+ WorkflowCompiler().compile(_Broken(), revision_id=uuid4())
+
+
+def test_legacy_workflow_compiles_as_opaque_non_durable_plan() -> None:
+ class _Legacy(Workflow):
+ def forward(self, session: Session) -> Session:
+ return session
+
+ plan = WorkflowCompiler().compile(_Legacy(), revision_id=uuid4())
+
+ assert plan.durable is False
+ assert plan.nodes[0].kind is NodeKind.OPAQUE
+ assert any("checkpoint" in issue for issue in plan.compatibility_issues)
+
+
+def test_step_metadata_rejects_unsafe_retry_contract() -> None:
+ with pytest.raises(ValueError, match="idempotency"):
+
+ @step(
+ retry=RetryPolicy(max_attempts=2),
+ effects=EffectClass.NON_IDEMPOTENT,
+ )
+ def unsafe(state, context): # type: ignore[no-untyped-def]
+ return state
+
+
+def test_production_durable_rejects_sync_step_timeout() -> None:
+ class _TimedSync(Workflow):
+ @step(entry=True, timeout_seconds=0.1)
+ def run(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ with pytest.raises(
+ DefinitionError,
+ match="synchronous durable steps cannot guarantee preemptive timeout",
+ ):
+ WorkflowCompiler().compile(
+ _TimedSync(),
+ revision_id=uuid4(),
+ production_durable=True,
+ )
diff --git a/tests/definition/test_definition_identity_regression.py b/tests/definition/test_definition_identity_regression.py
new file mode 100644
index 0000000..b3fa106
--- /dev/null
+++ b/tests/definition/test_definition_identity_regression.py
@@ -0,0 +1,38 @@
+from __future__ import annotations
+
+from uuid import uuid4
+
+from rath.definition import EffectClass, WorkflowCompiler, step
+from rath.flow import Workflow
+from rath.session import Session
+
+
+def test_handler_implementation_change_changes_definition_identity() -> None:
+ class _ImplementationIdentity(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def execute(self, state, context): # type: ignore[no-untyped-def]
+ return {"value": 1}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ revision_id = uuid4()
+ compiler = WorkflowCompiler()
+ first = compiler.compile(_ImplementationIdentity(), revision_id=revision_id)
+
+ def replacement(self, state, context): # type: ignore[no-untyped-def]
+ return {"value": 999}
+
+ replacement.__name__ = "execute"
+ setattr(
+ _ImplementationIdentity,
+ "execute",
+ step(entry=True, effects=EffectClass.READ_ONLY)(replacement),
+ )
+ second = compiler.compile(
+ _ImplementationIdentity(),
+ revision_id=revision_id,
+ )
+
+ assert first.definition_hash != second.definition_hash
+ assert first.id != second.id
diff --git a/tests/definition/test_plan_serialization.py b/tests/definition/test_plan_serialization.py
new file mode 100644
index 0000000..20b548a
--- /dev/null
+++ b/tests/definition/test_plan_serialization.py
@@ -0,0 +1,43 @@
+from __future__ import annotations
+
+import json
+from uuid import uuid4
+
+from rath.definition import EffectClass, WorkflowCompiler, step
+from rath.flow import AgentParam, Workflow
+from rath.llm import Provider
+from rath.session import Session
+
+
+class _WithSecretProvider(Workflow):
+ def __init__(self) -> None:
+ super().__init__()
+ self.agent = AgentParam(
+ Session.from_agent_prompt("system"),
+ Provider(model="model", api_key="must-not-leak"),
+ )
+
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def execute(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def test_canonical_plan_never_serializes_provider_secret_values() -> None:
+ plan = WorkflowCompiler().compile(_WithSecretProvider(), revision_id=uuid4())
+ encoded = plan.canonical_json()
+
+ assert "must-not-leak" not in encoded
+ payload = json.loads(encoded)
+ assert payload["resources"]["providers"][0]["model"] == "model"
+ assert "api_key" not in payload["resources"]["providers"][0]
+
+
+def test_existing_compiled_workflow_exposes_v2_execution_plan() -> None:
+ workflow = _WithSecretProvider()
+ compiled = workflow.compile()
+
+ assert compiled.execution_plan.definition_hash
+ assert compiled.execution_plan.durable is True
diff --git a/tests/deployment/test_ga_gate_reports.py b/tests/deployment/test_ga_gate_reports.py
new file mode 100644
index 0000000..e644265
--- /dev/null
+++ b/tests/deployment/test_ga_gate_reports.py
@@ -0,0 +1,237 @@
+from __future__ import annotations
+
+import hashlib
+import json
+from pathlib import Path
+
+import pytest
+from jsonschema import Draft202012Validator
+
+from scripts.release import record_gate, verify_gate_reports
+
+SOURCE_COMMIT = "b" * 40
+
+
+def _reports() -> dict[str, dict[str, object]]:
+ common = {
+ "schema": "openrath.ga-gate-report/1",
+ "source_commit": SOURCE_COMMIT,
+ "result": "passed",
+ "generated_at": "2026-07-30T12:00:00+00:00",
+ "environment": {"profile": "staging-us-east", "target_like": True},
+ "evidence": [],
+ "open_risks": [],
+ }
+ return {
+ "tests": {
+ **common,
+ "gate": "tests",
+ "details": {"required_ci": "passed", "open_p0": 0},
+ },
+ "live_adapters": {
+ **common,
+ "gate": "live_adapters",
+ "details": {
+ "provider": "passed",
+ "opensandbox": "passed",
+ "openviking": "passed",
+ },
+ },
+ "performance": {
+ **common,
+ "gate": "performance",
+ "details": {
+ "single_host": "passed",
+ "split_profile": "passed",
+ "worker_scaling_efficiency": 0.72,
+ },
+ },
+ "soak": {
+ **common,
+ "gate": "soak",
+ "details": {
+ "duration_seconds": 28800,
+ "errors": 0,
+ "unexplained_resource_growth": False,
+ },
+ },
+ "drills": {
+ **common,
+ "gate": "drills",
+ "details": {
+ "fault_matrix": "passed",
+ "backup_restore": "passed",
+ "rollout_rollback": "passed",
+ },
+ },
+ "compatibility": {
+ **common,
+ "gate": "compatibility",
+ "details": {
+ "api_review": "passed",
+ "v1_maintenance_window": "passed",
+ "migration": "passed",
+ },
+ },
+ }
+
+
+def _write_reports(directory: Path, reports: dict[str, dict[str, object]]) -> None:
+ evidence_directory = directory / "evidence"
+ evidence_directory.mkdir()
+ for gate, report in reports.items():
+ evidence = evidence_directory / f"{gate}.log"
+ evidence.write_text(f"{gate} passed\n", encoding="utf-8")
+ report["evidence"] = [
+ {
+ "path": evidence.relative_to(directory).as_posix(),
+ "sha256": hashlib.sha256(evidence.read_bytes()).hexdigest(),
+ "size": evidence.stat().st_size,
+ }
+ ]
+ filename = verify_gate_reports.GATE_REPORT_FILES[gate]
+ (directory / filename).write_text(json.dumps(report), encoding="utf-8")
+
+
+def test_complete_ga_gate_report_set_passes(tmp_path: Path) -> None:
+ _write_reports(tmp_path, _reports())
+ validated = verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+ assert set(validated) == set(verify_gate_reports.GATE_REPORT_FILES)
+
+
+def test_ga_gate_reports_match_the_committed_json_schema(tmp_path: Path) -> None:
+ reports = _reports()
+ _write_reports(tmp_path, reports)
+ schema = json.loads(
+ Path("release/evidence/schema/ga-gate-report.schema.json").read_text(
+ encoding="utf-8"
+ )
+ )
+ validator = Draft202012Validator(schema)
+ for report in reports.values():
+ validator.validate(report)
+
+
+def test_soak_shorter_than_eight_hours_is_rejected(tmp_path: Path) -> None:
+ reports = _reports()
+ soak_details = reports["soak"]["details"]
+ assert isinstance(soak_details, dict)
+ soak_details["duration_seconds"] = 28799
+ _write_reports(tmp_path, reports)
+
+ with pytest.raises(ValueError, match="28800"):
+ verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+
+
+def test_report_from_a_different_source_commit_is_rejected(tmp_path: Path) -> None:
+ reports = _reports()
+ reports["performance"]["source_commit"] = "c" * 40
+ _write_reports(tmp_path, reports)
+
+ with pytest.raises(ValueError, match="source_commit"):
+ verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+
+
+def test_rehearsal_environment_is_rejected(tmp_path: Path) -> None:
+ reports = _reports()
+ reports["tests"]["environment"] = {
+ "profile": "docker-desktop",
+ "target_like": False,
+ }
+ _write_reports(tmp_path, reports)
+
+ with pytest.raises(ValueError, match="target_like"):
+ verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+
+
+@pytest.mark.parametrize(
+ ("mutation", "message"),
+ [
+ ({"path": "../outside.log"}, "relative"),
+ ({"sha256": "0" * 64}, "hash"),
+ ({"size": 999}, "size"),
+ ],
+)
+def test_evidence_files_are_contained_and_hash_bound(
+ tmp_path: Path,
+ mutation: dict[str, object],
+ message: str,
+) -> None:
+ reports = _reports()
+ _write_reports(tmp_path, reports)
+ report_path = tmp_path / "tests.json"
+ report = json.loads(report_path.read_text(encoding="utf-8"))
+ report["evidence"][0].update(mutation)
+ report_path.write_text(json.dumps(report), encoding="utf-8")
+
+ with pytest.raises(ValueError, match=message):
+ verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+
+
+def test_symlink_evidence_is_rejected(tmp_path: Path) -> None:
+ reports = _reports()
+ _write_reports(tmp_path, reports)
+ target = tmp_path / "evidence/tests.log"
+ link = tmp_path / "evidence/tests-link.log"
+ try:
+ link.symlink_to(target)
+ except OSError:
+ pytest.skip("symlink creation is unavailable")
+ report_path = tmp_path / "tests.json"
+ report = json.loads(report_path.read_text(encoding="utf-8"))
+ report["evidence"][0]["path"] = "evidence/tests-link.log"
+ report_path.write_text(json.dumps(report), encoding="utf-8")
+
+ with pytest.raises(ValueError, match="symlink"):
+ verify_gate_reports.verify_directory(
+ tmp_path,
+ source_commit=SOURCE_COMMIT,
+ )
+
+
+def test_report_recorder_hashes_evidence_without_storing_absolute_paths(
+ tmp_path: Path,
+) -> None:
+ evidence_root = tmp_path / "bundle"
+ evidence_root.mkdir()
+ log = evidence_root / "logs/live.txt"
+ log.parent.mkdir()
+ log.write_text("provider lifecycle passed\n", encoding="utf-8")
+
+ report = record_gate.build_report(
+ gate="live_adapters",
+ source_commit=SOURCE_COMMIT,
+ environment={"profile": "staging-us-east", "target_like": True},
+ details={
+ "provider": "passed",
+ "opensandbox": "passed",
+ "openviking": "passed",
+ },
+ evidence_root=evidence_root,
+ evidence_files=[log],
+ open_risks=[],
+ generated_at="2026-07-30T12:00:00+00:00",
+ )
+
+ assert report["evidence"] == [
+ {
+ "path": "logs/live.txt",
+ "sha256": hashlib.sha256(log.read_bytes()).hexdigest(),
+ "size": log.stat().st_size,
+ }
+ ]
diff --git a/tests/deployment/test_gate_bundle_security.py b/tests/deployment/test_gate_bundle_security.py
new file mode 100644
index 0000000..a10daf0
--- /dev/null
+++ b/tests/deployment/test_gate_bundle_security.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+import pytest
+
+from scripts.release.verify_gate_bundle import verify_bundle
+
+
+def test_gate_bundle_allows_only_small_utf8_evidence_files(tmp_path: Path) -> None:
+ report = tmp_path / "tests.json"
+ report.write_text('{"result":"passed"}', encoding="utf-8")
+ evidence = tmp_path / "evidence"
+ evidence.mkdir()
+ log = evidence / "tests.log"
+ log.write_text("1083 tests passed\n", encoding="utf-8")
+
+ summary = verify_bundle(tmp_path)
+
+ assert summary == {
+ "files": 2,
+ "bytes": report.stat().st_size + log.stat().st_size,
+ }
+
+
+@pytest.mark.parametrize(
+ "content",
+ [
+ "Authorization: Bearer secret-value-that-must-not-leak",
+ "pypi-abcdefghijklmnopqrstuvwxyz0123456789",
+ "github_pat_abcdefghijklmnopqrstuvwxyz0123456789",
+ "-----BEGIN PRIVATE KEY-----",
+ '"api_key": "secret-value-that-must-not-leak"',
+ ],
+)
+def test_gate_bundle_rejects_high_confidence_secret_patterns(
+ tmp_path: Path,
+ content: str,
+) -> None:
+ (tmp_path / "evidence.log").write_text(content, encoding="utf-8")
+
+ with pytest.raises(ValueError, match="secret"):
+ verify_bundle(tmp_path)
+
+
+def test_gate_bundle_rejects_unsupported_binary_and_sensitive_names(
+ tmp_path: Path,
+) -> None:
+ (tmp_path / "capture.zip").write_bytes(b"archive")
+ with pytest.raises(ValueError, match="extension"):
+ verify_bundle(tmp_path)
+
+ (tmp_path / "capture.zip").unlink()
+ (tmp_path / ".env").write_text("SAFE=value", encoding="utf-8")
+ with pytest.raises(ValueError, match="sensitive"):
+ verify_bundle(tmp_path)
+
+
+def test_gate_bundle_rejects_symbolic_links(tmp_path: Path) -> None:
+ target = tmp_path / "target.log"
+ target.write_text("safe", encoding="utf-8")
+ link = tmp_path / "link.log"
+ try:
+ link.symlink_to(target)
+ except OSError:
+ pytest.skip("symlink creation is unavailable")
+
+ with pytest.raises(ValueError, match="symbolic"):
+ verify_bundle(tmp_path)
diff --git a/tests/deployment/test_manual_pypi_publish.py b/tests/deployment/test_manual_pypi_publish.py
new file mode 100644
index 0000000..2c51870
--- /dev/null
+++ b/tests/deployment/test_manual_pypi_publish.py
@@ -0,0 +1,32 @@
+from __future__ import annotations
+
+from scripts.release.publish_pypi_manual import (
+ twine_environment,
+ twine_upload_command,
+)
+
+
+def test_manual_upload_command_prompts_without_exposing_a_token() -> None:
+ command = twine_upload_command(["openrath.whl", "openrath.tar.gz"])
+
+ assert command[:4] == ["uvx", "--from", "twine==6.2.0", "twine"]
+ assert "__token__" in command
+ assert "--password" not in command
+ assert "--skip-existing" in command
+ assert not any(value.startswith("pypi-") for value in command)
+
+
+def test_manual_upload_environment_removes_credential_overrides() -> None:
+ environment = twine_environment(
+ {
+ "PATH": "kept",
+ "TWINE_PASSWORD": "secret",
+ "TWINE_USERNAME": "wrong",
+ "TWINE_REPOSITORY": "wrong",
+ "TWINE_REPOSITORY_URL": "wrong",
+ }
+ )
+
+ assert environment["PATH"] == "kept"
+ assert environment["PYTHON_KEYRING_BACKEND"] == "keyring.backends.null.Keyring"
+ assert not any(name.startswith("TWINE_") for name in environment)
diff --git a/tests/deployment/test_pypi_recovery.py b/tests/deployment/test_pypi_recovery.py
new file mode 100644
index 0000000..bf500ea
--- /dev/null
+++ b/tests/deployment/test_pypi_recovery.py
@@ -0,0 +1,66 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+import pytest
+
+from scripts.release.verify_pypi_files import (
+ local_distributions,
+ verify_remote_files,
+)
+
+
+def _payload(files: dict[str, str]) -> dict[str, object]:
+ return {
+ "info": {"version": "2.0.0"},
+ "urls": [
+ {"filename": filename, "digests": {"sha256": digest}}
+ for filename, digest in files.items()
+ ],
+ }
+
+
+def test_local_distributions_requires_one_wheel_and_sdist(tmp_path: Path) -> None:
+ (tmp_path / "openrath-2.0.0.tar.gz").write_bytes(b"sdist")
+ (tmp_path / "openrath-2.0.0-py3-none-any.whl").write_bytes(b"wheel")
+
+ files = local_distributions(tmp_path, version="2.0.0")
+
+ assert set(files) == {
+ "openrath-2.0.0.tar.gz",
+ "openrath-2.0.0-py3-none-any.whl",
+ }
+
+
+def test_pypi_recovery_accepts_absent_partial_or_complete_identical_files() -> None:
+ local = {"openrath-2.0.0.tar.gz": "a" * 64, "openrath-2.0.0.whl": "b" * 64}
+
+ assert not verify_remote_files(local, None, version="2.0.0", require_complete=False)
+ assert not verify_remote_files(
+ local,
+ _payload({"openrath-2.0.0.tar.gz": "a" * 64}),
+ version="2.0.0",
+ require_complete=False,
+ )
+ assert verify_remote_files(
+ local, _payload(local), version="2.0.0", require_complete=True
+ )
+
+
+def test_pypi_recovery_rejects_conflicting_or_unexpected_files() -> None:
+ local = {"openrath-2.0.0.tar.gz": "a" * 64}
+
+ with pytest.raises(ValueError, match="hash mismatch"):
+ verify_remote_files(
+ local,
+ _payload({"openrath-2.0.0.tar.gz": "b" * 64}),
+ version="2.0.0",
+ require_complete=False,
+ )
+ with pytest.raises(ValueError, match="unexpected files"):
+ verify_remote_files(
+ local,
+ _payload({**local, "openrath-2.0.0.exe": "c" * 64}),
+ version="2.0.0",
+ require_complete=False,
+ )
diff --git a/tests/deployment/test_reference_manifests.py b/tests/deployment/test_reference_manifests.py
new file mode 100644
index 0000000..e949282
--- /dev/null
+++ b/tests/deployment/test_reference_manifests.py
@@ -0,0 +1,68 @@
+from __future__ import annotations
+
+import re
+from pathlib import Path
+
+
+def test_external_reference_images_are_digest_pinned() -> None:
+ compose = Path("deploy/compose/compose.yaml").read_text(encoding="utf-8")
+ for image in re.findall(r"^\s+image:\s+(\S+)", compose, flags=re.MULTILINE):
+ if image.startswith("openrath:"):
+ continue
+ assert "@sha256:" in image, image
+
+ dockerfile = Path("docker/Dockerfile").read_text(encoding="utf-8")
+ for image in re.findall(r"^FROM\s+(\S+)", dockerfile, flags=re.MULTILINE):
+ assert "@sha256:" in image, image
+
+
+def test_kubernetes_template_covers_workloads_and_dns() -> None:
+ manifest = Path("deploy/kubernetes/openrath.yaml").read_text(encoding="utf-8")
+ assert 'values: ["openrath", "openrath-worker", "openrath-migrate"]' in manifest
+ assert "protocol: UDP\n port: 53" in manifest
+ assert "protocol: TCP\n port: 53" in manifest
+ assert manifest.count("Release automation must replace") == 3
+ assert "imagePullPolicy: Always" in manifest
+ assert "OPENRATH_GRANTS:" in manifest
+ assert '{"*"}' not in manifest
+
+
+def test_reference_server_enables_audit_and_explicit_grants() -> None:
+ app = Path("examples/v2_server_app.py").read_text(encoding="utf-8")
+ compose = Path("deploy/compose/compose.yaml").read_text(encoding="utf-8")
+ assert "StructuredAuditSink()" in app
+ assert 'os.environ["OPENRATH_GRANTS"]' in app
+ assert 'frozenset({"*"})' not in app
+ assert "OPENRATH_GRANTS:" in compose
+
+
+def test_production_workflow_pins_actions_and_service_images() -> None:
+ workflow = Path(".github/workflows/ci-v2-production.yml").read_text(
+ encoding="utf-8"
+ )
+ assert "actions/checkout@11d5960a326750d5838078e36cf38b85af677262" in workflow
+ assert "postgres:17-alpine@sha256:" in workflow
+ assert "redis:8-alpine@sha256:" in workflow
+ assert "minio/minio:RELEASE.2025-09-07T16-13-09Z@sha256:" in workflow
+ assert "pip-audit" in workflow
+ assert "--scanners secret" in workflow
+ assert (
+ "aquasec/trivy@sha256:"
+ "e2b22eac59c02003d8749f5b8d9bd073b62e30fefaef5b7c8371204e0a4b0c08" in workflow
+ )
+
+
+def test_live_release_workflows_fail_closed() -> None:
+ openviking = Path(".github/workflows/ci-test-openviking.yml").read_text(
+ encoding="utf-8"
+ )
+ provider = Path(".github/workflows/ci-live-provider.yml").read_text(
+ encoding="utf-8"
+ )
+ assert "pytest (openviking contracts)" in openviking
+ assert "continue-on-error:" not in openviking
+ assert "Require live credentials for release validation" in openviking
+ assert "exit 1" in openviking
+ assert "pytest (live provider required)" in provider
+ assert "An approved live provider credential is required." in provider
+ assert "uv run pytest -q -m live_llm" in provider
diff --git a/tests/deployment/test_release_assets.py b/tests/deployment/test_release_assets.py
new file mode 100644
index 0000000..57dd897
--- /dev/null
+++ b/tests/deployment/test_release_assets.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+import pytest
+
+from scripts.release.verify_release_assets import verify_assets
+
+
+def test_release_assets_require_exact_names_and_hashes(tmp_path: Path) -> None:
+ expected_dir = tmp_path / "expected"
+ actual_dir = tmp_path / "actual"
+ expected_dir.mkdir()
+ actual_dir.mkdir()
+ expected = expected_dir / "openrath.whl"
+ actual = actual_dir / "openrath.whl"
+ expected.write_bytes(b"same")
+ actual.write_bytes(b"same")
+
+ verify_assets(actual_dir, [expected])
+
+ actual.write_bytes(b"different")
+ with pytest.raises(ValueError, match="hash mismatch"):
+ verify_assets(actual_dir, [expected])
+
+
+def test_release_assets_reject_extra_and_duplicate_names(tmp_path: Path) -> None:
+ actual_dir = tmp_path / "actual"
+ actual_dir.mkdir()
+ first = tmp_path / "one" / "asset.json"
+ second = tmp_path / "two" / "asset.json"
+ first.parent.mkdir()
+ second.parent.mkdir()
+ first.write_text("one", encoding="utf-8")
+ second.write_text("two", encoding="utf-8")
+
+ with pytest.raises(ValueError, match="duplicate expected"):
+ verify_assets(actual_dir, [first, second])
+
+ (actual_dir / "extra.json").write_text("extra", encoding="utf-8")
+ with pytest.raises(ValueError, match="missing assets"):
+ verify_assets(actual_dir, [first])
diff --git a/tests/deployment/test_release_evidence.py b/tests/deployment/test_release_evidence.py
new file mode 100644
index 0000000..c063a82
--- /dev/null
+++ b/tests/deployment/test_release_evidence.py
@@ -0,0 +1,183 @@
+from __future__ import annotations
+
+import json
+from pathlib import Path
+
+import pytest
+
+from scripts.release import build_evidence, create_ga_approval, verify_evidence
+
+SOURCE_COMMIT = "a" * 40
+
+
+def _approval() -> dict[str, object]:
+ return {
+ "schema": "openrath.ga-approval/1",
+ "version": "2.0.0",
+ "source_commit": SOURCE_COMMIT,
+ "approved": True,
+ "approved_at": "2026-07-30T12:00:00+00:00",
+ "approvers": ["release-owner"],
+ "requested_by": "release-requester",
+ "environment": "ga-release",
+ "environment_reviews": [
+ {
+ "review_id": "42",
+ "reviewer": "release-owner",
+ "approved_at": "2026-07-30T12:00:00+00:00",
+ }
+ ],
+ "repository": "Rath-Team/OpenRath",
+ "workflow_run_id": "12345",
+ "actions": {
+ "pypi": True,
+ "ghcr": True,
+ "github_release": True,
+ },
+ }
+
+
+def test_release_stage_is_inferred_from_exact_supported_versions() -> None:
+ assert build_evidence.infer_release_stage("2.0.0rc1") == "rc"
+ assert build_evidence.infer_release_stage("2.0.0rc12") == "rc"
+ assert build_evidence.infer_release_stage("2.0.0") == "ga"
+
+ with pytest.raises(ValueError, match="unsupported release version"):
+ build_evidence.infer_release_stage("2.0.1")
+
+
+def test_ga_approval_is_bound_to_version_commit_and_all_release_actions(
+ tmp_path: Path,
+) -> None:
+ approval_path = tmp_path / "approval.json"
+ approval_path.write_text(json.dumps(_approval()), encoding="utf-8")
+
+ approval = build_evidence.load_ga_approval(
+ approval_path,
+ version="2.0.0",
+ commit=SOURCE_COMMIT,
+ repository="Rath-Team/OpenRath",
+ workflow_run_id="12345",
+ )
+ assert approval["approvers"] == ["release-owner"]
+
+ missing_action = _approval()
+ del missing_action["actions"]["pypi"] # type: ignore[index]
+ approval_path.write_text(json.dumps(missing_action), encoding="utf-8")
+ with pytest.raises(ValueError, match="pypi"):
+ build_evidence.load_ga_approval(
+ approval_path,
+ version="2.0.0",
+ commit=SOURCE_COMMIT,
+ )
+
+ unsupported_action = _approval()
+ unsupported_action["actions"]["tag"] = True # type: ignore[index]
+ approval_path.write_text(json.dumps(unsupported_action), encoding="utf-8")
+ with pytest.raises(ValueError, match="unsupported actions"):
+ build_evidence.load_ga_approval(
+ approval_path,
+ version="2.0.0",
+ commit=SOURCE_COMMIT,
+ )
+
+
+def test_ga_approval_uses_actual_protected_environment_reviews(
+ tmp_path: Path,
+) -> None:
+ history_path = tmp_path / "reviews.json"
+ history_path.write_text(
+ json.dumps(
+ [
+ {
+ "id": 42,
+ "state": "approved",
+ "user": {"login": "release-owner"},
+ "created_at": "2026-07-30T12:00:00Z",
+ "environments": [{"name": "ga-release"}],
+ },
+ {
+ "id": 43,
+ "state": "approved",
+ "user": {"login": "other-owner"},
+ "created_at": "2026-07-30T12:01:00Z",
+ "environments": [{"name": "staging"}],
+ },
+ ]
+ ),
+ encoding="utf-8",
+ )
+
+ approval = create_ga_approval.build_approval(
+ version="2.0.0",
+ source_commit=SOURCE_COMMIT,
+ requested_by="release-requester",
+ repository="Rath-Team/OpenRath",
+ workflow_run_id="12345",
+ review_history=history_path,
+ )
+
+ assert approval["approvers"] == ["release-owner"]
+ assert approval["requested_by"] == "release-requester"
+ assert approval["approved_at"] == "2026-07-30T12:00:00Z"
+ assert approval["environment_reviews"] == [
+ {
+ "review_id": "42",
+ "reviewer": "release-owner",
+ "approved_at": "2026-07-30T12:00:00Z",
+ }
+ ]
+
+
+def test_ga_release_requires_every_evidence_category() -> None:
+ complete = set(build_evidence.GA_REQUIRED_ARTIFACTS)
+ build_evidence.require_ga_artifacts(complete)
+
+ incomplete = complete - {"soak"}
+ with pytest.raises(ValueError, match="soak"):
+ build_evidence.require_ga_artifacts(incomplete)
+
+
+def test_verifier_accepts_legacy_rc_and_rejects_ga_with_blockers() -> None:
+ legacy_rc = {
+ "schema": "openrath.rc-evidence/1",
+ "release_stage": "rc",
+ "version": "2.0.0rc1",
+ "tag": "v2.0.0rc1",
+ "source_commit": SOURCE_COMMIT,
+ "source_tree_clean": True,
+ "ga_approved": False,
+ "blocking_gates": ["target-like soak"],
+ "artifacts": {},
+ }
+ verify_evidence.validate_release_state(
+ legacy_rc,
+ version="2.0.0rc1",
+ commit=SOURCE_COMMIT,
+ )
+
+ ga = {
+ **legacy_rc,
+ "schema": "openrath.release-evidence/2",
+ "release_stage": "ga",
+ "version": "2.0.0",
+ "tag": "v2.0.0",
+ "ga_approved": True,
+ "blocking_gates": ["not actually ready"],
+ "approval": _approval(),
+ "artifacts": {name: {} for name in build_evidence.GA_REQUIRED_ARTIFACTS},
+ }
+ with pytest.raises(AssertionError, match="blocking gates"):
+ verify_evidence.validate_release_state(
+ ga,
+ version="2.0.0",
+ commit=SOURCE_COMMIT,
+ )
+
+
+def test_release_manifest_schema_has_separate_rc_and_ga_contracts() -> None:
+ schema = json.loads(
+ Path("release/evidence/schema/manifest.schema.json").read_text(encoding="utf-8")
+ )
+ assert schema["$id"].endswith("/release-evidence-manifest-v2.json")
+ assert len(schema["oneOf"]) == 2
diff --git a/tests/deployment/test_release_load.py b/tests/deployment/test_release_load.py
new file mode 100644
index 0000000..26e879f
--- /dev/null
+++ b/tests/deployment/test_release_load.py
@@ -0,0 +1,179 @@
+from __future__ import annotations
+
+import json
+import threading
+from pathlib import Path
+from typing import Any
+
+import httpx
+import pytest
+
+from scripts.release import build_performance_report, load_v2
+
+SOURCE_COMMIT = "d" * 40
+
+
+def test_load_sample_completes_lifecycles_without_recording_token() -> None:
+ lock = threading.Lock()
+ sequence = 0
+
+ def handler(request: httpx.Request) -> httpx.Response:
+ nonlocal sequence
+ assert request.headers["authorization"] == "Bearer super-secret"
+ with lock:
+ sequence += 1
+ current = sequence
+ if request.method == "POST" and request.url.path == "/v1/sessions":
+ return httpx.Response(201, json={"id": f"session-{current}"})
+ if request.method == "POST" and request.url.path == "/v1/runs":
+ return httpx.Response(201, json={"id": f"run-{current}"})
+ if request.method == "GET" and request.url.path.startswith("/v1/runs/"):
+ return httpx.Response(200, json={"status": "succeeded"})
+ raise AssertionError(f"unexpected request: {request.method} {request.url.path}")
+
+ report = load_v2.run_sample(
+ load_v2.LoadConfig(
+ base_url="https://target.example",
+ token="super-secret",
+ source_commit=SOURCE_COMMIT,
+ profile="split",
+ worker_replicas=4,
+ concurrency=2,
+ duration_seconds=60,
+ max_runs=4,
+ poll_interval_seconds=0,
+ request_timeout_seconds=2,
+ run_timeout_seconds=2,
+ target_like=True,
+ ),
+ transport=httpx.MockTransport(handler),
+ )
+
+ assert report["completed_runs"] == 4
+ assert report["errors"] == 0
+ assert report["worker_replicas"] == 4
+ assert report["throughput_runs_per_second"] > 0
+ assert "super-secret" not in json.dumps(report)
+
+
+def test_target_like_load_requires_https() -> None:
+ with pytest.raises(ValueError, match="HTTPS"):
+ load_v2.run_sample(
+ load_v2.LoadConfig(
+ base_url="http://target.example",
+ token="super-secret",
+ source_commit=SOURCE_COMMIT,
+ profile="split",
+ worker_replicas=1,
+ concurrency=1,
+ duration_seconds=1,
+ max_runs=1,
+ poll_interval_seconds=0,
+ request_timeout_seconds=1,
+ run_timeout_seconds=1,
+ target_like=True,
+ )
+ )
+
+
+def _sample(
+ *,
+ profile: str,
+ replicas: int,
+ throughput: float,
+ errors: int = 0,
+) -> dict[str, Any]:
+ return {
+ "schema": "openrath.v2.load-sample/1",
+ "source_commit": SOURCE_COMMIT,
+ "profile": profile,
+ "target_like": True,
+ "worker_replicas": replicas,
+ "duration_seconds": 300.0,
+ "attempted_runs": 100,
+ "completed_runs": 100 - errors,
+ "errors": errors,
+ "throughput_runs_per_second": throughput,
+ "latency_seconds": {"p50": 0.1, "p95": 0.2, "p99": 0.3},
+ "generated_at": "2026-07-30T12:00:00Z",
+ "target_origin": "https://target.example",
+ }
+
+
+def _write_samples(root: Path, samples: list[dict[str, Any]]) -> list[Path]:
+ paths: list[Path] = []
+ for index, sample in enumerate(samples):
+ path = root / f"sample-{index}.json"
+ path.write_text(json.dumps(sample), encoding="utf-8")
+ paths.append(path)
+ return paths
+
+
+def test_performance_report_requires_single_and_split_scaling_samples(
+ tmp_path: Path,
+) -> None:
+ paths = _write_samples(
+ tmp_path,
+ [
+ _sample(profile="single_host", replicas=1, throughput=8),
+ _sample(profile="split", replicas=1, throughput=10),
+ _sample(profile="split", replicas=2, throughput=18),
+ _sample(profile="split", replicas=4, throughput=30),
+ ],
+ )
+
+ report = build_performance_report.build_report(
+ sample_paths=paths,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ generated_at="2026-07-30T13:00:00Z",
+ )
+
+ details = report["details"]
+ assert details["single_host"] == "passed"
+ assert details["split_profile"] == "passed"
+ assert details["worker_scaling_efficiency"] == pytest.approx(0.75)
+ assert report["source_commit"] == SOURCE_COMMIT
+ assert len(report["evidence"]) == 4
+
+
+def test_performance_report_rejects_errors_and_insufficient_scaling(
+ tmp_path: Path,
+) -> None:
+ samples = [
+ _sample(profile="single_host", replicas=1, throughput=8),
+ _sample(profile="split", replicas=1, throughput=10),
+ _sample(profile="split", replicas=2, throughput=18),
+ _sample(profile="split", replicas=4, throughput=20),
+ ]
+ paths = _write_samples(tmp_path, samples)
+ with pytest.raises(ValueError, match="scaling efficiency"):
+ build_performance_report.build_report(
+ sample_paths=paths,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ )
+
+ samples[-1] = _sample(
+ profile="split",
+ replicas=4,
+ throughput=32,
+ errors=1,
+ )
+ paths[-1].write_text(json.dumps(samples[-1]), encoding="utf-8")
+ with pytest.raises(ValueError, match="zero errors"):
+ build_performance_report.build_report(
+ sample_paths=paths,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ )
+
+ samples[-1] = _sample(profile="split", replicas=4, throughput=32)
+ samples[-1]["completed_runs"] = 0
+ paths[-1].write_text(json.dumps(samples[-1]), encoding="utf-8")
+ with pytest.raises(ValueError, match="completed run"):
+ build_performance_report.build_report(
+ sample_paths=paths,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ )
diff --git a/tests/deployment/test_release_operations_evidence.py b/tests/deployment/test_release_operations_evidence.py
new file mode 100644
index 0000000..dcf7ddf
--- /dev/null
+++ b/tests/deployment/test_release_operations_evidence.py
@@ -0,0 +1,229 @@
+from __future__ import annotations
+
+import json
+from pathlib import Path
+from typing import Any
+
+import pytest
+
+from scripts.release import build_drill_report, build_soak_report
+
+SOURCE_COMMIT = "e" * 40
+
+
+def _write(path: Path, value: object) -> Path:
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(json.dumps(value), encoding="utf-8")
+ return path
+
+
+def _soak_sample(*, duration: float = 28800, errors: int = 0) -> dict[str, Any]:
+ return {
+ "schema": "openrath.v2.load-sample/1",
+ "source_commit": SOURCE_COMMIT,
+ "profile": "split",
+ "target_like": True,
+ "worker_replicas": 4,
+ "duration_seconds": duration,
+ "attempted_runs": 1000,
+ "completed_runs": 1000 - errors,
+ "errors": errors,
+ "throughput_runs_per_second": 3.0,
+ "latency_seconds": {"p50": 0.2, "p95": 0.5, "p99": 0.8},
+ "generated_at": "2026-07-30T12:00:00Z",
+ "target_origin": "https://target.example",
+ }
+
+
+def _snapshot(phase: str, memory: int) -> dict[str, Any]:
+ return {
+ "schema": "openrath.v2.resource-snapshot/1",
+ "source_commit": SOURCE_COMMIT,
+ "phase": phase,
+ "captured_at": "2026-07-30T12:00:00Z",
+ "components": {
+ "api": {"memory_bytes": memory, "restarts": 0},
+ "worker": {"memory_bytes": memory, "restarts": 0},
+ },
+ }
+
+
+def _assessment(*, unexplained: bool = False) -> dict[str, Any]:
+ return {
+ "schema": "openrath.v2.resource-assessment/1",
+ "source_commit": SOURCE_COMMIT,
+ "assessor": "operations-owner",
+ "unexplained_resource_growth": unexplained,
+ "rationale": "Resource use stabilized after warm-up.",
+ }
+
+
+def test_soak_report_binds_eight_hour_run_and_resource_assessment(
+ tmp_path: Path,
+) -> None:
+ sample = _write(tmp_path / "raw/soak.json", _soak_sample())
+ before = _write(tmp_path / "raw/before.json", _snapshot("before", 100))
+ after = _write(tmp_path / "raw/after.json", _snapshot("after", 110))
+ assessment = _write(tmp_path / "raw/assessment.json", _assessment())
+
+ report = build_soak_report.build_report(
+ sample_path=sample,
+ before_snapshot_path=before,
+ after_snapshot_path=after,
+ assessment_path=assessment,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ generated_at="2026-07-30T21:00:00Z",
+ )
+
+ assert report["details"]["duration_seconds"] == 28800
+ assert report["details"]["errors"] == 0
+ assert report["details"]["unexplained_resource_growth"] is False
+ assert len(report["evidence"]) == 4
+
+
+@pytest.mark.parametrize(
+ ("duration", "errors", "unexplained", "message"),
+ [
+ (28799, 0, False, "28800"),
+ (28800, 1, False, "zero errors"),
+ (28800, 0, True, "unexplained"),
+ ],
+)
+def test_soak_report_rejects_incomplete_acceptance(
+ tmp_path: Path,
+ duration: float,
+ errors: int,
+ unexplained: bool,
+ message: str,
+) -> None:
+ sample = _write(
+ tmp_path / "raw/soak.json", _soak_sample(duration=duration, errors=errors)
+ )
+ before = _write(tmp_path / "raw/before.json", _snapshot("before", 100))
+ after = _write(tmp_path / "raw/after.json", _snapshot("after", 110))
+ assessment = _write(
+ tmp_path / "raw/assessment.json",
+ _assessment(unexplained=unexplained),
+ )
+ with pytest.raises(ValueError, match=message):
+ build_soak_report.build_report(
+ sample_path=sample,
+ before_snapshot_path=before,
+ after_snapshot_path=after,
+ assessment_path=assessment,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ )
+
+
+def test_soak_report_requires_comparable_resource_components(tmp_path: Path) -> None:
+ sample = _write(tmp_path / "raw/soak.json", _soak_sample())
+ before = _write(tmp_path / "raw/before.json", _snapshot("before", 100))
+ after_value = _snapshot("after", 110)
+ del after_value["components"]["worker"]
+ after = _write(tmp_path / "raw/after.json", after_value)
+ assessment = _write(tmp_path / "raw/assessment.json", _assessment())
+
+ with pytest.raises(ValueError, match="same components"):
+ build_soak_report.build_report(
+ sample_path=sample,
+ before_snapshot_path=before,
+ after_snapshot_path=after,
+ assessment_path=assessment,
+ evidence_root=tmp_path,
+ environment_profile="staging-us-east",
+ )
+
+
+def _drill_results() -> dict[str, Any]:
+ required = (
+ "postgresql_failure",
+ "redis_failure",
+ "s3_failure",
+ "api_failure",
+ "worker_failure",
+ "backup_restore",
+ "rollout_rollback",
+ )
+ return {
+ "schema": "openrath.v2.drill-results/1",
+ "source_commit": SOURCE_COMMIT,
+ "environment_profile": "staging-us-east",
+ "drills": {
+ name: {
+ "status": "passed",
+ "operator": "operations-owner",
+ "started_at": "2026-07-30T12:00:00Z",
+ "completed_at": "2026-07-30T12:05:00Z",
+ "recovery_seconds": 300,
+ "data_loss_records": 0,
+ "observed": f"{name} recovered",
+ }
+ for name in required
+ },
+ }
+
+
+def test_drill_report_requires_full_fault_restore_and_rollback_matrix(
+ tmp_path: Path,
+) -> None:
+ results = _write(tmp_path / "raw/drills.json", _drill_results())
+ log = _write(tmp_path / "raw/operator-log.json", {"events": ["passed"]})
+
+ report = build_drill_report.build_report(
+ results_path=results,
+ evidence_paths=[log],
+ evidence_root=tmp_path,
+ generated_at="2026-07-30T14:00:00Z",
+ )
+
+ assert report["details"] == {
+ "fault_matrix": "passed",
+ "backup_restore": "passed",
+ "rollout_rollback": "passed",
+ }
+
+
+def test_drill_report_rejects_missing_drill_data_loss_and_rto_breach(
+ tmp_path: Path,
+) -> None:
+ results = _drill_results()
+ del results["drills"]["redis_failure"]
+ path = _write(tmp_path / "raw/drills.json", results)
+ with pytest.raises(ValueError, match="missing drills"):
+ build_drill_report.build_report(
+ results_path=path,
+ evidence_paths=[],
+ evidence_root=tmp_path,
+ )
+
+ results = _drill_results()
+ results["drills"]["worker_failure"]["completed_at"] = "2026-07-30T11:00:00Z"
+ path.write_text(json.dumps(results), encoding="utf-8")
+ with pytest.raises(ValueError, match="completion"):
+ build_drill_report.build_report(
+ results_path=path,
+ evidence_paths=[],
+ evidence_root=tmp_path,
+ )
+
+ results = _drill_results()
+ results["drills"]["backup_restore"]["data_loss_records"] = 1
+ path.write_text(json.dumps(results), encoding="utf-8")
+ with pytest.raises(ValueError, match="data loss"):
+ build_drill_report.build_report(
+ results_path=path,
+ evidence_paths=[],
+ evidence_root=tmp_path,
+ )
+
+ results["drills"]["backup_restore"]["data_loss_records"] = 0
+ results["drills"]["backup_restore"]["recovery_seconds"] = 3601
+ path.write_text(json.dumps(results), encoding="utf-8")
+ with pytest.raises(ValueError, match="3600"):
+ build_drill_report.build_report(
+ results_path=path,
+ evidence_paths=[],
+ evidence_root=tmp_path,
+ )
diff --git a/tests/deployment/test_release_version.py b/tests/deployment/test_release_version.py
new file mode 100644
index 0000000..98907ed
--- /dev/null
+++ b/tests/deployment/test_release_version.py
@@ -0,0 +1,115 @@
+from __future__ import annotations
+
+import json
+import re
+from pathlib import Path
+
+RC_VERSION = "2.0.0rc1"
+
+
+def test_release_candidate_version_surfaces_are_consistent() -> None:
+ pyproject = Path("pyproject.toml").read_text(encoding="utf-8")
+ match = re.search(r'^version = "([^"]+)"$', pyproject, flags=re.MULTILINE)
+ assert match is not None
+ assert match.group(1) == RC_VERSION
+
+ openapi = json.loads(
+ Path("deploy/docs/openapi-v2.json").read_text(encoding="utf-8")
+ )
+ assert openapi["info"]["version"] == RC_VERSION
+
+ compose = Path("deploy/compose/compose.yaml").read_text(encoding="utf-8")
+ kubernetes = Path("deploy/kubernetes/openrath.yaml").read_text(encoding="utf-8")
+ assert compose.count(f"openrath:{RC_VERSION}") == 3
+ assert kubernetes.count(f"openrath:{RC_VERSION}") == 3
+
+ dockerfile = Path("docker/Dockerfile").read_text(encoding="utf-8")
+ assert 'org.opencontainers.image.version="${OPENRATH_VERSION}"' in dockerfile
+ assert 'org.opencontainers.image.revision="${OPENRATH_REVISION}"' in dockerfile
+
+ assert Path(f"release/notes/v{RC_VERSION}.md").is_file()
+
+
+def test_release_candidate_workflow_is_digest_and_evidence_bound() -> None:
+ workflow = Path(".github/workflows/release-v2-rc.yml").read_text(encoding="utf-8")
+ assert "packages: write" in workflow
+ assert "attestations: write" in workflow
+ assert "push: true" in workflow
+ assert "steps.image.outputs.digest" in workflow
+ assert "scripts/release/build_evidence.py" in workflow
+ assert "scripts/release/verify_evidence.py" in workflow
+ assert "--prerelease" in workflow
+ assert "PyPI" not in workflow
+
+
+def test_ga_workflows_separate_preparation_manual_pypi_and_finalization() -> None:
+ prepare = Path(".github/workflows/release-v2-ga.yml").read_text(encoding="utf-8")
+ finalize = Path(".github/workflows/release-v2-ga-finalize.yml").read_text(
+ encoding="utf-8"
+ )
+ workflows = prepare + finalize
+
+ assert "workflow_dispatch:" in prepare
+ assert "evidence_run_id:" in prepare
+ assert "name: ga-release" in prepare
+ assert "scripts/release/verify_gate_reports.py" in prepare
+ assert "--stage ga" in prepare
+ assert "--approval" in prepare
+ assert "openrath-v2.0.0-ga-input" in prepare
+ assert "openrath-2.0.0-ga-candidate" in workflows
+ assert "attestations: write" in prepare
+ assert "pypa/gh-action-pypi-publish" not in workflows
+ assert "TWINE_PASSWORD" not in workflows
+ assert "id-token: write" in prepare
+ assert "id-token: write" not in finalize
+
+ assert "preparation_run_id:" in finalize
+ assert "workflowName" in finalize
+ assert "--artifact-root release-bundle" in finalize
+ assert "scripts/release/verify_pypi_files.py" in finalize
+ assert "--require-complete" in finalize
+ assert "imagetools create" in finalize
+ assert "gh release create" in finalize
+ assert "--prerelease" not in workflows
+
+ manual = Path("scripts/release/publish_pypi_manual.py").read_text(encoding="utf-8")
+ assert '"__token__"' in manual
+ assert '"--password"' not in manual
+ assert "twine=={TWINE_VERSION}" in manual
+ assert Path("release/manual-pypi-v2.0.0.md").is_file()
+
+
+def test_gate_c_collector_is_protected_and_release_checks_its_identity() -> None:
+ collector = Path(".github/workflows/collect-v2-ga-evidence.yml").read_text(
+ encoding="utf-8"
+ )
+ prepare = Path(".github/workflows/release-v2-ga.yml").read_text(encoding="utf-8")
+
+ assert "name: Collect v2.0.0 Gate C evidence" in collector
+ assert "workflow_dispatch:" in collector
+ assert "runs-on: [self-hosted, linux, openrath-ga]" in collector
+ assert "name: ga-evidence" in collector
+ assert "OPENRATH_GA_EVIDENCE_ROOT" in collector
+ assert "openrath-v2.0.0-ga-input" in collector
+ assert "scripts/release/verify_gate_bundle.py" in collector
+ assert "scripts/release/verify_gate_reports.py" in collector
+ assert '--source-commit "$GITHUB_SHA"' in collector
+ assert 'find "$source_real" -type l' in collector
+ assert "actions/upload-artifact@" in collector
+
+ assert "actions/runs/$EVIDENCE_RUN_ID" in prepare
+ assert ".github/workflows/collect-v2-ga-evidence.yml" in prepare
+ assert "Collect v2.0.0 Gate C evidence" in prepare
+ assert 'jq -r .event <<<"$run_json"' in prepare
+ assert 'jq -r .head_branch <<<"$run_json"' in prepare
+ assert '--artifact-root "$gate_dir"' in prepare
+
+
+def test_ga_release_documents_are_present_and_not_marked_as_drafts() -> None:
+ notes = Path("release/notes/v2.0.0.md").read_text(encoding="utf-8")
+ checklist = Path("release/checklists/v2.0.0-ga.md").read_text(encoding="utf-8")
+ assert "OpenRath v2.0.0" in notes
+ assert "Gate C" in checklist
+ assert "Trusted Publishing" not in checklist
+ for marker in ("TODO", "HOLD", "DRAFT"):
+ assert marker not in notes
diff --git a/tests/deployment/test_revisions.py b/tests/deployment/test_revisions.py
new file mode 100644
index 0000000..72609ac
--- /dev/null
+++ b/tests/deployment/test_revisions.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+
+from pathlib import Path
+
+from rath.deployment import DeploymentManifest, Revision, SQLiteRevisionStore
+from rath.runtime import SQLiteRunStore
+
+
+def test_revision_identity_is_deterministic_and_persistent(tmp_path: Path) -> None:
+ manifest = DeploymentManifest(
+ image_digest="a" * 64,
+ plan_hash="b" * 64,
+ python_version="3.12",
+ dependencies_digest="c" * 64,
+ resources={"provider": "openai"},
+ )
+ first = Revision.create(code_digest="d" * 64, manifest=manifest)
+ second = Revision.create(code_digest="d" * 64, manifest=manifest)
+ run_store = SQLiteRunStore(tmp_path / "runtime.db")
+ store = SQLiteRevisionStore(run_store)
+
+ store.put(first)
+
+ assert first.id == second.id
+ assert first.content_digest == second.content_digest
+ assert len(first.content_digest) == 64
+ assert store.get(first.id) == first
+ assert store.put(second).id == first.id
+
+
+def test_manifest_change_changes_revision_content_identity() -> None:
+ first_manifest = DeploymentManifest(
+ image_digest="a" * 64,
+ plan_hash="b" * 64,
+ python_version="3.12",
+ dependencies_digest="c" * 64,
+ )
+ second_manifest = DeploymentManifest(
+ image_digest="a" * 64,
+ plan_hash="e" * 64,
+ python_version="3.12",
+ dependencies_digest="c" * 64,
+ )
+
+ first = Revision.create(code_digest="d" * 64, manifest=first_manifest)
+ second = Revision.create(code_digest="d" * 64, manifest=second_manifest)
+
+ assert first.id != second.id
+ assert first.content_digest != second.content_digest
diff --git a/tests/eval/test_runner.py b/tests/eval/test_runner.py
new file mode 100644
index 0000000..3df2c57
--- /dev/null
+++ b/tests/eval/test_runner.py
@@ -0,0 +1,31 @@
+from __future__ import annotations
+
+from uuid import uuid4
+
+from rath.eval import EvaluationResult, Experiment, GateDecision, regression_gate
+
+
+def _experiment(score: float) -> Experiment:
+ return Experiment(
+ id=uuid4(),
+ dataset_id=uuid4(),
+ revision_id=uuid4(),
+ results=(
+ EvaluationResult(
+ evaluator="exact",
+ score=score,
+ passed=score >= 0.8,
+ reason="test",
+ ),
+ ),
+ )
+
+
+def test_regression_gate_blocks_absolute_and_relative_regression() -> None:
+ baseline = _experiment(0.9)
+ assert regression_gate(_experiment(0.89), baseline=baseline) is GateDecision.PASS
+ assert regression_gate(_experiment(0.85), baseline=baseline) is GateDecision.FAIL
+ assert (
+ regression_gate(_experiment(0.79), baseline=_experiment(0.7))
+ is GateDecision.FAIL
+ )
diff --git a/tests/eval/test_store.py b/tests/eval/test_store.py
new file mode 100644
index 0000000..9e379c7
--- /dev/null
+++ b/tests/eval/test_store.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+
+from pathlib import Path
+from uuid import uuid4
+
+from rath.eval import (
+ Dataset,
+ EvaluationResult,
+ Example,
+ Experiment,
+ SQLiteEvaluationStore,
+)
+from rath.runtime import SQLiteRunStore
+
+
+def test_evaluation_dataset_and_experiment_persist(tmp_path: Path) -> None:
+ run_store = SQLiteRunStore(tmp_path / "runtime.db")
+ store = SQLiteEvaluationStore(run_store)
+ dataset = Dataset(
+ id=uuid4(),
+ name="qa",
+ version="1",
+ examples=(Example.create({"question": "q"}, {"answer": "a"}),),
+ )
+ experiment = Experiment(
+ id=uuid4(),
+ dataset_id=dataset.id,
+ revision_id=uuid4(),
+ results=(
+ EvaluationResult(
+ evaluator="exact",
+ score=1,
+ passed=True,
+ reason="match",
+ ),
+ ),
+ )
+ store.save_dataset(dataset)
+ store.save_experiment(experiment)
+
+ assert store.get_dataset(dataset.id) == dataset
+ assert store.get_experiment(experiment.id) == experiment
diff --git a/tests/flow/test_agent_forward_memory.py b/tests/flow/test_agent_forward_memory.py
index 5c7585a..fb6dfda 100644
--- a/tests/flow/test_agent_forward_memory.py
+++ b/tests/flow/test_agent_forward_memory.py
@@ -119,7 +119,7 @@ def test_forward_without_memory_is_unchanged() -> None:
assert kinds[-1] == ChunkKind.ASSISTANT
-def test_forward_prepends_injected_system_chunks() -> None:
+def test_forward_prepends_injected_user_context_chunks() -> None:
backend = _FakeBackend(
find_hits=(
MemoryHit(
@@ -146,13 +146,19 @@ def test_forward_prepends_injected_system_chunks() -> None:
# Exactly one MemoryOpFind dispatched, no commit.
assert any(isinstance(op, MemoryOpFind) for op in backend.ops_seen)
assert not any(isinstance(op, MemoryOpCommit) for op in backend.ops_seen)
- # The injected snippet should appear as a system chunk in the output.
- sys_bodies = "\n".join(
+ # The injected snippet should appear as untrusted user-context, not SYSTEM.
+ user_bodies = "\n".join(
str(r.payload.get("content", ""))
for r in out.chunk_table.rows
+ if r.kind == ChunkKind.USER
+ )
+ assert "[untrusted memory:" in user_bodies
+ assert "loves dark mode" in user_bodies
+ assert all(
+ "loves dark mode" not in str(r.payload.get("content", ""))
+ for r in out.chunk_table.rows
if r.kind == ChunkKind.SYSTEM
)
- assert "loves dark mode" in sys_bodies
def test_forward_with_commit_on_forward_dispatches_one_commit() -> None:
diff --git a/tests/flow/test_memory_inject.py b/tests/flow/test_memory_inject.py
index 8a4b796..41983cc 100644
--- a/tests/flow/test_memory_inject.py
+++ b/tests/flow/test_memory_inject.py
@@ -101,9 +101,10 @@ def test_default_recall_emits_one_chunk_per_hit() -> None:
assert isinstance(chunks, tuple)
assert len(chunks) == 2
for chunk in chunks:
- assert chunk.kind == ChunkKind.SYSTEM
+ assert chunk.kind == ChunkKind.USER
assert "content" in chunk.payload
bodies = "\n".join(c.payload["content"] for c in chunks)
+ assert "[untrusted memory:" in bodies
assert "dark mode preferred" in bodies
assert "GMT+8 timezone" in bodies
# The dispatch should carry the configured target_uri + top_k
diff --git a/tests/integration/test_postgres_run_store.py b/tests/integration/test_postgres_run_store.py
new file mode 100644
index 0000000..593cebc
--- /dev/null
+++ b/tests/integration/test_postgres_run_store.py
@@ -0,0 +1,273 @@
+from __future__ import annotations
+
+import os
+from concurrent.futures import ThreadPoolExecutor
+from datetime import datetime, timedelta, timezone
+from uuid import uuid4
+
+import pytest
+
+from rath.definition import EffectClass
+from rath.eval import (
+ Dataset,
+ EvaluationResult,
+ Example,
+ Experiment,
+ PostgresEvaluationStore,
+)
+from rath.runtime import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Checkpoint,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ PostgresEffectLedger,
+ PostgresRunStore,
+ Run,
+ RunStatus,
+ arguments_digest,
+)
+from rath.server import PostgresResourceStore
+
+pytestmark = pytest.mark.skipif(
+ not os.getenv("OPENRATH_TEST_POSTGRES_DSN"),
+ reason="OPENRATH_TEST_POSTGRES_DSN is not configured",
+)
+
+
+def _run(*, key: str | None = None) -> Run:
+ return Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="postgres-test",
+ state={"count": 0},
+ next_nodes=("start",),
+ idempotency_key=key,
+ )
+
+
+@pytest.fixture
+def store() -> PostgresRunStore:
+ dsn = os.environ["OPENRATH_TEST_POSTGRES_DSN"]
+ schema = f"test_{uuid4().hex}"
+ PostgresRunStore.migrate(dsn, schema=schema)
+ value = PostgresRunStore(dsn, schema=schema)
+ yield value
+ value.close()
+ import psycopg
+ from psycopg import sql
+
+ with psycopg.connect(dsn) as connection:
+ connection.execute(
+ sql.SQL("DROP SCHEMA {} CASCADE").format(sql.Identifier(schema))
+ )
+
+
+def test_postgres_lifecycle_and_interrupt(store: PostgresRunStore) -> None:
+ queued = store.create_run(_run(key="lifecycle"))
+ assert store.create_run(queued) == queued
+ running = store.transition_run(
+ queued.id,
+ expected_version=queued.version,
+ target=RunStatus.RUNNING,
+ )
+ checkpoint = Checkpoint.create(
+ run_id=running.id,
+ sequence=1,
+ plan_hash="a" * 64,
+ state={"count": 1},
+ next_nodes=("approve",),
+ effect_watermark=0,
+ )
+ store.append_checkpoint(checkpoint)
+ assert store.latest_checkpoint(running.id) == checkpoint
+ interrupt = Interrupt.create(
+ run_id=running.id,
+ kind=InterruptKind.APPROVAL,
+ request={"operation": "email.send"},
+ )
+ waiting = store.create_interrupt(interrupt, expected_run_version=running.version)
+ assert store.list_interrupts(tenant_id="postgres-test") == (interrupt,)
+ resumed = store.decide_interrupt(
+ interrupt.id,
+ decision=ApprovalDecision(
+ kind=ApprovalDecisionKind.APPROVE,
+ actor_id="reviewer",
+ reason="expected operation",
+ ),
+ expected_run_version=waiting.version,
+ )
+
+ assert resumed.status is RunStatus.QUEUED
+ assert store.get_interrupt(interrupt.id).decision is not None
+ assert store.list_interrupts(tenant_id="postgres-test") == ()
+ assert [event.sequence for event in store.list_run_events(queued.id)] == list(
+ range(1, len(store.list_run_events(queued.id)) + 1)
+ )
+
+
+def test_postgres_interrupt_deadline_is_atomic(store: PostgresRunStore) -> None:
+ queued = store.create_run(_run())
+ running = store.transition_run(
+ queued.id,
+ expected_version=queued.version,
+ target=RunStatus.RUNNING,
+ )
+ interrupt = Interrupt.create(
+ run_id=running.id,
+ kind=InterruptKind.INPUT,
+ request={"question": "continue?"},
+ timeout_seconds=1,
+ )
+ store.create_interrupt(interrupt, expected_run_version=running.version)
+ assert interrupt.expires_at is not None
+
+ assert store.expire_interrupts(now=interrupt.expires_at + timedelta(seconds=1)) == (
+ interrupt.id,
+ )
+ assert store.get_run(running.id).status is RunStatus.TIMED_OUT
+
+
+def test_postgres_idempotency_and_claim_are_concurrency_safe(
+ store: PostgresRunStore,
+) -> None:
+ candidate = _run(key="same")
+ with ThreadPoolExecutor(max_workers=8) as pool:
+ ids = list(pool.map(lambda _: store.create_run(candidate).id, range(16)))
+ assert set(ids) == {candidate.id}
+
+ with ThreadPoolExecutor(max_workers=8) as pool:
+ claims = list(
+ pool.map(
+ lambda index: store.claim_next(
+ worker_id=f"worker-{index}", lease_seconds=30
+ ),
+ range(8),
+ )
+ )
+ winners = [claim for claim in claims if claim is not None]
+ assert len(winners) == 1
+ assert winners[0].run.status is RunStatus.RUNNING
+
+
+def test_postgres_checkpoint_fencing_and_orphan_recovery(
+ store: PostgresRunStore,
+) -> None:
+ queued = store.create_run(_run())
+ first = store.claim_next(worker_id="worker-1", lease_seconds=1)
+ assert first is not None
+ checkpoint = Checkpoint.create(
+ run_id=queued.id,
+ sequence=1,
+ plan_hash="b" * 64,
+ state={"count": 1},
+ next_nodes=(),
+ effect_watermark=0,
+ )
+ updated = store.commit_checkpoint(
+ checkpoint,
+ worker_id="worker-1",
+ fencing_token=first.lease.fencing_token,
+ expected_run_version=first.run.version,
+ )
+ future = datetime.now(timezone.utc) + timedelta(seconds=2)
+ assert store.requeue_expired_leases(now=future) == (queued.id,)
+ second = store.claim_next(worker_id="worker-2", lease_seconds=30, now=future)
+ assert second is not None
+ assert second.lease.fencing_token == 2
+ with pytest.raises(ConflictError, match="fencing"):
+ store.finish_claim(
+ updated.id,
+ worker_id="worker-1",
+ fencing_token=first.lease.fencing_token,
+ expected_run_version=updated.version,
+ target=RunStatus.SUCCEEDED,
+ )
+
+
+def test_postgres_effect_ledger_persists_ambiguous_dispatch(
+ store: PostgresRunStore,
+) -> None:
+ run = store.create_run(_run())
+ running = store.transition_run(run.id, expected_version=0, target=RunStatus.RUNNING)
+ ledger = PostgresEffectLedger(store.dsn, schema=store.schema)
+ invocation = ledger.prepare(
+ run_id=running.id,
+ tool_name="payment.charge@1",
+ effect_class=EffectClass.NON_IDEMPOTENT,
+ arguments_digest=arguments_digest({"amount": 42}),
+ idempotency_key="charge-42",
+ )
+ dispatched = ledger.mark_dispatched(invocation.id)
+
+ assert dispatched.status.value == "dispatched"
+ stale = ledger.reconcile_stale(
+ older_than=datetime.now(timezone.utc) + timedelta(seconds=1)
+ )
+ assert stale[0].status.value == "ambiguous"
+
+
+def test_postgres_server_resources_share_run_transaction_domain(
+ store: PostgresRunStore,
+) -> None:
+ resources = PostgresResourceStore(store)
+ revision_id = uuid4()
+ assistant = resources.create_assistant(
+ tenant_id="postgres-test",
+ id="tenant-agent",
+ template_id="deployed-template",
+ revision_id=revision_id,
+ )
+ session = resources.create_session("postgres-test")
+ run = store.create_run(
+ Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=session.id,
+ tenant_id="postgres-test",
+ )
+ )
+ feedback = resources.create_feedback(
+ tenant_id="postgres-test",
+ run_id=run.id,
+ key="quality",
+ score=1,
+ value=None,
+ )
+
+ assert resources.get_assistant("postgres-test", "tenant-agent") == assistant
+ assert resources.list_assistants("postgres-test") == (assistant,)
+ assert resources.list_assistants("other") == ()
+ assert resources.get_session(session.id) == session
+ assert resources.count_tenants() == ("postgres-test",)
+ assert feedback.run_id == run.id
+
+
+def test_postgres_evaluation_results_are_durable(store: PostgresRunStore) -> None:
+ evaluations = PostgresEvaluationStore(store)
+ dataset = Dataset(
+ id=uuid4(),
+ name="integration",
+ version="1",
+ examples=(Example.create({"input": "x"}, {"output": "y"}),),
+ )
+ experiment = Experiment(
+ id=uuid4(),
+ dataset_id=dataset.id,
+ revision_id=uuid4(),
+ results=(
+ EvaluationResult(
+ evaluator="test",
+ score=1,
+ passed=True,
+ reason="ok",
+ ),
+ ),
+ )
+ evaluations.save_dataset(dataset)
+ evaluations.save_experiment(experiment)
+
+ assert evaluations.get_dataset(dataset.id) == dataset
+ assert evaluations.get_experiment(experiment.id) == experiment
diff --git a/tests/integration/test_redis_signals.py b/tests/integration/test_redis_signals.py
new file mode 100644
index 0000000..6787e66
--- /dev/null
+++ b/tests/integration/test_redis_signals.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+
+import os
+from datetime import datetime, timezone
+from uuid import uuid4
+
+import pytest
+
+from rath.runtime import RedisSignalBus, RunSignal, SignalKind
+
+pytestmark = pytest.mark.skipif(
+ not os.getenv("OPENRATH_TEST_REDIS_URL"),
+ reason="OPENRATH_TEST_REDIS_URL is not configured",
+)
+
+
+def test_redis_signal_real_round_trip() -> None:
+ namespace = f"openrath-test-{uuid4().hex}"
+ bus = RedisSignalBus(os.environ["OPENRATH_TEST_REDIS_URL"], namespace=namespace)
+ signal = RunSignal(
+ kind=SignalKind.CANCEL,
+ run_id=uuid4(),
+ tenant_id="tenant",
+ created_at=datetime.now(timezone.utc),
+ )
+ bus.publish(signal)
+ assert bus.receive(timeout_seconds=1) == signal
diff --git a/tests/integration/test_s3_artifact_store.py b/tests/integration/test_s3_artifact_store.py
new file mode 100644
index 0000000..990d17c
--- /dev/null
+++ b/tests/integration/test_s3_artifact_store.py
@@ -0,0 +1,51 @@
+from __future__ import annotations
+
+import os
+from uuid import uuid4
+
+import pytest
+
+from rath.artifacts import ArtifactNotFound, S3ArtifactStore
+
+pytestmark = pytest.mark.skipif(
+ not os.getenv("OPENRATH_TEST_S3_ENDPOINT"),
+ reason="OPENRATH_TEST_S3_ENDPOINT is not configured",
+)
+
+
+def test_s3_artifact_real_lifecycle() -> None:
+ import boto3
+
+ endpoint = os.environ["OPENRATH_TEST_S3_ENDPOINT"]
+ bucket = f"openrath-{uuid4().hex}"
+ client = boto3.client(
+ "s3",
+ endpoint_url=endpoint,
+ region_name="us-east-1",
+ aws_access_key_id=os.environ["OPENRATH_TEST_S3_ACCESS_KEY"],
+ aws_secret_access_key=os.environ["OPENRATH_TEST_S3_SECRET_KEY"],
+ )
+ client.create_bucket(Bucket=bucket)
+ try:
+ store = S3ArtifactStore(bucket, client=client)
+ artifact = store.put(
+ "tenant-a",
+ b"object-store-result",
+ media_type="text/plain",
+ metadata={"source": "integration"},
+ )
+
+ assert store.stat("tenant-a", artifact.digest) == artifact
+ assert store.get("tenant-a", artifact.digest) == b"object-store-result"
+ with pytest.raises(ArtifactNotFound):
+ store.get("tenant-b", artifact.digest)
+ assert store.delete("tenant-a", artifact.digest)
+ assert not store.delete("tenant-a", artifact.digest)
+ finally:
+ objects = client.list_objects_v2(Bucket=bucket).get("Contents", [])
+ if objects:
+ client.delete_objects(
+ Bucket=bucket,
+ Delete={"Objects": [{"Key": item["Key"]} for item in objects]},
+ )
+ client.delete_bucket(Bucket=bucket)
diff --git a/tests/integration/test_v1_migration_postgres.py b/tests/integration/test_v1_migration_postgres.py
new file mode 100644
index 0000000..365b219
--- /dev/null
+++ b/tests/integration/test_v1_migration_postgres.py
@@ -0,0 +1,74 @@
+from __future__ import annotations
+
+import json
+import os
+import subprocess
+import sys
+from pathlib import Path
+from uuid import uuid4
+
+import pytest
+
+from rath.runtime import PostgresRunStore, RunStatus
+from rath.session import Session
+from rath.session.chunk import ChunkTable
+from rath.session.persistence.writer import SessionWriter
+
+pytestmark = pytest.mark.skipif(
+ not os.getenv("OPENRATH_TEST_POSTGRES_DSN"),
+ reason="OPENRATH_TEST_POSTGRES_DSN is not configured",
+)
+
+
+def test_v1_session_import_real_postgres(tmp_path: Path) -> None:
+ dsn = os.environ["OPENRATH_TEST_POSTGRES_DSN"]
+ schema = f"migration_{uuid4().hex}"
+ source = tmp_path / "sessions"
+ source.mkdir()
+ session = Session(chunk_table=ChunkTable(rows=()))
+ SessionWriter(session, path=source / f"{session.id}.jsonl").close()
+ report = tmp_path / "result.json"
+ artifact_root = tmp_path / "artifacts"
+ try:
+ result = subprocess.run(
+ [
+ sys.executable,
+ "scripts/migrate_v1_to_v2.py",
+ "--source",
+ str(source),
+ "--report",
+ str(report),
+ "--tenant",
+ "migration-tenant",
+ "--apply",
+ "--postgres-dsn",
+ dsn,
+ "--schema",
+ schema,
+ "--artifact-root",
+ str(artifact_root),
+ ],
+ check=False,
+ capture_output=True,
+ text=True,
+ )
+ assert result.returncode == 0, result.stderr
+ payload = json.loads(report.read_text(encoding="utf-8"))
+ assert payload["summary"]["imported"] == 1
+ PostgresRunStore.migrate(dsn, schema=schema)
+ store = PostgresRunStore(dsn, schema=schema)
+ runs = store.list_runs(tenant_id="migration-tenant")
+ assert len(runs) == 1
+ assert runs[0].status is RunStatus.SUCCEEDED
+ assert runs[0].state["resumable"] is False
+ store.close()
+ finally:
+ import psycopg
+ from psycopg import sql
+
+ with psycopg.connect(dsn) as connection:
+ connection.execute(
+ sql.SQL("DROP SCHEMA IF EXISTS {} CASCADE").format(
+ sql.Identifier(schema)
+ )
+ )
diff --git a/tests/memory/backends/conftest.py b/tests/memory/backends/conftest.py
index ded12b5..78d54b6 100644
--- a/tests/memory/backends/conftest.py
+++ b/tests/memory/backends/conftest.py
@@ -119,7 +119,7 @@ def add_resource_with_retry(
raise last_exc
-@pytest.fixture(autouse=True)
+@pytest.fixture(scope="session", autouse=True)
def _openviking_canary() -> Iterator[None]:
pytest.importorskip("openviking", reason="openviking optional extra not installed")
url = os.environ.get("OPEN_VIKING_URL", _DEFAULT_URL)
diff --git a/tests/memory/local_backend/conftest.py b/tests/memory/local_backend/conftest.py
index b9d0dd5..1e29862 100644
--- a/tests/memory/local_backend/conftest.py
+++ b/tests/memory/local_backend/conftest.py
@@ -7,7 +7,7 @@
import pytest
-from rath.memory import MemoryStore
+from rath.memory import MemoryStore, MemoryStoreSpec
from rath.memory.adapters.local import LocalMemoryBackend
@@ -30,8 +30,18 @@ def backend() -> Iterator[LocalMemoryBackend]:
@pytest.fixture
-def store(backend: LocalMemoryBackend) -> Iterator[MemoryStore]:
- s = backend.open()
+def store(
+ backend: LocalMemoryBackend,
+ tmp_path: Path,
+) -> Iterator[MemoryStore]:
+ spec = MemoryStoreSpec(
+ options={
+ "resource_import_roots": [str(tmp_path)],
+ "resource_allowed_http_hosts": ["127.0.0.1"],
+ "resource_allow_private_hosts": True,
+ },
+ )
+ s = backend.open(spec)
try:
yield s
finally:
diff --git a/tests/memory/local_backend/test_local_memory_commit.py b/tests/memory/local_backend/test_local_memory_commit.py
index 6d15840..b9dfc6f 100644
--- a/tests/memory/local_backend/test_local_memory_commit.py
+++ b/tests/memory/local_backend/test_local_memory_commit.py
@@ -21,6 +21,7 @@
from rath.memory.op_types import MemoryOpCommit, MemoryOpList, MemoryOpRead
from rath.memory.results import (
MemoryCommitResult,
+ MemoryExecutionFailure,
MemoryListResult,
MemoryReadResult,
)
@@ -130,6 +131,23 @@ def test_commit_with_no_chat_client_skips_extraction(
assert not extracted_dir.exists()
+def test_commit_rejects_path_like_session_id(
+ backend: LocalMemoryBackend, store: MemoryStore, tmp_path: Path
+) -> None:
+ outside = tmp_path / "outside"
+ res = backend.dispatch(
+ store,
+ MemoryOpCommit(
+ session_id=f"../{outside.name}",
+ messages=[{"role": "user", "content": "x"}],
+ wait=False,
+ ),
+ )
+ assert isinstance(res, MemoryExecutionFailure)
+ assert res.kind == "invalid_uri"
+ assert not outside.exists()
+
+
# ----------------------------------------------------- Extraction (wait=True + live chat)
diff --git a/tests/memory/local_backend/test_local_memory_resource.py b/tests/memory/local_backend/test_local_memory_resource.py
index dba316f..158d37b 100644
--- a/tests/memory/local_backend/test_local_memory_resource.py
+++ b/tests/memory/local_backend/test_local_memory_resource.py
@@ -16,7 +16,7 @@
import pytest
-from rath.memory import MemoryStore
+from rath.memory import MemoryStore, MemoryStoreSpec
from rath.memory.adapters.local import LocalMemoryBackend
from rath.memory.op_types import MemoryOpResource
from rath.memory.results import (
@@ -99,6 +99,20 @@ def test_resource_ingest_missing_local_file_is_not_found(
assert res.kind == "not_found"
+def test_resource_ingest_rejects_local_file_without_import_root(
+ backend: LocalMemoryBackend, tmp_path: Path
+) -> None:
+ src = tmp_path / "secret.txt"
+ src.write_text("secret", encoding="utf-8")
+ unsafe_store = backend.open()
+ try:
+ res = backend.dispatch(unsafe_store, MemoryOpResource(source=str(src)))
+ finally:
+ backend.close(unsafe_store)
+ assert isinstance(res, MemoryExecutionFailure)
+ assert res.kind == "unauthorized"
+
+
def test_resource_ingest_rejects_unknown_target_scope(
backend: LocalMemoryBackend, store: MemoryStore, tmp_path: Path
) -> None:
@@ -182,3 +196,30 @@ def test_resource_ingest_http_url_persists_body(
assert blob.read_bytes() == _ServeBody.BODY
meta_body = (root / "meta.md").read_text(encoding="utf-8")
assert "127.0.0.1" in meta_body # original URL in meta
+
+
+def test_resource_ingest_rejects_http_url_without_allowed_host(
+ backend: LocalMemoryBackend, http_server: str
+) -> None:
+ unsafe_store = backend.open()
+ try:
+ res = backend.dispatch(unsafe_store, MemoryOpResource(source=http_server))
+ finally:
+ backend.close(unsafe_store)
+ assert isinstance(res, MemoryExecutionFailure)
+ assert res.kind == "unauthorized"
+
+
+def test_resource_ingest_blocks_private_host_without_opt_in(
+ backend: LocalMemoryBackend, http_server: str
+) -> None:
+ spec = MemoryStoreSpec(
+ options={"resource_allowed_http_hosts": ["127.0.0.1"]},
+ )
+ unsafe_store = backend.open(spec)
+ try:
+ res = backend.dispatch(unsafe_store, MemoryOpResource(source=http_server))
+ finally:
+ backend.close(unsafe_store)
+ assert isinstance(res, MemoryExecutionFailure)
+ assert res.kind == "unauthorized"
diff --git a/tests/memory/persistence/test_persistence.py b/tests/memory/persistence/test_persistence.py
index e1e6f41..74d5d93 100644
--- a/tests/memory/persistence/test_persistence.py
+++ b/tests/memory/persistence/test_persistence.py
@@ -13,6 +13,8 @@
from pathlib import Path
from uuid import UUID, uuid4
+import pytest
+
from rath.memory.persistence import (
PersistentMemoryRegistry,
local_memory_root,
@@ -56,6 +58,15 @@ def test_local_store_dir_accepts_str(_isolate_openrath_home: Path) -> None:
assert local_store_dir(str(sid)) == local_store_dir(sid)
+@pytest.mark.parametrize("bad_id", ["../escape", "/tmp/escape", "not-a-uuid"])
+def test_local_store_dir_rejects_path_like_ids(
+ _isolate_openrath_home: Path,
+ bad_id: str,
+) -> None:
+ with pytest.raises(ValueError, match="store_id must be a UUID"):
+ local_store_dir(bad_id)
+
+
def test_ensure_local_memory_root_creates_and_is_idempotent(
_isolate_openrath_home: Path,
) -> None:
diff --git a/tests/memory/unit/test_openviking_result_compat.py b/tests/memory/unit/test_openviking_result_compat.py
new file mode 100644
index 0000000..4abadb6
--- /dev/null
+++ b/tests/memory/unit/test_openviking_result_compat.py
@@ -0,0 +1,67 @@
+"""OpenViking SDK result-shape compatibility without a live server."""
+
+from __future__ import annotations
+
+from types import SimpleNamespace
+
+import pytest
+
+pytest.importorskip("openviking")
+
+from rath.memory.adapters.openviking import _hits_from_findresult # noqa: E402
+
+
+def test_http_mapping_result_is_normalized() -> None:
+ hits = _hits_from_findresult(
+ {
+ "memories": [
+ {
+ "uri": "viking://user/memories/preferences/style.md",
+ "score": 0.8,
+ "abstract": "Prefers concise answers.",
+ "level": 0,
+ }
+ ],
+ "resources": [
+ {
+ "uri": "viking://resources/runbook.md",
+ "score": 0.95,
+ "overview": "Production runbook.",
+ "level": 1,
+ }
+ ],
+ "skills": [],
+ }
+ )
+
+ assert [hit.uri for hit in hits] == [
+ "memory://resources/runbook.md",
+ "memory://user/memories/preferences/style.md",
+ ]
+ assert [hit.level for hit in hits] == ["overview", "abstract"]
+ assert [hit.snippet for hit in hits] == [
+ "Production runbook.",
+ "Prefers concise answers.",
+ ]
+
+
+def test_embedded_object_result_remains_supported() -> None:
+ hits = _hits_from_findresult(
+ SimpleNamespace(
+ memories=[],
+ resources=[],
+ skills=[
+ SimpleNamespace(
+ uri="viking://agent/skills/release",
+ score=0.7,
+ abstract="Release safely.",
+ overview=None,
+ level=2,
+ )
+ ],
+ )
+ )
+
+ assert len(hits) == 1
+ assert hits[0].uri == "memory://agent/skills/release"
+ assert hits[0].level == "detail"
diff --git a/tests/migration/test_v1_to_v2.py b/tests/migration/test_v1_to_v2.py
new file mode 100644
index 0000000..26f4683
--- /dev/null
+++ b/tests/migration/test_v1_to_v2.py
@@ -0,0 +1,85 @@
+from __future__ import annotations
+
+import json
+import subprocess
+import sys
+from pathlib import Path
+
+from rath.session import Session
+from rath.session.chunk import ChunkTable
+from rath.session.persistence.writer import SessionWriter
+
+
+def test_v1_migration_inventory_is_read_only_and_machine_readable(
+ tmp_path: Path,
+) -> None:
+ source = tmp_path / "sessions"
+ source.mkdir()
+ session = Session(chunk_table=ChunkTable(rows=()))
+ legacy_path = source / f"{session.id}.jsonl"
+ SessionWriter(session, path=legacy_path).close()
+ before = legacy_path.read_bytes()
+ report = tmp_path / "inventory.json"
+
+ result = subprocess.run(
+ [
+ sys.executable,
+ "scripts/migrate_v1_to_v2.py",
+ "--source",
+ str(source),
+ "--report",
+ str(report),
+ "--tenant",
+ "tenant-1",
+ ],
+ check=False,
+ capture_output=True,
+ text=True,
+ )
+
+ assert result.returncode == 0, result.stderr
+ assert legacy_path.read_bytes() == before
+ payload = json.loads(report.read_text(encoding="utf-8"))
+ assert payload["mode"] == "inventory"
+ assert payload["summary"] == {
+ "total": 1,
+ "ready": 1,
+ "imported": 0,
+ "invalid": 0,
+ }
+
+
+def test_v1_migration_reports_bad_filename_and_continues(tmp_path: Path) -> None:
+ source = tmp_path / "sessions"
+ source.mkdir()
+ (source / "not-a-uuid.jsonl").write_text("{}\n", encoding="utf-8")
+ session = Session(chunk_table=ChunkTable(rows=()))
+ SessionWriter(session, path=source / f"{session.id}.jsonl").close()
+ report = tmp_path / "inventory.json"
+
+ result = subprocess.run(
+ [
+ sys.executable,
+ "scripts/migrate_v1_to_v2.py",
+ "--source",
+ str(source),
+ "--report",
+ str(report),
+ "--tenant",
+ "tenant-1",
+ ],
+ check=False,
+ capture_output=True,
+ text=True,
+ )
+
+ assert result.returncode == 0, result.stderr
+ payload = json.loads(report.read_text(encoding="utf-8"))
+ assert payload["summary"] == {
+ "total": 2,
+ "ready": 1,
+ "imported": 0,
+ "invalid": 1,
+ }
+ invalid = next(item for item in payload["sessions"] if item["status"] == "invalid")
+ assert invalid["error_code"] == "invalid_session_id"
diff --git a/tests/observability/test_telemetry.py b/tests/observability/test_telemetry.py
new file mode 100644
index 0000000..15717ba
--- /dev/null
+++ b/tests/observability/test_telemetry.py
@@ -0,0 +1,88 @@
+from __future__ import annotations
+
+from contextlib import contextmanager
+
+from rath.context import TraceContext
+from rath.observability import (
+ GuardedTelemetry,
+ InMemoryTelemetry,
+ OpenTelemetry,
+ StructuredLogger,
+ redact,
+)
+
+
+def test_span_records_status_and_correlation() -> None:
+ telemetry = InMemoryTelemetry()
+ trace = TraceContext.new()
+ with telemetry.span("run", context=trace, attributes={"run.status": "running"}):
+ pass
+ assert telemetry.spans[0].trace_id == trace.trace_id
+ assert telemetry.spans[0].status == "ok"
+
+
+def test_redaction_is_recursive() -> None:
+ assert redact({"api_key": "x", "nested": {"password": "y"}}) == {
+ "api_key": "",
+ "nested": {"password": ""},
+ }
+
+
+def test_guarded_telemetry_swallows_exporter_failure() -> None:
+ class Broken:
+ @contextmanager
+ def span(self, name, *, context, attributes=None): # type: ignore[no-untyped-def]
+ yield
+ raise RuntimeError("export failed")
+
+ def increment(self, name, value=1, *, attributes=None): # type: ignore[no-untyped-def]
+ raise RuntimeError("export failed")
+
+ guarded = GuardedTelemetry(Broken())
+ with guarded.span("run", context=TraceContext.new()):
+ value = 42
+ guarded.increment("counter")
+ assert value == 42
+
+
+def test_otel_bridge_preserves_parent_trace_and_redacts_secrets() -> None:
+ from opentelemetry.sdk.trace import TracerProvider
+ from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+ from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
+ InMemorySpanExporter,
+ )
+
+ exporter = InMemorySpanExporter()
+ provider = TracerProvider()
+ provider.add_span_processor(SimpleSpanProcessor(exporter))
+ telemetry = OpenTelemetry(tracer_provider=provider)
+ context = TraceContext.new()
+ with telemetry.span(
+ "openrath.run",
+ context=context,
+ attributes={"run_id": "r1", "api_key": "secret"},
+ ):
+ pass
+
+ span = exporter.get_finished_spans()[0]
+ assert f"{span.context.trace_id:032x}" == context.trace_id
+ assert span.attributes["api_key"] == ""
+
+
+def test_structured_logger_correlates_and_redacts() -> None:
+ import json
+
+ records: list[str] = []
+ trace = TraceContext.new()
+ logger = StructuredLogger(records.append)
+ logger.emit(
+ "run.failed",
+ context=trace,
+ fields={"run_id": "run-1", "api_key": "secret"},
+ )
+
+ parsed = json.loads(records[0])
+ assert parsed["event"] == "run.failed"
+ assert parsed["trace_id"] == trace.trace_id
+ assert parsed["run_id"] == "run-1"
+ assert parsed["api_key"] == ""
diff --git a/tests/runtime/test_effect_ledger.py b/tests/runtime/test_effect_ledger.py
new file mode 100644
index 0000000..8f6f368
--- /dev/null
+++ b/tests/runtime/test_effect_ledger.py
@@ -0,0 +1,162 @@
+from __future__ import annotations
+
+from datetime import datetime, timedelta, timezone
+from pathlib import Path
+from uuid import uuid4
+
+from rath.definition import EffectClass
+from rath.runtime import (
+ InvocationStatus,
+ Run,
+ RunStatus,
+ SQLiteEffectLedger,
+ SQLiteRunStore,
+ arguments_digest,
+ reconcile_stale_effects,
+)
+
+
+def _running(store: SQLiteRunStore) -> Run:
+ queued = store.create_run(
+ Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant",
+ )
+ )
+ return store.transition_run(queued.id, expected_version=0, target=RunStatus.RUNNING)
+
+
+def test_completed_effect_is_deduplicated(tmp_path: Path) -> None:
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = _running(store)
+ ledger = SQLiteEffectLedger(str(path))
+ digest = arguments_digest({"to": "user@example.test"})
+ first = ledger.prepare(
+ run_id=run.id,
+ tool_name="email.send@1",
+ effect_class=EffectClass.NON_IDEMPOTENT,
+ arguments_digest=digest,
+ idempotency_key="email-1",
+ )
+ ledger.mark_dispatched(first.id)
+ completed = ledger.complete(first.id, {"message_id": "m-1"})
+ replay = ledger.prepare(
+ run_id=run.id,
+ tool_name="email.send@1",
+ effect_class=EffectClass.NON_IDEMPOTENT,
+ arguments_digest=digest,
+ idempotency_key="email-1",
+ )
+
+ assert completed.status is InvocationStatus.SUCCEEDED
+ assert replay == completed
+
+
+def test_crashed_non_idempotent_effect_requires_review(tmp_path: Path) -> None:
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = _running(store)
+ ledger = SQLiteEffectLedger(str(path))
+ invocation = ledger.prepare(
+ run_id=run.id,
+ tool_name="payment.charge@1",
+ effect_class=EffectClass.NON_IDEMPOTENT,
+ arguments_digest=arguments_digest({"amount": 10}),
+ idempotency_key="charge-1",
+ )
+ ledger.mark_dispatched(invocation.id)
+
+ result = reconcile_stale_effects(
+ ledger,
+ store,
+ grace_seconds=0,
+ now=datetime.now(timezone.utc) + timedelta(seconds=1),
+ )
+
+ assert result.needs_review == (invocation.id,)
+ assert ledger.get(invocation.id).status is InvocationStatus.AMBIGUOUS
+ assert store.get_run(run.id).status is RunStatus.NEEDS_REVIEW
+
+
+def test_crashed_idempotent_effect_is_retryable(tmp_path: Path) -> None:
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = _running(store)
+ ledger = SQLiteEffectLedger(str(path))
+ invocation = ledger.prepare(
+ run_id=run.id,
+ tool_name="object.put@1",
+ effect_class=EffectClass.IDEMPOTENT,
+ arguments_digest=arguments_digest({"key": "a"}),
+ idempotency_key="put-a",
+ )
+ ledger.mark_dispatched(invocation.id)
+ result = reconcile_stale_effects(
+ ledger,
+ store,
+ grace_seconds=0,
+ now=datetime.now(timezone.utc) + timedelta(seconds=1),
+ )
+
+ assert result.retryable == (invocation.id,)
+ assert ledger.get(invocation.id).status is InvocationStatus.PREPARED
+ assert store.get_run(run.id).status is RunStatus.RUNNING
+
+
+def test_crashed_idempotent_effect_without_key_requires_review(
+ tmp_path: Path,
+) -> None:
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = _running(store)
+ ledger = SQLiteEffectLedger(str(path))
+ invocation = ledger.prepare(
+ run_id=run.id,
+ tool_name="object.put@1",
+ effect_class=EffectClass.IDEMPOTENT,
+ arguments_digest=arguments_digest({"key": "a"}),
+ idempotency_key=None,
+ )
+ ledger.mark_dispatched(invocation.id)
+
+ result = reconcile_stale_effects(
+ ledger,
+ store,
+ grace_seconds=0,
+ now=datetime.now(timezone.utc) + timedelta(seconds=1),
+ )
+
+ assert result.needs_review == (invocation.id,)
+ assert ledger.get(invocation.id).status is InvocationStatus.AMBIGUOUS
+ assert store.get_run(run.id).status is RunStatus.NEEDS_REVIEW
+
+
+def test_runtime_reconciles_effects_before_expired_run_requeue(
+ tmp_path: Path,
+) -> None:
+ from rath.runtime import LocalRuntime
+
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = _running(store)
+ ledger = SQLiteEffectLedger(str(path))
+ invocation = ledger.prepare(
+ run_id=run.id,
+ tool_name="payment.charge@1",
+ effect_class=EffectClass.NON_IDEMPOTENT,
+ arguments_digest=arguments_digest({"amount": 10}),
+ idempotency_key="charge-1",
+ )
+ ledger.mark_dispatched(invocation.id)
+ runtime = LocalRuntime(store, effect_ledger=ledger)
+
+ result = runtime.reconcile_effects(
+ grace_seconds=0,
+ now=datetime.now(timezone.utc) + timedelta(seconds=1),
+ )
+
+ assert result.needs_review == (invocation.id,)
+ assert store.get_run(run.id).status is RunStatus.NEEDS_REVIEW
diff --git a/tests/runtime/test_local_runtime.py b/tests/runtime/test_local_runtime.py
new file mode 100644
index 0000000..9042795
--- /dev/null
+++ b/tests/runtime/test_local_runtime.py
@@ -0,0 +1,282 @@
+from __future__ import annotations
+
+from datetime import datetime, timedelta, timezone
+from pathlib import Path
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.definition import EffectClass, RetryPolicy, router, step
+from rath.flow import Workflow
+from rath.runtime import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ InterruptKind,
+ LocalRuntime,
+ RunStatus,
+ SQLiteRunStore,
+)
+from rath.security import Principal, PrincipalKind, SecurityContext
+from rath.session import Session
+
+
+class _Workflow(Workflow):
+ @step(entry=True, successors=("route",), effects=EffectClass.READ_ONLY)
+ async def start(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "count": state.get("count", 0) + 1}
+
+ @router(successors=("finish", "review"))
+ def route(self, state): # type: ignore[no-untyped-def]
+ return "finish" if state["count"] == 1 else "review"
+
+ @step(effects=EffectClass.READ_ONLY)
+ def finish(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "result": "done"}
+
+ @step(effects=EffectClass.READ_ONLY)
+ def review(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def test_local_runtime_executes_and_checkpoints_every_step(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ context = RunContext.local(revision_id=uuid4())
+ submitted = runtime.submit(
+ _Workflow(),
+ session_id=uuid4(),
+ context=context,
+ state={"count": 0},
+ idempotency_key="request-1",
+ )
+
+ completed = runtime.work_once(worker_id="worker-1")
+
+ assert completed is not None
+ assert completed.id == submitted.id
+ assert completed.status is RunStatus.SUCCEEDED
+ assert completed.state["result"] == "done"
+ checkpoints = store.list_checkpoints(completed.id)
+ assert [checkpoint.sequence for checkpoint in checkpoints] == [1, 2, 3]
+ assert checkpoints[-1].next_nodes == ()
+
+
+def test_runtime_resumes_from_committed_checkpoint_after_lease_expiry(
+ tmp_path: Path,
+) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ context = RunContext.local(revision_id=uuid4())
+ submitted = runtime.submit(
+ _Workflow(),
+ session_id=uuid4(),
+ context=context,
+ state={"count": 0},
+ )
+ partial = runtime.work_once(worker_id="worker-1", max_steps=1, lease_seconds=1)
+ assert partial is not None
+ assert partial.status is RunStatus.RUNNING
+ assert partial.next_nodes == ("route",)
+
+ future = datetime.now(timezone.utc) + timedelta(seconds=2)
+ assert store.requeue_expired_leases(now=future) == (submitted.id,)
+ resumed = runtime.work_once(worker_id="worker-2", now=future)
+
+ assert resumed is not None
+ assert resumed.status is RunStatus.SUCCEEDED
+ assert resumed.state["count"] == 1
+ assert len(store.list_checkpoints(resumed.id)) == 3
+
+
+def test_runtime_marks_step_exception_failed(tmp_path: Path) -> None:
+ class _Broken(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def broken(self, state, context): # type: ignore[no-untyped-def]
+ raise RuntimeError("boom")
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ runtime.submit(
+ _Broken(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+
+ failed = runtime.work_once(worker_id="worker-1")
+
+ assert failed is not None
+ assert failed.status is RunStatus.FAILED
+ assert any(
+ event.type == "run.execution.failed"
+ for event in store.list_run_events(failed.id)
+ )
+
+
+def test_worker_restores_security_context_after_process_restart(
+ tmp_path: Path,
+) -> None:
+ seen: list[tuple[str, str]] = []
+
+ class _ContextWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def capture(self, state, context): # type: ignore[no-untyped-def]
+ seen.append(
+ (
+ context.request.security.tenant_id,
+ context.request.security.principal.id,
+ )
+ )
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ path = tmp_path / "runtime.db"
+ revision_id = uuid4()
+ workflow = _ContextWorkflow()
+ first_store = SQLiteRunStore(path)
+ first = LocalRuntime(first_store)
+ first.submit(
+ workflow,
+ session_id=uuid4(),
+ context=RunContext(
+ security=SecurityContext(
+ principal=Principal(id="user-42", kind=PrincipalKind.USER),
+ tenant_id="tenant-42",
+ grants=frozenset({"tool.read"}),
+ ),
+ revision_id=revision_id,
+ ),
+ )
+ first_store.close()
+
+ second_store = SQLiteRunStore(path)
+ second = LocalRuntime(second_store)
+ second.register(workflow, revision_id=revision_id)
+ completed = second.work_once(worker_id="worker-after-restart")
+
+ assert completed is not None
+ assert completed.status is RunStatus.SUCCEEDED
+ assert seen == [("tenant-42", "user-42")]
+
+
+def test_runtime_retries_declared_idempotent_step(tmp_path: Path) -> None:
+ attempts = 0
+
+ class _Retry(Workflow):
+ @step(
+ entry=True,
+ effects=EffectClass.IDEMPOTENT,
+ idempotency_key="run-step",
+ retry=RetryPolicy(max_attempts=3, base_seconds=0.001),
+ )
+ def unstable(self, state, context): # type: ignore[no-untyped-def]
+ nonlocal attempts
+ attempts += 1
+ if attempts < 3:
+ raise ConnectionError("temporary")
+ return {"ok": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ submitted = runtime.submit(
+ _Retry(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None and completed.status is RunStatus.SUCCEEDED
+ assert attempts == 3
+ failures = [
+ event
+ for event in store.list_run_events(submitted.id)
+ if event.type == "run.step.attempt.failed"
+ ]
+ assert len(failures) == 2
+
+
+def test_runtime_enforces_async_step_timeout(tmp_path: Path) -> None:
+ import asyncio
+
+ class _Timeout(Workflow):
+ @step(
+ entry=True,
+ effects=EffectClass.READ_ONLY,
+ timeout_seconds=0.01,
+ )
+ async def slow(self, state, context): # type: ignore[no-untyped-def]
+ await asyncio.sleep(1)
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ runtime.submit(
+ _Timeout(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None
+ assert completed.status is RunStatus.TIMED_OUT
+
+
+def test_runtime_durably_suspends_and_resumes_human_decision(
+ tmp_path: Path,
+) -> None:
+ class _Approval(Workflow):
+ @step(entry=True, effects=EffectClass.NON_IDEMPOTENT)
+ def approve(self, state, context): # type: ignore[no-untyped-def]
+ decision = context.interrupt(
+ InterruptKind.APPROVAL,
+ {"tool": "email.send", "arguments": {"to": "user@example.com"}},
+ )
+ return {
+ "decision": decision.kind.value,
+ "edited": decision.payload.get("arguments"),
+ }
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ submitted = runtime.submit(
+ _Approval(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+
+ waiting = runtime.work_once(worker_id="worker-1")
+ assert waiting is not None and waiting.status is RunStatus.WAITING
+ (interrupt,) = store.list_interrupts(tenant_id="local")
+ resumed = store.decide_interrupt(
+ interrupt.id,
+ decision=ApprovalDecision(
+ kind=ApprovalDecisionKind.EDIT,
+ actor_id="reviewer",
+ reason="replace recipient",
+ payload={"arguments": {"to": "safe@example.com"}},
+ ),
+ expected_run_version=waiting.version,
+ )
+ assert resumed.status is RunStatus.QUEUED
+
+ completed = runtime.work_once(worker_id="worker-2")
+ assert completed is not None and completed.status is RunStatus.SUCCEEDED
+ assert completed.id == submitted.id
+ assert completed.state["decision"] == "edit"
+ assert completed.state["edited"] == {"to": "safe@example.com"}
+ assert len(store.list_interrupts(tenant_id="local", pending_only=False)) == 1
diff --git a/tests/runtime/test_review_regressions.py b/tests/runtime/test_review_regressions.py
new file mode 100644
index 0000000..caa7088
--- /dev/null
+++ b/tests/runtime/test_review_regressions.py
@@ -0,0 +1,209 @@
+from __future__ import annotations
+
+import time
+from pathlib import Path
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import (
+ Checkpoint,
+ LocalRuntime,
+ RunStatus,
+ SQLiteEffectLedger,
+ SQLiteRunStore,
+ arguments_digest,
+)
+from rath.session import Session
+
+
+def test_sync_timeout_does_not_report_terminal_while_handler_runs(
+ tmp_path: Path,
+) -> None:
+ effects: list[str] = []
+
+ class _SyncTimeout(Workflow):
+ @step(
+ entry=True,
+ effects=EffectClass.READ_ONLY,
+ timeout_seconds=0.01,
+ )
+ def slow(self, state, context): # type: ignore[no-untyped-def]
+ time.sleep(0.05)
+ effects.append("completed")
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ runtime.submit(
+ _SyncTimeout(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+
+ started = time.perf_counter()
+ completed = runtime.work_once(worker_id="worker")
+ elapsed = time.perf_counter() - started
+
+ assert completed is not None
+ assert completed.status is RunStatus.TIMED_OUT
+ assert elapsed >= 0.05
+ assert effects == ["completed"]
+
+
+def test_checkpoint_false_skips_non_terminal_checkpoint(tmp_path: Path) -> None:
+ class _NoCheckpoint(Workflow):
+ @step(
+ entry=True,
+ successors=("finish",),
+ effects=EffectClass.READ_ONLY,
+ checkpoint=False,
+ )
+ def start(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "started": True}
+
+ @step(effects=EffectClass.READ_ONLY)
+ def finish(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "finished": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ run = runtime.submit(
+ _NoCheckpoint(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None
+ assert completed.status is RunStatus.SUCCEEDED
+ checkpoints = store.list_checkpoints(run.id)
+ assert len(checkpoints) == 1
+ assert checkpoints[0].state["finished"] is True
+
+
+def test_runtime_enforces_declared_input_and_state_schema(tmp_path: Path) -> None:
+ class _SchemaWorkflow(Workflow):
+ input_schema = {
+ "type": "object",
+ "required": ["count"],
+ "properties": {"count": {"type": "integer"}},
+ }
+ state_schema = {
+ "type": "object",
+ "required": ["count"],
+ "properties": {"count": {"type": "integer"}},
+ }
+
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def corrupt(self, state, context): # type: ignore[no-untyped-def]
+ return {"count": "not-an-integer"}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+
+ try:
+ runtime.submit(
+ _SchemaWorkflow(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ state={"count": "bad"},
+ )
+ except Exception as exc:
+ assert type(exc).__name__ == "SchemaValidationError"
+ else:
+ raise AssertionError("invalid input schema was accepted")
+
+ run = runtime.submit(
+ _SchemaWorkflow(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ state={"count": 1},
+ )
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None
+ assert completed.status is RunStatus.FAILED
+ assert store.list_checkpoints(run.id) == ()
+
+
+def test_checkpoint_records_effect_watermark(tmp_path: Path) -> None:
+ class _EffectWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def finish(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ ledger = SQLiteEffectLedger(str(path))
+ runtime = LocalRuntime(store, effect_ledger=ledger)
+ run = runtime.submit(
+ _EffectWorkflow(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ invocation = ledger.prepare(
+ run_id=run.id,
+ tool_name="lookup@1",
+ effect_class=EffectClass.READ_ONLY,
+ arguments_digest=arguments_digest({}),
+ idempotency_key="lookup",
+ )
+ ledger.complete(invocation.id, {"ok": True})
+
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None
+ assert store.list_checkpoints(run.id)[0].effect_watermark == 1
+
+
+def test_runtime_fails_closed_on_checkpoint_plan_mismatch(
+ tmp_path: Path,
+) -> None:
+ class _ResumeWorkflow(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def finish(self, state, context): # type: ignore[no-untyped-def]
+ return state
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ run = runtime.submit(
+ _ResumeWorkflow(),
+ session_id=uuid4(),
+ context=RunContext.local(revision_id=uuid4()),
+ )
+ store.append_checkpoint(
+ Checkpoint.create(
+ run_id=run.id,
+ sequence=1,
+ plan_hash="0" * 64,
+ state={},
+ next_nodes=("finish",),
+ effect_watermark=0,
+ )
+ )
+
+ completed = runtime.work_once(worker_id="worker")
+
+ assert completed is not None
+ assert completed.status is RunStatus.FAILED
+ assert any(
+ event.data.get("error_type") == "PlanMismatchError"
+ for event in store.list_run_events(run.id)
+ )
diff --git a/tests/runtime/test_run_state.py b/tests/runtime/test_run_state.py
new file mode 100644
index 0000000..0354c63
--- /dev/null
+++ b/tests/runtime/test_run_state.py
@@ -0,0 +1,60 @@
+from __future__ import annotations
+
+from uuid import uuid4
+
+import pytest
+
+from rath.runtime import (
+ InvalidRunTransition,
+ Run,
+ RunStatus,
+ assert_transition,
+)
+
+
+def _run(status: RunStatus = RunStatus.QUEUED) -> Run:
+ return Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-1",
+ status=status,
+ state={"query": "hello"},
+ next_nodes=("search",),
+ )
+
+
+@pytest.mark.parametrize(
+ ("source", "target"),
+ [
+ (RunStatus.QUEUED, RunStatus.RUNNING),
+ (RunStatus.RUNNING, RunStatus.WAITING),
+ (RunStatus.WAITING, RunStatus.QUEUED),
+ (RunStatus.RUNNING, RunStatus.SUCCEEDED),
+ (RunStatus.RUNNING, RunStatus.NEEDS_REVIEW),
+ (RunStatus.NEEDS_REVIEW, RunStatus.QUEUED),
+ ],
+)
+def test_valid_run_transitions(source: RunStatus, target: RunStatus) -> None:
+ assert_transition(source, target)
+
+
+def test_terminal_run_is_immutable() -> None:
+ with pytest.raises(InvalidRunTransition):
+ assert_transition(RunStatus.SUCCEEDED, RunStatus.RUNNING)
+
+
+def test_run_state_is_deeply_immutable() -> None:
+ state = {"nested": {"value": 1}}
+ run = Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-1",
+ state=state,
+ next_nodes=("search",),
+ )
+ state["nested"]["value"] = 2
+
+ assert run.state["nested"]["value"] == 1 # type: ignore[index]
+ assert run.version == 0
diff --git a/tests/runtime/test_scheduler_leases.py b/tests/runtime/test_scheduler_leases.py
new file mode 100644
index 0000000..ef1a092
--- /dev/null
+++ b/tests/runtime/test_scheduler_leases.py
@@ -0,0 +1,125 @@
+from __future__ import annotations
+
+from concurrent.futures import ThreadPoolExecutor
+from datetime import datetime, timedelta, timezone
+from pathlib import Path
+from uuid import uuid4
+
+import pytest
+
+from rath.runtime import ConflictError, Run, RunStatus, SQLiteRunStore
+
+
+def _run() -> Run:
+ return Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-1",
+ next_nodes=("start",),
+ )
+
+
+def test_claim_prefers_higher_priority_then_fifo(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ low = store.create_run(
+ Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-1",
+ priority=0,
+ )
+ )
+ high = store.create_run(
+ Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-2",
+ priority=10,
+ )
+ )
+
+ claim = store.claim_next(worker_id="worker", lease_seconds=30)
+
+ assert claim is not None
+ assert claim.run.id == high.id
+ assert claim.run.id != low.id
+
+
+def test_claim_is_exclusive_and_moves_run_to_running(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ queued = store.create_run(_run())
+
+ claim = store.claim_next(worker_id="worker-1", lease_seconds=30)
+
+ assert claim is not None
+ assert claim.run.id == queued.id
+ assert claim.run.status is RunStatus.RUNNING
+ assert claim.lease.holder_worker_id == "worker-1"
+ assert claim.lease.fencing_token == 1
+ assert store.claim_next(worker_id="worker-2", lease_seconds=30) is None
+
+
+def test_concurrent_claim_has_single_winner(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ store.create_run(_run())
+ with ThreadPoolExecutor(max_workers=8) as pool:
+ claims = list(
+ pool.map(
+ lambda index: store.claim_next(
+ worker_id=f"worker-{index}",
+ lease_seconds=30,
+ ),
+ range(8),
+ )
+ )
+
+ winners = [claim for claim in claims if claim is not None]
+ assert len(winners) == 1
+
+
+def test_lease_renewal_rejects_stale_fencing_token(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ store.create_run(_run())
+ claim = store.claim_next(worker_id="worker-1", lease_seconds=30)
+ assert claim is not None
+
+ renewed = store.renew_lease(
+ claim.run.id,
+ worker_id="worker-1",
+ fencing_token=claim.lease.fencing_token,
+ lease_seconds=60,
+ )
+ assert renewed.expires_at > claim.lease.expires_at
+
+ with pytest.raises(ConflictError, match="fencing"):
+ store.renew_lease(
+ claim.run.id,
+ worker_id="worker-1",
+ fencing_token=0,
+ lease_seconds=60,
+ )
+
+
+def test_expired_lease_is_requeued_with_new_fencing_token(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ store.create_run(_run())
+ first = store.claim_next(worker_id="worker-1", lease_seconds=1)
+ assert first is not None
+ future = datetime.now(timezone.utc) + timedelta(seconds=2)
+
+ recovered = store.requeue_expired_leases(now=future)
+ second = store.claim_next(worker_id="worker-2", lease_seconds=30, now=future)
+
+ assert recovered == (first.run.id,)
+ assert second is not None
+ assert second.run.id == first.run.id
+ assert second.lease.fencing_token == 2
+ with pytest.raises(ConflictError, match="fencing"):
+ store.assert_fencing_token(
+ first.run.id,
+ worker_id="worker-1",
+ fencing_token=first.lease.fencing_token,
+ )
diff --git a/tests/runtime/test_signals.py b/tests/runtime/test_signals.py
new file mode 100644
index 0000000..8eb280a
--- /dev/null
+++ b/tests/runtime/test_signals.py
@@ -0,0 +1,49 @@
+from __future__ import annotations
+
+from datetime import datetime, timezone
+from uuid import uuid4
+
+from rath.runtime import (
+ GuardedSignalBus,
+ InMemorySignalBus,
+ RunSignal,
+ SignalKind,
+)
+
+
+def test_in_memory_signal_round_trip() -> None:
+ bus = InMemorySignalBus()
+ signal = RunSignal(
+ kind=SignalKind.WAKE,
+ run_id=uuid4(),
+ tenant_id="tenant",
+ created_at=datetime.now(timezone.utc),
+ )
+ bus.publish(signal)
+ assert bus.receive() == signal
+
+
+def test_signal_failure_does_not_change_durable_outcome() -> None:
+ class Broken:
+ def publish(self, signal: RunSignal) -> None:
+ raise ConnectionError("redis down")
+
+ def receive(self, *, timeout_seconds: float = 0) -> RunSignal | None:
+ raise ConnectionError("redis down")
+
+ bus = GuardedSignalBus(Broken())
+ bus.publish(
+ RunSignal(
+ kind=SignalKind.CANCEL,
+ run_id=uuid4(),
+ tenant_id="tenant",
+ created_at=datetime.now(timezone.utc),
+ )
+ )
+ assert bus.receive() is None
+ assert bus.failures == 2
+
+
+def test_in_memory_receive_without_timeout_is_non_blocking() -> None:
+ bus = InMemorySignalBus()
+ assert bus.receive(timeout_seconds=0) is None
diff --git a/tests/runtime/test_sqlite_run_store.py b/tests/runtime/test_sqlite_run_store.py
new file mode 100644
index 0000000..b12cf11
--- /dev/null
+++ b/tests/runtime/test_sqlite_run_store.py
@@ -0,0 +1,220 @@
+from __future__ import annotations
+
+from concurrent.futures import ThreadPoolExecutor
+from datetime import timedelta
+from pathlib import Path
+from uuid import uuid4
+
+import pytest
+
+from rath.runtime import (
+ ApprovalDecision,
+ ApprovalDecisionKind,
+ Checkpoint,
+ ConflictError,
+ Interrupt,
+ InterruptKind,
+ Run,
+ RunStatus,
+ SQLiteRunStore,
+)
+
+
+def _run(*, idempotency_key: str | None = None) -> Run:
+ return Run.create(
+ plan_id=uuid4(),
+ revision_id=uuid4(),
+ session_id=uuid4(),
+ tenant_id="tenant-1",
+ state={"count": 0},
+ next_nodes=("start",),
+ idempotency_key=idempotency_key,
+ )
+
+
+def test_run_survives_store_reopen(tmp_path: Path) -> None:
+ path = tmp_path / "runtime.db"
+ first = SQLiteRunStore(path)
+ created = first.create_run(_run())
+ first.close()
+
+ second = SQLiteRunStore(path)
+ loaded = second.get_run(created.id)
+ second.close()
+
+ assert loaded == created
+ assert loaded.state["count"] == 0
+
+
+def test_transition_is_compare_and_swap_and_appends_event(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ created = store.create_run(_run())
+ running = store.transition_run(
+ created.id,
+ expected_version=0,
+ target=RunStatus.RUNNING,
+ )
+
+ assert running.status is RunStatus.RUNNING
+ assert running.version == 1
+ assert [event.type for event in store.list_run_events(created.id)] == [
+ "run.created",
+ "run.state.changed",
+ ]
+ with pytest.raises(ConflictError):
+ store.transition_run(
+ created.id,
+ expected_version=0,
+ target=RunStatus.FAILED,
+ )
+
+
+def test_idempotency_key_returns_same_run_and_rejects_payload_mismatch(
+ tmp_path: Path,
+) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ original = _run(idempotency_key="request-1")
+ first = store.create_run(original)
+ second = store.create_run(original)
+
+ assert second.id == first.id
+
+ mismatch = Run.create(
+ plan_id=uuid4(),
+ revision_id=original.revision_id,
+ session_id=original.session_id,
+ tenant_id=original.tenant_id,
+ idempotency_key=original.idempotency_key,
+ )
+ with pytest.raises(ConflictError, match="different request"):
+ store.create_run(mismatch)
+
+
+def test_concurrent_idempotent_create_has_single_winner(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ candidate = _run(idempotency_key="same-request")
+ with ThreadPoolExecutor(max_workers=8) as pool:
+ ids = list(pool.map(lambda _: store.create_run(candidate).id, range(16)))
+
+ assert set(ids) == {candidate.id}
+ assert len(store.list_runs(tenant_id="tenant-1")) == 1
+
+
+def test_checkpoints_are_ordered_and_survive_restart(tmp_path: Path) -> None:
+ path = tmp_path / "runtime.db"
+ store = SQLiteRunStore(path)
+ run = store.create_run(_run())
+ checkpoint = Checkpoint.create(
+ run_id=run.id,
+ sequence=1,
+ plan_hash="a" * 64,
+ state={"count": 1},
+ next_nodes=("next",),
+ effect_watermark=0,
+ )
+ store.append_checkpoint(checkpoint)
+ with pytest.raises(ConflictError, match="sequence"):
+ store.append_checkpoint(checkpoint)
+ store.close()
+
+ reopened = SQLiteRunStore(path)
+ loaded = reopened.latest_checkpoint(run.id)
+ assert loaded == checkpoint
+
+
+def test_interrupt_decision_and_waiting_resume_are_atomic(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ queued = store.create_run(_run())
+ running = store.transition_run(
+ queued.id,
+ expected_version=queued.version,
+ target=RunStatus.RUNNING,
+ )
+ interrupt = Interrupt.create(
+ run_id=running.id,
+ kind=InterruptKind.APPROVAL,
+ request={"tool": "email.send"},
+ )
+ waiting = store.create_interrupt(
+ interrupt,
+ expected_run_version=running.version,
+ )
+ assert waiting.status is RunStatus.WAITING
+ assert store.list_interrupts(tenant_id="tenant-1") == (interrupt,)
+ assert store.list_interrupts(tenant_id="other") == ()
+
+ resumed = store.decide_interrupt(
+ interrupt.id,
+ decision=ApprovalDecision(
+ kind=ApprovalDecisionKind.APPROVE,
+ actor_id="user-1",
+ reason="approved",
+ ),
+ expected_run_version=waiting.version,
+ )
+ assert resumed.status is RunStatus.QUEUED
+ decided = store.get_interrupt(interrupt.id)
+ assert decided.decision is not None
+ assert decided.decision.actor_id == "user-1"
+ assert store.list_interrupts(tenant_id="tenant-1") == ()
+ assert store.list_interrupts(tenant_id="tenant-1", pending_only=False) == (decided,)
+ with pytest.raises(ConflictError, match="already decided"):
+ store.decide_interrupt(
+ interrupt.id,
+ decision=ApprovalDecision(
+ kind=ApprovalDecisionKind.REJECT,
+ actor_id="user-2",
+ reason="late",
+ ),
+ expected_run_version=resumed.version,
+ )
+
+
+def test_interrupt_deadline_expires_run_atomically(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ queued = store.create_run(_run())
+ running = store.transition_run(
+ queued.id,
+ expected_version=queued.version,
+ target=RunStatus.RUNNING,
+ )
+ interrupt = Interrupt.create(
+ run_id=running.id,
+ kind=InterruptKind.INPUT,
+ request={"question": "continue?"},
+ timeout_seconds=1,
+ )
+ store.create_interrupt(interrupt, expected_run_version=running.version)
+ assert interrupt.expires_at is not None
+
+ assert store.expire_interrupts(now=interrupt.expires_at + timedelta(seconds=1)) == (
+ interrupt.id,
+ )
+ expired = store.get_interrupt(interrupt.id)
+ assert expired.decision is not None
+ assert expired.decision.kind is ApprovalDecisionKind.REJECT
+ assert store.get_run(running.id).status is RunStatus.TIMED_OUT
+ assert (
+ store.expire_interrupts(now=interrupt.expires_at + timedelta(seconds=2)) == ()
+ )
+
+
+def test_store_pushes_down_run_and_event_cursors(tmp_path: Path) -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ first = store.create_run(_run())
+ second = store.create_run(_run())
+ third = store.create_run(_run())
+
+ page = store.list_runs(tenant_id="tenant-1", limit=2)
+ assert page == (first, second)
+ assert store.list_runs(
+ tenant_id="tenant-1",
+ after=second.id,
+ limit=2,
+ ) == (third,)
+
+ store.append_run_event(first.id, "custom.one", {})
+ store.append_run_event(first.id, "custom.two", {})
+ events = store.list_run_events(first.id, after_sequence=1, limit=1)
+ assert len(events) == 1
+ assert events[0].sequence == 2
diff --git a/tests/security/test_context.py b/tests/security/test_context.py
new file mode 100644
index 0000000..aca9c7e
--- /dev/null
+++ b/tests/security/test_context.py
@@ -0,0 +1,74 @@
+from __future__ import annotations
+
+from datetime import datetime, timedelta, timezone
+from uuid import UUID, uuid4
+
+import pytest
+
+from rath.context import DeadlineExceededError, RunContext, TraceContext
+from rath.security import Principal, PrincipalKind, SecurityContext
+
+
+def test_security_context_is_deeply_immutable() -> None:
+ claims = {"roles": ["developer"], "profile": {"region": "cn"}}
+ principal = Principal(
+ id="user-1",
+ kind=PrincipalKind.USER,
+ claims=claims,
+ )
+ context = SecurityContext(
+ principal=principal,
+ tenant_id="tenant-1",
+ project_id="project-1",
+ grants={"tool.search", "memory.read"},
+ )
+
+ claims["roles"].append("admin")
+ claims["profile"]["region"] = "other" # type: ignore[index]
+
+ assert principal.claims["roles"] == ("developer",)
+ assert principal.claims["profile"]["region"] == "cn" # type: ignore[index]
+ assert context.grants == frozenset({"tool.search", "memory.read"})
+ with pytest.raises(TypeError):
+ principal.claims["new"] = True # type: ignore[index]
+
+
+def test_local_context_is_explicit_and_not_anonymous() -> None:
+ context = SecurityContext.local()
+
+ assert context.tenant_id == "local"
+ assert context.principal.id == "local-process"
+ assert context.principal.kind is PrincipalKind.SYSTEM
+ assert "trusted_host" in context.grants
+
+
+def test_trace_context_uses_w3c_sized_hex_identifiers() -> None:
+ trace = TraceContext.new()
+
+ assert len(trace.trace_id) == 32
+ assert len(trace.span_id) == 16
+ int(trace.trace_id, 16)
+ int(trace.span_id, 16)
+
+
+def test_run_context_rejects_naive_deadline() -> None:
+ with pytest.raises(ValueError, match="timezone-aware"):
+ RunContext(
+ security=SecurityContext.local(),
+ revision_id=uuid4(),
+ deadline=datetime.now(),
+ )
+
+
+def test_run_context_deadline_check_uses_stable_error_code() -> None:
+ context = RunContext(
+ security=SecurityContext.local(),
+ revision_id=uuid4(),
+ deadline=datetime.now(timezone.utc) - timedelta(seconds=1),
+ )
+
+ with pytest.raises(DeadlineExceededError) as raised:
+ context.ensure_active()
+
+ assert raised.value.code.value == "runtime.deadline_exceeded"
+ assert isinstance(context.request_id, UUID)
diff --git a/tests/security/test_policy.py b/tests/security/test_policy.py
new file mode 100644
index 0000000..1615440
--- /dev/null
+++ b/tests/security/test_policy.py
@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+import asyncio
+from dataclasses import replace
+from uuid import uuid4
+
+import pytest
+
+from rath.context import RunContext
+from rath.security import (
+ Action,
+ ApprovalRequiredError,
+ AuthorizationError,
+ DenyAllPolicy,
+ LocalTrustedPolicy,
+ PolicyConstraints,
+ PolicyDecision,
+ PolicyEffect,
+ ResourceRef,
+ authorize,
+)
+
+
+def _context() -> RunContext:
+ return RunContext.local(revision_id=uuid4())
+
+
+def test_deny_all_policy_fails_closed() -> None:
+ async def exercise() -> None:
+ with pytest.raises(AuthorizationError) as raised:
+ await authorize(
+ DenyAllPolicy(),
+ action=Action("tool.execute"),
+ resource=ResourceRef(kind="tool", id="search"),
+ context=_context(),
+ )
+ assert raised.value.code.value == "security.forbidden"
+
+ asyncio.run(exercise())
+
+
+def test_local_trusted_policy_only_allows_explicit_local_context() -> None:
+ async def exercise() -> None:
+ decision = await authorize(
+ LocalTrustedPolicy(),
+ action=Action("sandbox.execute"),
+ resource=ResourceRef(kind="sandbox", id="local"),
+ context=_context(),
+ )
+ assert decision.effect is PolicyEffect.ALLOW
+
+ remote_context = replace(
+ _context(),
+ security=replace(_context().security, tenant_id="tenant-1"),
+ )
+ with pytest.raises(AuthorizationError):
+ await authorize(
+ LocalTrustedPolicy(),
+ action=Action("sandbox.execute"),
+ resource=ResourceRef(kind="sandbox", id="local"),
+ context=remote_context,
+ )
+
+ asyncio.run(exercise())
+
+
+def test_approval_decision_is_not_misreported_as_denial() -> None:
+ class ApprovalPolicy:
+ async def evaluate(
+ self,
+ action: Action,
+ resource: ResourceRef,
+ context: RunContext,
+ ) -> PolicyDecision:
+ return PolicyDecision(
+ effect=PolicyEffect.REQUIRE_APPROVAL,
+ reason="non-idempotent tool",
+ policy_id="test",
+ )
+
+ async def exercise() -> None:
+ with pytest.raises(ApprovalRequiredError) as raised:
+ await authorize(
+ ApprovalPolicy(),
+ action=Action("tool.execute"),
+ resource=ResourceRef(kind="tool", id="email.send"),
+ context=_context(),
+ )
+ assert raised.value.code.value == "security.approval_required"
+
+ asyncio.run(exercise())
+
+
+def test_policy_constraints_validate_resource_budgets() -> None:
+ with pytest.raises(ValueError, match="max_output_bytes"):
+ PolicyConstraints(max_output_bytes=0)
+ with pytest.raises(ValueError, match="timeout_seconds"):
+ PolicyConstraints(timeout_seconds=-1)
diff --git a/tests/security/test_secrets_audit.py b/tests/security/test_secrets_audit.py
new file mode 100644
index 0000000..32ab1f8
--- /dev/null
+++ b/tests/security/test_secrets_audit.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+import asyncio
+import json
+from uuid import uuid4
+
+from rath.context import RunContext
+from rath.security import (
+ Action,
+ AuditEvent,
+ AuditKind,
+ InMemoryAuditSink,
+ PolicyDecision,
+ PolicyEffect,
+ ResolvedSecret,
+ ResourceRef,
+ SecretRef,
+ StructuredAuditSink,
+)
+
+
+def test_resolved_secret_never_exposes_value_in_repr_or_str() -> None:
+ secret = ResolvedSecret(
+ ref=SecretRef(provider="env", key="OPENAI_API_KEY"),
+ value="super-secret-value",
+ )
+
+ assert "super-secret-value" not in repr(secret)
+ assert "super-secret-value" not in str(secret)
+ assert secret.reveal() == "super-secret-value"
+
+
+def test_audit_sink_preserves_security_correlation_without_secret_values() -> None:
+ async def exercise() -> None:
+ context = RunContext.local(revision_id=uuid4())
+ event = AuditEvent.for_policy_decision(
+ kind=AuditKind.POLICY_DECISION,
+ action=Action("provider.invoke"),
+ resource=ResourceRef(kind="provider", id="openai-main"),
+ context=context,
+ decision=PolicyDecision(
+ effect=PolicyEffect.ALLOW,
+ reason="local trusted mode",
+ policy_id="local",
+ ),
+ attributes={"secret_ref": "env:OPENAI_API_KEY"},
+ )
+ sink = InMemoryAuditSink()
+ await sink.emit(event)
+
+ assert sink.events == (event,)
+ assert event.request_id == context.request_id
+ assert event.trace_id == context.trace_context.trace_id
+ assert event.tenant_id == "local"
+
+ asyncio.run(exercise())
+
+
+def test_structured_audit_sink_emits_redacted_correlated_json() -> None:
+ async def exercise() -> None:
+ context = RunContext.local(revision_id=uuid4())
+ event = AuditEvent.for_policy_decision(
+ kind=AuditKind.POLICY_DECISION,
+ action=Action("provider.invoke"),
+ resource=ResourceRef(kind="provider", id="openai-main"),
+ context=context,
+ decision=PolicyDecision(
+ effect=PolicyEffect.ALLOW,
+ reason="approved",
+ policy_id="release-policy",
+ ),
+ attributes={
+ "authorization": "Bearer super-secret-value",
+ "secret_ref": "env:OPENAI_API_KEY",
+ },
+ )
+ lines: list[str] = []
+ await StructuredAuditSink(lines.append).emit(event)
+
+ assert len(lines) == 1
+ assert "super-secret-value" not in lines[0]
+ record = json.loads(lines[0])
+ assert record["schema"] == "openrath.security-audit/1"
+ assert record["request_id"] == str(context.request_id)
+ assert record["trace_id"] == context.trace_context.trace_id
+ assert record["action"] == "provider.invoke"
+ assert record["attributes"]["authorization"] == ""
+
+ asyncio.run(exercise())
diff --git a/tests/server/test_agent_server.py b/tests/server/test_agent_server.py
new file mode 100644
index 0000000..ee306ba
--- /dev/null
+++ b/tests/server/test_agent_server.py
@@ -0,0 +1,363 @@
+from __future__ import annotations
+
+from pathlib import Path
+from uuid import uuid4
+
+import httpx
+
+from rath.adapters import MemoryExecutor
+from rath.definition import EffectClass, step
+from rath.flow import Workflow
+from rath.runtime import InterruptKind, LocalRuntime, RunStatus, SQLiteRunStore
+from rath.security import (
+ InMemoryAuditSink,
+ LocalTrustedPolicy,
+ Principal,
+ PrincipalKind,
+ SecurityContext,
+)
+from rath.server import AgentServer, StaticTokenAuth
+from rath.session import Session
+
+
+class _Echo(Workflow):
+ @step(entry=True, effects=EffectClass.READ_ONLY)
+ def echo(self, state, context): # type: ignore[no-untyped-def]
+ return {**state, "done": True}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+class _Approval(Workflow):
+ @step(entry=True, effects=EffectClass.NON_IDEMPOTENT)
+ def approve(self, state, context): # type: ignore[no-untyped-def]
+ decision = context.interrupt(
+ InterruptKind.APPROVAL,
+ {"tool": "email.send"},
+ )
+ return {"decision": decision.kind.value}
+
+ def forward(self, session: Session) -> Session:
+ return session
+
+
+def test_control_mutation_emits_redacted_audit(tmp_path: Path) -> None:
+ import asyncio
+
+ async def exercise() -> None:
+ store = SQLiteRunStore(tmp_path / "audit.db")
+ runtime = LocalRuntime(store)
+ context = SecurityContext(
+ principal=Principal(id="operator", kind=PrincipalKind.USER),
+ tenant_id="tenant",
+ grants=frozenset({"*"}),
+ )
+ audit = InMemoryAuditSink()
+ server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth({"super-secret-token": context}),
+ audit_sink=audit,
+ )
+ server.register_assistant("echo", _Echo(), revision_id=uuid4())
+ transport = httpx.ASGITransport(app=server.app)
+ headers = {"Authorization": "Bearer super-secret-token"}
+ async with httpx.AsyncClient(
+ transport=transport,
+ base_url="http://test",
+ ) as client:
+ session = await client.post("/v1/sessions", headers=headers)
+ run = await client.post(
+ "/v1/runs",
+ headers=headers,
+ json={
+ "assistant_id": "echo",
+ "session_id": session.json()["id"],
+ },
+ )
+ response = await client.post(
+ f"/v1/runs/{run.json()['id']}/cancel",
+ headers=headers,
+ )
+ assert response.status_code == 200
+
+ assert [event.action for event in audit.events] == ["run.cancel"]
+ assert "super-secret-token" not in repr(audit.events)
+
+ asyncio.run(exercise())
+
+
+def test_server_requires_explicit_action_grants(tmp_path: Path) -> None:
+ import asyncio
+
+ async def exercise() -> None:
+ store = SQLiteRunStore(tmp_path / "authorization.db")
+ runtime = LocalRuntime(store)
+ denied = SecurityContext(
+ principal=Principal(id="user", kind=PrincipalKind.USER),
+ tenant_id="tenant",
+ )
+ reader = SecurityContext(
+ principal=Principal(id="reader", kind=PrincipalKind.USER),
+ tenant_id="tenant",
+ grants=frozenset({"assistant.read"}),
+ )
+ server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth({"denied": denied, "reader": reader}),
+ )
+ server.register_assistant("echo", _Echo(), revision_id=uuid4())
+ transport = httpx.ASGITransport(app=server.app)
+ async with httpx.AsyncClient(
+ transport=transport,
+ base_url="http://test",
+ ) as client:
+ no_grant = await client.get(
+ "/v1/assistants",
+ headers={"Authorization": "Bearer denied"},
+ )
+ assert no_grant.status_code == 403
+ allowed = await client.get(
+ "/v1/assistants",
+ headers={"Authorization": "Bearer reader"},
+ )
+ assert allowed.status_code == 200
+ mutation = await client.post(
+ "/v1/assistants",
+ headers={"Authorization": "Bearer reader"},
+ json={"id": "alias", "template_id": "echo"},
+ )
+ assert mutation.status_code == 403
+
+ asyncio.run(exercise())
+
+
+def test_server_auth_tenant_idempotency_and_sse_sync(tmp_path: Path) -> None:
+ import asyncio
+
+ async def exercise() -> None:
+ store = SQLiteRunStore(tmp_path / "runtime.db")
+ runtime = LocalRuntime(store)
+ tenant = SecurityContext(
+ principal=Principal(id="user-1", kind=PrincipalKind.USER),
+ tenant_id="tenant-1",
+ grants=frozenset({"*"}),
+ )
+ server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth({"token": tenant}),
+ )
+ server.register_assistant("echo", _Echo(), revision_id=uuid4())
+ transport = httpx.ASGITransport(app=server.app)
+ async with httpx.AsyncClient(
+ transport=transport,
+ base_url="http://test",
+ ) as client:
+ assert (await client.get("/v1/assistants")).status_code == 401
+ headers = {
+ "Authorization": "Bearer token",
+ "Idempotency-Key": "req-1",
+ }
+ session = await client.post("/v1/sessions", headers=headers)
+ assert session.status_code == 201
+ body = {
+ "assistant_id": "echo",
+ "session_id": session.json()["id"],
+ "state": {"value": 1},
+ }
+ first = await client.post("/v1/runs", headers=headers, json=body)
+ second = await client.post("/v1/runs", headers=headers, json=body)
+ assert first.status_code == 201
+ assert first.headers["x-request-id"]
+ assert first.json()["request_id"]
+ assert first.json()["trace_id"]
+ assert second.json()["id"] == first.json()["id"]
+ runtime.work_once(worker_id="worker")
+ run_id = first.json()["id"]
+ fetched = await client.get(f"/v1/runs/{run_id}", headers=headers)
+ assert fetched.json()["status"] == "succeeded"
+ stream = await client.get(
+ f"/v1/runs/{run_id}/stream?after=1",
+ headers=headers,
+ )
+ assert stream.status_code == 200
+ assert "run.checkpoint.created" in stream.text
+ assert (await client.get("/health/ready")).status_code == 200
+ openapi = await client.get("/openapi.json")
+ assert openapi.status_code == 200
+ schema = openapi.json()
+ assert schema["paths"]["/v1/runs"]["post"]["operationId"] == "createRun"
+ assert schema["components"]["securitySchemes"]["bearerAuth"]
+ assert all(operations for operations in schema["paths"].values())
+ assert (await client.get("/metrics", headers=headers)).status_code == 200
+
+ session = await client.post("/v1/sessions", headers=headers)
+ assert session.status_code == 201
+ session_id = session.json()["id"]
+ session_run = await client.post(
+ f"/v1/sessions/{session_id}/runs",
+ headers={"Authorization": "Bearer token"},
+ json={"assistant_id": "echo", "state": {"value": 2}},
+ )
+ assert session_run.status_code == 201
+ listed = await client.get("/v1/runs?limit=1", headers=headers)
+ assert len(listed.json()["items"]) == 1
+ assert listed.json()["next"] is not None
+ assistant = await client.get("/v1/assistants/echo", headers=headers)
+ assert assistant.status_code == 200
+ alias = await client.post(
+ "/v1/assistants",
+ headers=headers,
+ json={"id": "tenant-echo", "template_id": "echo"},
+ )
+ assert alias.status_code == 201
+ assert alias.json()["kind"] == "alias"
+ alias_session = await client.post("/v1/sessions", headers=headers)
+ assert alias_session.status_code == 201
+ alias_run = await client.post(
+ "/v1/runs",
+ headers={"Authorization": "Bearer token"},
+ json={
+ "assistant_id": "tenant-echo",
+ "session_id": alias_session.json()["id"],
+ "state": {"value": 3},
+ },
+ )
+ assert alias_run.status_code == 201
+ listed_assistants = await client.get("/v1/assistants", headers=headers)
+ assert {item["id"] for item in listed_assistants.json()["items"]} == {
+ "echo",
+ "tenant-echo",
+ }
+ reconnected = await client.get(
+ f"/v1/runs/{run_id}/stream",
+ headers={**headers, "Last-Event-ID": "1"},
+ )
+ assert "id: 1\n" not in reconnected.text
+ invalid_cursor = await client.get(
+ f"/v1/runs/{run_id}/stream",
+ headers={**headers, "Last-Event-ID": "not-an-integer"},
+ )
+ assert invalid_cursor.status_code == 400
+ feedback = await client.post(
+ "/v1/feedback",
+ headers=headers,
+ json={"run_id": run_id, "key": "quality", "score": 1},
+ )
+ assert feedback.status_code == 201
+ assert feedback.headers["x-content-type-options"] == "nosniff"
+ oversized = await client.post(
+ "/v1/runs",
+ headers={"Authorization": "Bearer token"},
+ content=b"x" * (1024 * 1024 + 1),
+ )
+ assert oversized.status_code == 400
+
+ asyncio.run(exercise())
+
+
+def test_store_api_is_policy_governed_and_tenant_scoped(tmp_path: Path) -> None:
+ import asyncio
+
+ async def exercise() -> None:
+ store = SQLiteRunStore(tmp_path / "store-api.db")
+ runtime = LocalRuntime(store)
+ local = SecurityContext.local(grants=("*", "trusted_host"))
+ calls: list[tuple[str, str, dict[str, object]]] = []
+
+ def memory_handler(operation, namespace, payload, context): # type: ignore[no-untyped-def]
+ calls.append((operation, namespace.tenant_id, dict(payload)))
+ return {"operation": operation, "tenant_id": namespace.tenant_id}
+
+ server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth({"token": local}),
+ memory_executor=MemoryExecutor(LocalTrustedPolicy()),
+ memory_handler=memory_handler,
+ )
+ transport = httpx.ASGITransport(app=server.app)
+ async with httpx.AsyncClient(
+ transport=transport,
+ base_url="http://test",
+ ) as client:
+ headers = {"Authorization": "Bearer token"}
+ response = await client.post(
+ "/v1/store/search",
+ headers=headers,
+ json={"payload": {"query": "safe"}},
+ )
+ assert response.status_code == 200
+ assert response.json()["result"]["tenant_id"] == "local"
+ denied = await client.post(
+ "/v1/store/search",
+ headers=headers,
+ json={"tenant_id": "other", "payload": {"query": "unsafe"}},
+ )
+ assert denied.status_code == 403
+ assert calls == [("search", "local", {"query": "safe"})]
+
+ asyncio.run(exercise())
+
+
+def test_server_interrupt_inbox_and_decision_resume(tmp_path: Path) -> None:
+ import asyncio
+
+ async def exercise() -> None:
+ store = SQLiteRunStore(tmp_path / "interrupt-api.db")
+ runtime = LocalRuntime(store)
+ tenant = SecurityContext(
+ principal=Principal(id="reviewer", kind=PrincipalKind.USER),
+ tenant_id="tenant",
+ grants=frozenset({"*"}),
+ )
+ server = AgentServer(
+ store,
+ runtime,
+ auth=StaticTokenAuth({"token": tenant}),
+ )
+ server.register_assistant(
+ "approval",
+ _Approval(),
+ revision_id=uuid4(),
+ )
+ transport = httpx.ASGITransport(app=server.app)
+ async with httpx.AsyncClient(
+ transport=transport,
+ base_url="http://test",
+ ) as client:
+ headers = {"Authorization": "Bearer token"}
+ session = await client.post("/v1/sessions", headers=headers)
+ assert session.status_code == 201
+ created = await client.post(
+ "/v1/runs",
+ headers=headers,
+ json={
+ "assistant_id": "approval",
+ "session_id": session.json()["id"],
+ },
+ )
+ assert created.status_code == 201
+ waiting = runtime.work_once(worker_id="worker-1")
+ assert waiting is not None and waiting.status is RunStatus.WAITING
+ inbox = await client.get("/v1/interrupts", headers=headers)
+ assert inbox.status_code == 200
+ (interrupt,) = inbox.json()["items"]
+ decided = await client.post(
+ f"/v1/interrupts/{interrupt['id']}/decision",
+ headers=headers,
+ json={
+ "kind": "approve",
+ "reason": "expected test operation",
+ },
+ )
+ assert decided.status_code == 200
+ completed = runtime.work_once(worker_id="worker-2")
+ assert completed is not None
+ assert completed.status is RunStatus.SUCCEEDED
+ assert completed.state["decision"] == "approve"
+
+ asyncio.run(exercise())
diff --git a/tests/server/test_openapi_contract.py b/tests/server/test_openapi_contract.py
new file mode 100644
index 0000000..11d52af
--- /dev/null
+++ b/tests/server/test_openapi_contract.py
@@ -0,0 +1,30 @@
+from __future__ import annotations
+
+import json
+from pathlib import Path
+
+from rath.server.app import _openapi_document
+
+
+def test_committed_openapi_matches_generator() -> None:
+ committed = json.loads(
+ Path("deploy/docs/openapi-v2.json").read_text(encoding="utf-8")
+ )
+ assert committed == _openapi_document(
+ "2.0.0rc1",
+ store_enabled=True,
+ )
+
+
+def test_openapi_documents_security_actions_and_schemas() -> None:
+ document = _openapi_document("2.0.0rc1", store_enabled=True)
+ paths = document["paths"]
+ assert paths["/v1/runs"]["post"]["x-openrath-action"] == "run.create"
+ assert paths["/metrics"]["get"]["security"] == [{"bearerAuth": []}]
+ assert (
+ paths["/v1/runs"]["post"]["requestBody"]["content"]["application/json"][
+ "schema"
+ ]["$ref"]
+ == "#/components/schemas/CreateRunRequest"
+ )
+ assert document["components"]["schemas"]["Run"]["required"]
diff --git a/tests/session/persistence/test_loader_gc.py b/tests/session/persistence/test_loader_gc.py
index d906381..baa55f8 100644
--- a/tests/session/persistence/test_loader_gc.py
+++ b/tests/session/persistence/test_loader_gc.py
@@ -33,6 +33,7 @@
load_session,
prune_sessions,
session_file,
+ session_partial_file,
)
from rath.session.session import Session
@@ -213,6 +214,17 @@ def test_session_file_path_under_resolved_dir(_isolate_openrath_home: Path) -> N
assert str(expected).endswith(f"{sid}.jsonl")
+@pytest.mark.parametrize("bad_id", ["../escape", "/tmp/escape", "not-a-uuid"])
+def test_session_paths_reject_path_like_ids(
+ _isolate_openrath_home: Path,
+ bad_id: str,
+) -> None:
+ with pytest.raises(ValueError, match="session_id must be a UUID"):
+ session_file(bad_id)
+ with pytest.raises(ValueError, match="session_id must be a UUID"):
+ session_partial_file(bad_id)
+
+
# ---------------------------------------------------------------------------
# GC: delete + prune
# ---------------------------------------------------------------------------
diff --git a/tests/session/test_arun_session_loop.py b/tests/session/test_arun_session_loop.py
index e352061..423a5d5 100644
--- a/tests/session/test_arun_session_loop.py
+++ b/tests/session/test_arun_session_loop.py
@@ -21,7 +21,7 @@
from rath._async.aloop import _arun_session_loop
from rath._async.runtime import runtime
-from rath.backend import get
+from rath.backend import BackendSandboxSpec, get
from rath.flow.agent_param import AgentParam, Provider
from rath.flow.tool import FlowToolCall
from rath.llm import (
@@ -147,7 +147,7 @@ def test_arun_session_loop_stop_without_tools() -> None:
def test_arun_session_loop_write_file_via_tool_then_stop(tmp_path: Any) -> None:
body = {
- "path": str(tmp_path / "_arun_probe.txt"),
+ "path": "_arun_probe.txt",
"content": "ASYNC_LOOP_MARKER",
}
first = _tool_round(
@@ -160,7 +160,7 @@ def test_arun_session_loop_write_file_via_tool_then_stop(tmp_path: Any) -> None:
agent = AgentParam(Session.from_agent_prompt("scripted assistant"), Provider())
backend = get("local")
- with backend.open() as sandbox:
+ with backend.open(BackendSandboxSpec(working_dir=str(tmp_path))) as sandbox:
user = Session.from_user_message("Please write the file.").bind_sandbox(sandbox)
out = runtime().run(
_arun_session_loop(
@@ -181,6 +181,8 @@ def test_arun_session_loop_write_file_via_tool_then_stop(tmp_path: Any) -> None:
def test_arun_session_loop_parallel_safe_tools_overlap(tmp_path: Any) -> None:
"""Three writes on distinct paths run concurrently."""
n = 3
+ in_flight = 0
+ max_in_flight = 0
paths = [str(tmp_path / f"par_{i}.txt") for i in range(n)]
parts = tuple(
_tool_call(
@@ -193,6 +195,10 @@ def test_arun_session_loop_parallel_safe_tools_overlap(tmp_path: Any) -> None:
# Sleeping tool to make parallelism observable. resource_key returns the
# path so distinct paths land on distinct queues.
+ import threading
+
+ counter_lock = threading.Lock()
+
class _SleepyWrite(FlowToolCall):
parallel_safe = True
@@ -215,9 +221,17 @@ def parameters(self) -> Mapping[str, Any]:
}
def __call__(self, session: Session, arguments: Mapping[str, Any]) -> Any:
- time.sleep(0.25)
- with open(arguments["path"], "w", encoding="utf-8") as fp:
- fp.write(str(arguments["content"]))
+ nonlocal in_flight, max_in_flight
+ with counter_lock:
+ in_flight += 1
+ max_in_flight = max(max_in_flight, in_flight)
+ try:
+ time.sleep(0.25)
+ with open(arguments["path"], "w", encoding="utf-8") as fp:
+ fp.write(str(arguments["content"]))
+ finally:
+ with counter_lock:
+ in_flight -= 1
return True
executor = _ScriptedAsyncExecutor([_tool_round(*parts, rid="r-par"), _stop("done")])
@@ -225,7 +239,6 @@ def __call__(self, session: Session, arguments: Mapping[str, Any]) -> Any:
backend = get("local")
with backend.open() as sandbox:
user = Session.from_user_message("write three").bind_sandbox(sandbox)
- t0 = time.perf_counter()
out = runtime().run(
_arun_session_loop(
user,
@@ -235,12 +248,12 @@ def __call__(self, session: Session, arguments: Mapping[str, Any]) -> Any:
tools=[_SleepyWrite()],
)
)
- elapsed = time.perf_counter() - t0
for p in paths:
assert open(p, encoding="utf-8").read().startswith("slot-")
- # 3 × 0.25s serial would be 0.75s; parallel must finish well under that.
- assert elapsed < 0.5, f"parallel-safe tools did not overlap; elapsed={elapsed:.3f}s"
+ assert max_in_flight >= 2, (
+ f"parallel-safe tools did not overlap; max_in_flight={max_in_flight}"
+ )
# Transcript order must remain the call order.
tool_rows = [r for r in out.chunk_table.rows if r.kind == ChunkKind.TOOL_RESULT]
assert [r.payload.get("tool_call_id") for r in tool_rows] == [
diff --git a/tests/unit/test_errors_v2.py b/tests/unit/test_errors_v2.py
new file mode 100644
index 0000000..3dc6272
--- /dev/null
+++ b/tests/unit/test_errors_v2.py
@@ -0,0 +1,27 @@
+from __future__ import annotations
+
+from rath.errors import ErrorCode, RathError
+
+
+def test_rath_error_has_stable_machine_contract() -> None:
+ error = RathError(
+ ErrorCode.INVALID_ARGUMENT,
+ "invalid input",
+ retryable=False,
+ details={"field": "name"},
+ )
+
+ assert error.to_dict() == {
+ "code": "request.invalid_argument",
+ "message": "invalid input",
+ "retryable": False,
+ "details": {"field": "name"},
+ }
+
+
+def test_error_details_are_immutable_copies() -> None:
+ details = {"nested": {"value": 1}}
+ error = RathError(ErrorCode.INTERNAL, "internal", details=details)
+ details["nested"]["value"] = 2
+
+ assert error.details["nested"]["value"] == 1 # type: ignore[index]
diff --git a/uv.lock b/uv.lock
index 9b5accb..a133e5c 100644
--- a/uv.lock
+++ b/uv.lock
@@ -31,7 +31,7 @@ wheels = [
[[package]]
name = "aiohttp"
-version = "3.13.5"
+version = "3.14.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohappyeyeballs" },
@@ -41,78 +41,88 @@ dependencies = [
{ name = "frozenlist" },
{ name = "multidict" },
{ name = "propcache" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
{ name = "yarl" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/bd/85/cebc47ee74d8b408749073a1a46c6fcba13d170dc8af7e61996c6c9394ac/aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b", size = 750547, upload-time = "2026-03-31T21:56:30.024Z" },
- { url = "https://files.pythonhosted.org/packages/05/98/afd308e35b9d3d8c9ec54c0918f1d722c86dc17ddfec272fcdbcce5a3124/aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5", size = 503535, upload-time = "2026-03-31T21:56:31.935Z" },
- { url = "https://files.pythonhosted.org/packages/6f/4d/926c183e06b09d5270a309eb50fbde7b09782bfd305dec1e800f329834fb/aiohttp-3.13.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f546a4dc1e6a5edbb9fd1fd6ad18134550e096a5a43f4ad74acfbd834fc6670", size = 497830, upload-time = "2026-03-31T21:56:33.654Z" },
- { url = "https://files.pythonhosted.org/packages/e4/d6/f47d1c690f115a5c2a5e8938cce4a232a5be9aac5c5fb2647efcbbbda333/aiohttp-3.13.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c86969d012e51b8e415a8c6ce96f7857d6a87d6207303ab02d5d11ef0cad2274", size = 1682474, upload-time = "2026-03-31T21:56:35.513Z" },
- { url = "https://files.pythonhosted.org/packages/01/44/056fd37b1bb52eac760303e5196acc74d9d546631b035704ae5927f7b4ac/aiohttp-3.13.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b6f6cd1560c5fa427e3b6074bb24d2c64e225afbb7165008903bd42e4e33e28a", size = 1655259, upload-time = "2026-03-31T21:56:37.843Z" },
- { url = "https://files.pythonhosted.org/packages/91/9f/78eb1a20c1c28ae02f6a3c0f4d7b0dcc66abce5290cadd53d78ce3084175/aiohttp-3.13.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:636bc362f0c5bbc7372bc3ae49737f9e3030dbce469f0f422c8f38079780363d", size = 1736204, upload-time = "2026-03-31T21:56:39.822Z" },
- { url = "https://files.pythonhosted.org/packages/de/6c/d20d7de23f0b52b8c1d9e2033b2db1ac4dacbb470bb74c56de0f5f86bb4f/aiohttp-3.13.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a7cbeb06d1070f1d14895eeeed4dac5913b22d7b456f2eb969f11f4b3993796", size = 1826198, upload-time = "2026-03-31T21:56:41.378Z" },
- { url = "https://files.pythonhosted.org/packages/2f/86/a6f3ff1fd795f49545a7c74b2c92f62729135d73e7e4055bf74da5a26c82/aiohttp-3.13.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca9ef7517fd7874a1a08970ae88f497bf5c984610caa0bf40bd7e8450852b95", size = 1681329, upload-time = "2026-03-31T21:56:43.374Z" },
- { url = "https://files.pythonhosted.org/packages/fb/68/84cd3dab6b7b4f3e6fe9459a961acb142aaab846417f6e8905110d7027e5/aiohttp-3.13.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:019a67772e034a0e6b9b17c13d0a8fe56ad9fb150fc724b7f3ffd3724288d9e5", size = 1560023, upload-time = "2026-03-31T21:56:45.031Z" },
- { url = "https://files.pythonhosted.org/packages/41/2c/db61b64b0249e30f954a65ab4cb4970ced57544b1de2e3c98ee5dc24165f/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f34ecee82858e41dd217734f0c41a532bd066bcaab636ad830f03a30b2a96f2a", size = 1652372, upload-time = "2026-03-31T21:56:47.075Z" },
- { url = "https://files.pythonhosted.org/packages/25/6f/e96988a6c982d047810c772e28c43c64c300c943b0ed5c1c0c4ce1e1027c/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4eac02d9af4813ee289cd63a361576da36dba57f5a1ab36377bc2600db0cbb73", size = 1662031, upload-time = "2026-03-31T21:56:48.835Z" },
- { url = "https://files.pythonhosted.org/packages/b7/26/a56feace81f3d347b4052403a9d03754a0ab23f7940780dada0849a38c92/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4beac52e9fe46d6abf98b0176a88154b742e878fdf209d2248e99fcdf73cd297", size = 1708118, upload-time = "2026-03-31T21:56:50.833Z" },
- { url = "https://files.pythonhosted.org/packages/78/6e/b6173a8ff03d01d5e1a694bc06764b5dad1df2d4ed8f0ceec12bb3277936/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c180f480207a9b2475f2b8d8bd7204e47aec952d084b2a2be58a782ffcf96074", size = 1548667, upload-time = "2026-03-31T21:56:52.81Z" },
- { url = "https://files.pythonhosted.org/packages/16/13/13296ffe2c132d888b3fe2c195c8b9c0c24c89c3fa5cc2c44464dc23b22e/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2837fb92951564d6339cedae4a7231692aa9f73cbc4fb2e04263b96844e03b4e", size = 1724490, upload-time = "2026-03-31T21:56:54.541Z" },
- { url = "https://files.pythonhosted.org/packages/7a/b4/1f1c287f4a79782ef36e5a6e62954c85343bc30470d862d30bd5f26c9fa2/aiohttp-3.13.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9010032a0b9710f58012a1e9c222528763d860ba2ee1422c03473eab47703e7", size = 1667109, upload-time = "2026-03-31T21:56:56.21Z" },
- { url = "https://files.pythonhosted.org/packages/ef/42/8461a2aaf60a8f4ea4549a4056be36b904b0eb03d97ca9a8a2604681a500/aiohttp-3.13.5-cp310-cp310-win32.whl", hash = "sha256:7c4b6668b2b2b9027f209ddf647f2a4407784b5d88b8be4efcc72036f365baf9", size = 439478, upload-time = "2026-03-31T21:56:58.292Z" },
- { url = "https://files.pythonhosted.org/packages/e5/71/06956304cb5ee439dfe8d86e1b2e70088bd88ed1ced1f42fb29e5d855f0e/aiohttp-3.13.5-cp310-cp310-win_amd64.whl", hash = "sha256:cd3db5927bf9167d5a6157ddb2f036f6b6b0ad001ac82355d43e97a4bde76d76", size = 462047, upload-time = "2026-03-31T21:57:00.257Z" },
- { url = "https://files.pythonhosted.org/packages/d6/f5/a20c4ac64aeaef1679e25c9983573618ff765d7aa829fa2b84ae7573169e/aiohttp-3.13.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ab7229b6f9b5c1ba4910d6c41a9eb11f543eadb3f384df1b4c293f4e73d44d6", size = 757513, upload-time = "2026-03-31T21:57:02.146Z" },
- { url = "https://files.pythonhosted.org/packages/75/0a/39fa6c6b179b53fcb3e4b3d2b6d6cad0180854eda17060c7218540102bef/aiohttp-3.13.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f14c50708bb156b3a3ca7230b3d820199d56a48e3af76fa21c2d6087190fe3d", size = 506748, upload-time = "2026-03-31T21:57:04.275Z" },
- { url = "https://files.pythonhosted.org/packages/87/ec/e38ce072e724fd7add6243613f8d1810da084f54175353d25ccf9f9c7e5a/aiohttp-3.13.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7d2f8616f0ff60bd332022279011776c3ac0faa0f1b463f7bb12326fbc97a1c", size = 501673, upload-time = "2026-03-31T21:57:06.208Z" },
- { url = "https://files.pythonhosted.org/packages/ba/ba/3bc7525d7e2beaa11b309a70d48b0d3cfc3c2089ec6a7d0820d59c657053/aiohttp-3.13.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2567b72e1ffc3ab25510db43f355b29eeada56c0a622e58dcdb19530eb0a3cb", size = 1763757, upload-time = "2026-03-31T21:57:07.882Z" },
- { url = "https://files.pythonhosted.org/packages/5e/ab/e87744cf18f1bd78263aba24924d4953b41086bd3a31d22452378e9028a0/aiohttp-3.13.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fb0540c854ac9c0c5ad495908fdfd3e332d553ec731698c0e29b1877ba0d2ec6", size = 1720152, upload-time = "2026-03-31T21:57:09.946Z" },
- { url = "https://files.pythonhosted.org/packages/6b/f3/ed17a6f2d742af17b50bae2d152315ed1b164b07a5fd5cc1754d99e4dfa5/aiohttp-3.13.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9883051c6972f58bfc4ebb2116345ee2aa151178e99c3f2b2bbe2af712abd13", size = 1818010, upload-time = "2026-03-31T21:57:12.157Z" },
- { url = "https://files.pythonhosted.org/packages/53/06/ecbc63dc937192e2a5cb46df4d3edb21deb8225535818802f210a6ea5816/aiohttp-3.13.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2294172ce08a82fb7c7273485895de1fa1186cc8294cfeb6aef4af42ad261174", size = 1907251, upload-time = "2026-03-31T21:57:14.023Z" },
- { url = "https://files.pythonhosted.org/packages/7e/a5/0521aa32c1ddf3aa1e71dcc466be0b7db2771907a13f18cddaa45967d97b/aiohttp-3.13.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a807cabd5115fb55af198b98178997a5e0e57dead43eb74a93d9c07d6d4a7dc", size = 1759969, upload-time = "2026-03-31T21:57:16.146Z" },
- { url = "https://files.pythonhosted.org/packages/f6/78/a38f8c9105199dd3b9706745865a8a59d0041b6be0ca0cc4b2ccf1bab374/aiohttp-3.13.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6d0d932e0f39c02b80744273cd5c388a2d9bc07760a03164f229c8e02662f6", size = 1616871, upload-time = "2026-03-31T21:57:17.856Z" },
- { url = "https://files.pythonhosted.org/packages/6f/41/27392a61ead8ab38072105c71aa44ff891e71653fe53d576a7067da2b4e8/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60869c7ac4aaabe7110f26499f3e6e5696eae98144735b12a9c3d9eae2b51a49", size = 1739844, upload-time = "2026-03-31T21:57:19.679Z" },
- { url = "https://files.pythonhosted.org/packages/6e/55/5564e7ae26d94f3214250009a0b1c65a0c6af4bf88924ccb6fdab901de28/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:26d2f8546f1dfa75efa50c3488215a903c0168d253b75fba4210f57ab77a0fb8", size = 1731969, upload-time = "2026-03-31T21:57:22.006Z" },
- { url = "https://files.pythonhosted.org/packages/6d/c5/705a3929149865fc941bcbdd1047b238e4a72bcb215a9b16b9d7a2e8d992/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1162a1492032c82f14271e831c8f4b49f2b6078f4f5fc74de2c912fa225d51d", size = 1795193, upload-time = "2026-03-31T21:57:24.256Z" },
- { url = "https://files.pythonhosted.org/packages/a6/19/edabed62f718d02cff7231ca0db4ef1c72504235bc467f7b67adb1679f48/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8b14eb3262fad0dc2f89c1a43b13727e709504972186ff6a99a3ecaa77102b6c", size = 1606477, upload-time = "2026-03-31T21:57:26.364Z" },
- { url = "https://files.pythonhosted.org/packages/de/fc/76f80ef008675637d88d0b21584596dc27410a990b0918cb1e5776545b5b/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ca9ac61ac6db4eb6c2a0cd1d0f7e1357647b638ccc92f7e9d8d133e71ed3c6ac", size = 1813198, upload-time = "2026-03-31T21:57:28.316Z" },
- { url = "https://files.pythonhosted.org/packages/e5/67/5b3ac26b80adb20ea541c487f73730dc8fa107d632c998f25bbbab98fcda/aiohttp-3.13.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7996023b2ed59489ae4762256c8516df9820f751cf2c5da8ed2fb20ee50abab3", size = 1752321, upload-time = "2026-03-31T21:57:30.549Z" },
- { url = "https://files.pythonhosted.org/packages/88/06/e4a2e49255ea23fa4feeb5ab092d90240d927c15e47b5b5c48dff5a9ce29/aiohttp-3.13.5-cp311-cp311-win32.whl", hash = "sha256:77dfa48c9f8013271011e51c00f8ada19851f013cde2c48fca1ba5e0caf5bb06", size = 439069, upload-time = "2026-03-31T21:57:32.388Z" },
- { url = "https://files.pythonhosted.org/packages/c0/43/8c7163a596dab4f8be12c190cf467a1e07e4734cf90eebb39f7f5d53fc6a/aiohttp-3.13.5-cp311-cp311-win_amd64.whl", hash = "sha256:d3a4834f221061624b8887090637db9ad4f61752001eae37d56c52fddade2dc8", size = 462859, upload-time = "2026-03-31T21:57:34.455Z" },
- { url = "https://files.pythonhosted.org/packages/be/6f/353954c29e7dcce7cf00280a02c75f30e133c00793c7a2ed3776d7b2f426/aiohttp-3.13.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:023ecba036ddd840b0b19bf195bfae970083fd7024ce1ac22e9bba90464620e9", size = 748876, upload-time = "2026-03-31T21:57:36.319Z" },
- { url = "https://files.pythonhosted.org/packages/f5/1b/428a7c64687b3b2e9cd293186695affc0e1e54a445d0361743b231f11066/aiohttp-3.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15c933ad7920b7d9a20de151efcd05a6e38302cbf0e10c9b2acb9a42210a2416", size = 499557, upload-time = "2026-03-31T21:57:38.236Z" },
- { url = "https://files.pythonhosted.org/packages/29/47/7be41556bfbb6917069d6a6634bb7dd5e163ba445b783a90d40f5ac7e3a7/aiohttp-3.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab2899f9fa2f9f741896ebb6fa07c4c883bfa5c7f2ddd8cf2aafa86fa981b2d2", size = 500258, upload-time = "2026-03-31T21:57:39.923Z" },
- { url = "https://files.pythonhosted.org/packages/67/84/c9ecc5828cb0b3695856c07c0a6817a99d51e2473400f705275a2b3d9239/aiohttp-3.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60eaa2d440cd4707696b52e40ed3e2b0f73f65be07fd0ef23b6b539c9c0b0b4", size = 1749199, upload-time = "2026-03-31T21:57:41.938Z" },
- { url = "https://files.pythonhosted.org/packages/f0/d3/3c6d610e66b495657622edb6ae7c7fd31b2e9086b4ec50b47897ad6042a9/aiohttp-3.13.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55b3bdd3292283295774ab585160c4004f4f2f203946997f49aac032c84649e9", size = 1721013, upload-time = "2026-03-31T21:57:43.904Z" },
- { url = "https://files.pythonhosted.org/packages/49/a0/24409c12217456df0bae7babe3b014e460b0b38a8e60753d6cb339f6556d/aiohttp-3.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2b2355dc094e5f7d45a7bb262fe7207aa0460b37a0d87027dcf21b5d890e7d5", size = 1781501, upload-time = "2026-03-31T21:57:46.285Z" },
- { url = "https://files.pythonhosted.org/packages/98/9d/b65ec649adc5bccc008b0957a9a9c691070aeac4e41cea18559fef49958b/aiohttp-3.13.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b38765950832f7d728297689ad78f5f2cf79ff82487131c4d26fe6ceecdc5f8e", size = 1878981, upload-time = "2026-03-31T21:57:48.734Z" },
- { url = "https://files.pythonhosted.org/packages/57/d8/8d44036d7eb7b6a8ec4c5494ea0c8c8b94fbc0ed3991c1a7adf230df03bf/aiohttp-3.13.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b18f31b80d5a33661e08c89e202edabf1986e9b49c42b4504371daeaa11b47c1", size = 1767934, upload-time = "2026-03-31T21:57:51.171Z" },
- { url = "https://files.pythonhosted.org/packages/31/04/d3f8211f273356f158e3464e9e45484d3fb8c4ce5eb2f6fe9405c3273983/aiohttp-3.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:33add2463dde55c4f2d9635c6ab33ce154e5ecf322bd26d09af95c5f81cfa286", size = 1566671, upload-time = "2026-03-31T21:57:53.326Z" },
- { url = "https://files.pythonhosted.org/packages/41/db/073e4ebe00b78e2dfcacff734291651729a62953b48933d765dc513bf798/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:327cc432fdf1356fb4fbc6fe833ad4e9f6aacb71a8acaa5f1855e4b25910e4a9", size = 1705219, upload-time = "2026-03-31T21:57:55.385Z" },
- { url = "https://files.pythonhosted.org/packages/48/45/7dfba71a2f9fd97b15c95c06819de7eb38113d2cdb6319669195a7d64270/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7c35b0bf0b48a70b4cb4fc5d7bed9b932532728e124874355de1a0af8ec4bc88", size = 1743049, upload-time = "2026-03-31T21:57:57.341Z" },
- { url = "https://files.pythonhosted.org/packages/18/71/901db0061e0f717d226386a7f471bb59b19566f2cae5f0d93874b017271f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:df23d57718f24badef8656c49743e11a89fd6f5358fa8a7b96e728fda2abf7d3", size = 1749557, upload-time = "2026-03-31T21:57:59.626Z" },
- { url = "https://files.pythonhosted.org/packages/08/d5/41eebd16066e59cd43728fe74bce953d7402f2b4ddfdfef2c0e9f17ca274/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:02e048037a6501a5ec1f6fc9736135aec6eb8a004ce48838cb951c515f32c80b", size = 1558931, upload-time = "2026-03-31T21:58:01.972Z" },
- { url = "https://files.pythonhosted.org/packages/30/e6/4a799798bf05740e66c3a1161079bda7a3dd8e22ca392481d7a7f9af82a6/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31cebae8b26f8a615d2b546fee45d5ffb76852ae6450e2a03f42c9102260d6fe", size = 1774125, upload-time = "2026-03-31T21:58:04.007Z" },
- { url = "https://files.pythonhosted.org/packages/84/63/7749337c90f92bc2cb18f9560d67aa6258c7060d1397d21529b8004fcf6f/aiohttp-3.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:888e78eb5ca55a615d285c3c09a7a91b42e9dd6fc699b166ebd5dee87c9ccf14", size = 1732427, upload-time = "2026-03-31T21:58:06.337Z" },
- { url = "https://files.pythonhosted.org/packages/98/de/cf2f44ff98d307e72fb97d5f5bbae3bfcb442f0ea9790c0bf5c5c2331404/aiohttp-3.13.5-cp312-cp312-win32.whl", hash = "sha256:8bd3ec6376e68a41f9f95f5ed170e2fcf22d4eb27a1f8cb361d0508f6e0557f3", size = 433534, upload-time = "2026-03-31T21:58:08.712Z" },
- { url = "https://files.pythonhosted.org/packages/aa/ca/eadf6f9c8fa5e31d40993e3db153fb5ed0b11008ad5d9de98a95045bed84/aiohttp-3.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:110e448e02c729bcebb18c60b9214a87ba33bac4a9fa5e9a5f139938b56c6cb1", size = 460446, upload-time = "2026-03-31T21:58:10.945Z" },
- { url = "https://files.pythonhosted.org/packages/78/e9/d76bf503005709e390122d34e15256b88f7008e246c4bdbe915cd4f1adce/aiohttp-3.13.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5029cc80718bbd545123cd8fe5d15025eccaaaace5d0eeec6bd556ad6163d61", size = 742930, upload-time = "2026-03-31T21:58:13.155Z" },
- { url = "https://files.pythonhosted.org/packages/57/00/4b7b70223deaebd9bb85984d01a764b0d7bd6526fcdc73cca83bcbe7243e/aiohttp-3.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4bb6bf5811620003614076bdc807ef3b5e38244f9d25ca5fe888eaccea2a9832", size = 496927, upload-time = "2026-03-31T21:58:15.073Z" },
- { url = "https://files.pythonhosted.org/packages/9c/f5/0fb20fb49f8efdcdce6cd8127604ad2c503e754a8f139f5e02b01626523f/aiohttp-3.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a84792f8631bf5a94e52d9cc881c0b824ab42717165a5579c760b830d9392ac9", size = 497141, upload-time = "2026-03-31T21:58:17.009Z" },
- { url = "https://files.pythonhosted.org/packages/3b/86/b7c870053e36a94e8951b803cb5b909bfbc9b90ca941527f5fcafbf6b0fa/aiohttp-3.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:57653eac22c6a4c13eb22ecf4d673d64a12f266e72785ab1c8b8e5940d0e8090", size = 1732476, upload-time = "2026-03-31T21:58:18.925Z" },
- { url = "https://files.pythonhosted.org/packages/b5/e5/4e161f84f98d80c03a238671b4136e6530453d65262867d989bbe78244d0/aiohttp-3.13.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5e5f7debc7a57af53fdf5c5009f9391d9f4c12867049d509bf7bb164a6e295b", size = 1706507, upload-time = "2026-03-31T21:58:21.094Z" },
- { url = "https://files.pythonhosted.org/packages/d4/56/ea11a9f01518bd5a2a2fcee869d248c4b8a0cfa0bb13401574fa31adf4d4/aiohttp-3.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c719f65bebcdf6716f10e9eff80d27567f7892d8988c06de12bbbd39307c6e3a", size = 1773465, upload-time = "2026-03-31T21:58:23.159Z" },
- { url = "https://files.pythonhosted.org/packages/eb/40/333ca27fb74b0383f17c90570c748f7582501507307350a79d9f9f3c6eb1/aiohttp-3.13.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d97f93fdae594d886c5a866636397e2bcab146fd7a132fd6bb9ce182224452f8", size = 1873523, upload-time = "2026-03-31T21:58:25.59Z" },
- { url = "https://files.pythonhosted.org/packages/f0/d2/e2f77eef1acb7111405433c707dc735e63f67a56e176e72e9e7a2cd3f493/aiohttp-3.13.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df334e39d4c2f899a914f1dba283c1aadc311790733f705182998c6f7cae665", size = 1754113, upload-time = "2026-03-31T21:58:27.624Z" },
- { url = "https://files.pythonhosted.org/packages/fb/56/3f653d7f53c89669301ec9e42c95233e2a0c0a6dd051269e6e678db4fdb0/aiohttp-3.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe6970addfea9e5e081401bcbadf865d2b6da045472f58af08427e108d618540", size = 1562351, upload-time = "2026-03-31T21:58:29.918Z" },
- { url = "https://files.pythonhosted.org/packages/ec/a6/9b3e91eb8ae791cce4ee736da02211c85c6f835f1bdfac0594a8a3b7018c/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7becdf835feff2f4f335d7477f121af787e3504b48b449ff737afb35869ba7bb", size = 1693205, upload-time = "2026-03-31T21:58:32.214Z" },
- { url = "https://files.pythonhosted.org/packages/98/fc/bfb437a99a2fcebd6b6eaec609571954de2ed424f01c352f4b5504371dd3/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:676e5651705ad5d8a70aeb8eb6936c436d8ebbd56e63436cb7dd9bb36d2a9a46", size = 1730618, upload-time = "2026-03-31T21:58:34.728Z" },
- { url = "https://files.pythonhosted.org/packages/e4/b6/c8534862126191a034f68153194c389addc285a0f1347d85096d349bbc15/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9b16c653d38eb1a611cc898c41e76859ca27f119d25b53c12875fd0474ae31a8", size = 1745185, upload-time = "2026-03-31T21:58:36.909Z" },
- { url = "https://files.pythonhosted.org/packages/0b/93/4ca8ee2ef5236e2707e0fd5fecb10ce214aee1ff4ab307af9c558bda3b37/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:999802d5fa0389f58decd24b537c54aa63c01c3219ce17d1214cbda3c2b22d2d", size = 1557311, upload-time = "2026-03-31T21:58:39.38Z" },
- { url = "https://files.pythonhosted.org/packages/57/ae/76177b15f18c5f5d094f19901d284025db28eccc5ae374d1d254181d33f4/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec707059ee75732b1ba130ed5f9580fe10ff75180c812bc267ded039db5128c6", size = 1773147, upload-time = "2026-03-31T21:58:41.476Z" },
- { url = "https://files.pythonhosted.org/packages/01/a4/62f05a0a98d88af59d93b7fcac564e5f18f513cb7471696ac286db970d6a/aiohttp-3.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d6d44a5b48132053c2f6cd5c8cb14bc67e99a63594e336b0f2af81e94d5530c", size = 1730356, upload-time = "2026-03-31T21:58:44.049Z" },
- { url = "https://files.pythonhosted.org/packages/e4/85/fc8601f59dfa8c9523808281f2da571f8b4699685f9809a228adcc90838d/aiohttp-3.13.5-cp313-cp313-win32.whl", hash = "sha256:329f292ed14d38a6c4c435e465f48bebb47479fd676a0411936cc371643225cc", size = 432637, upload-time = "2026-03-31T21:58:46.167Z" },
- { url = "https://files.pythonhosted.org/packages/c0/1b/ac685a8882896acf0f6b31d689e3792199cfe7aba37969fa91da63a7fa27/aiohttp-3.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:69f571de7500e0557801c0b51f4780482c0ec5fe2ac851af5a92cfce1af1cb83", size = 458896, upload-time = "2026-03-31T21:58:48.119Z" },
+sdist = { url = "https://files.pythonhosted.org/packages/58/d9/22ce5786ac0c1653ae8b6c23bded02c1686d11f0dbb45b31ce128e0df985/aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc", size = 7971213, upload-time = "2026-07-23T01:57:27.037Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2d/4d/4a99fb425c5e0cad715eea7bd190aff46f38b959a0a2dadb993705d34b26/aiohttp-3.14.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b", size = 765848, upload-time = "2026-07-23T01:52:08.217Z" },
+ { url = "https://files.pythonhosted.org/packages/74/e8/43b85dc55b8e950dc644babe762add781319ea881b57b33d2cce12017d12/aiohttp-3.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a", size = 517476, upload-time = "2026-07-23T01:52:10.846Z" },
+ { url = "https://files.pythonhosted.org/packages/7f/9e/73b582c4dbbc3c12ef4473822475effaabf1f934b56f14f5b03fe5d3a2af/aiohttp-3.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5", size = 515334, upload-time = "2026-07-23T01:52:12.636Z" },
+ { url = "https://files.pythonhosted.org/packages/79/03/e98c3c9e05a5bdf97defe5ff9169baba4f0ec9a901f2d60e0f060c2f051e/aiohttp-3.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f", size = 1708830, upload-time = "2026-07-23T01:52:14.538Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/2c/26e60b694844dfd2176c57f913a22d0cd6a16f9ff202cbda7580d0328b98/aiohttp-3.14.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43", size = 1674012, upload-time = "2026-07-23T01:52:16.486Z" },
+ { url = "https://files.pythonhosted.org/packages/38/65/672df92e3172cd876aacfa97a952ac560877eb169384b2991ac5b273de4c/aiohttp-3.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9", size = 1767015, upload-time = "2026-07-23T01:52:18.28Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/c5/228dec7bfec1c373cc2217cdeb47d6456dcd7a13a4c55144930a75ae3851/aiohttp-3.14.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8", size = 1858700, upload-time = "2026-07-23T01:52:20.08Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/ff/cb36724e8c8d17f90ada567a9ff3efe1d6e9b549fba697a242aece180f21/aiohttp-3.14.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479", size = 1714075, upload-time = "2026-07-23T01:52:22.071Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/3a/296a4135c6366376263aeef54b15caca1f07676c2ae0c525d7832f2f808a/aiohttp-3.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b", size = 1588234, upload-time = "2026-07-23T01:52:23.757Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/81/9d5d853ef892dc066d1eb6db0e87a47348b920c1c879aa554612fdbd9d79/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d", size = 1677300, upload-time = "2026-07-23T01:52:25.861Z" },
+ { url = "https://files.pythonhosted.org/packages/68/96/021d386ae32d9b26d4b88df2e794546232ff56bb6be952bf6be227c0bbc7/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d", size = 1691501, upload-time = "2026-07-23T01:52:28Z" },
+ { url = "https://files.pythonhosted.org/packages/29/9f/af66adce26a14af135c003cbd0f44ccaa68cebd30ff8ac99ca47fb4958f7/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2", size = 1735113, upload-time = "2026-07-23T01:52:29.995Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/90/28c390d4c9851effe52ac25b5a2e1d92246acd00728b4fc7975dafb67484/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48", size = 1577486, upload-time = "2026-07-23T01:52:31.937Z" },
+ { url = "https://files.pythonhosted.org/packages/db/c2/00e23a1bf2abb70dd353f6987db7e7f2491d0261f7363997738c71c98f95/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f", size = 1751353, upload-time = "2026-07-23T01:52:33.688Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/7d/d51a706a8cbfa57f0611127daf61ab3ae02ab8420b0407412079227d1c65/aiohttp-3.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32", size = 1698681, upload-time = "2026-07-23T01:52:38.167Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/b0/90bd5cd9fdd9787cb4211d284d1fb8401339a933cb0227a15b71e789232f/aiohttp-3.14.3-cp310-cp310-win32.whl", hash = "sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e", size = 456733, upload-time = "2026-07-23T01:52:41.823Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/15/fe5b8f6a71ae112bc677163d0b0701bda5dc15005249582258ede0eb88c7/aiohttp-3.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c", size = 480460, upload-time = "2026-07-23T01:52:43.905Z" },
+ { url = "https://files.pythonhosted.org/packages/54/00/45e98b6645cd7f00a4b78b749ebd309094b0eaeb2d2e96157eadbc0d0050/aiohttp-3.14.3-cp310-cp310-win_arm64.whl", hash = "sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb", size = 453479, upload-time = "2026-07-23T01:52:46.075Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/5c/b3e4ff8ad43a8afef9602c5e90285936da1beaea8b029016b793891f03c3/aiohttp-3.14.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3", size = 764250, upload-time = "2026-07-23T01:52:48.525Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/da/f1b384465e51449d844056b75070461da03a9a23e6c1747003695bf4172a/aiohttp-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a", size = 516281, upload-time = "2026-07-23T01:52:51.047Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/3f/01264f820ee2e3712a827892b1cd6ff80f3300c1fcbffbb45714a915d47a/aiohttp-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8", size = 514742, upload-time = "2026-07-23T01:52:53.779Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/8d/a71c6f2db52ac1ed142b133f7feddaa6b70539c3f4de24d7e226c95b794c/aiohttp-3.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239", size = 1780613, upload-time = "2026-07-23T01:52:56.948Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/11/3dd9b3fb3a170f6ec9011b5291d876a6fab4086714c9e158600edf01b4fd/aiohttp-3.14.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f", size = 1737688, upload-time = "2026-07-23T01:52:59.294Z" },
+ { url = "https://files.pythonhosted.org/packages/6d/3e/834c26918be7d88068822b40e0db30fca50b5f4fe79104aa16a93f1d74e6/aiohttp-3.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06", size = 1845742, upload-time = "2026-07-23T01:53:01.641Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/c9/49ab8572df7d66bc13d11e31f781292badb04180dd87ba98733066c6aed7/aiohttp-3.14.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929", size = 1928412, upload-time = "2026-07-23T01:53:04.018Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/b9/2b8f0c0ce09c87a1daf80fd483431b56b1435d3f62789bc86f572e1245de/aiohttp-3.14.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db", size = 1786220, upload-time = "2026-07-23T01:53:06.481Z" },
+ { url = "https://files.pythonhosted.org/packages/85/00/9c45f81de11710460edfa1dc81317b6e882703b160926c879a9d20da9fcc/aiohttp-3.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce", size = 1637231, upload-time = "2026-07-23T01:53:10.258Z" },
+ { url = "https://files.pythonhosted.org/packages/19/ce/967d628e910756f3539c6107cb7844a1b69440dcb3029a5ee7871b09ab63/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c", size = 1753161, upload-time = "2026-07-23T01:53:13.817Z" },
+ { url = "https://files.pythonhosted.org/packages/11/b2/0c3d4114f0aee4f580f5b3b4eb71b24d7a23b834ea506a4dfebe76513f35/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15", size = 1756356, upload-time = "2026-07-23T01:53:16.211Z" },
+ { url = "https://files.pythonhosted.org/packages/63/5d/99e7d91c82f1399d1ae2a854e080bd1493fbc31e5e959dbc4ec33dac3bec/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c", size = 1819846, upload-time = "2026-07-23T01:53:18.289Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/05/d5e1cb6480eeffd3f901d40a2c5e2d1e7effdc797837da3b490272699f13/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae", size = 1628531, upload-time = "2026-07-23T01:53:23.86Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/90/b934682bcaefae18a9e04f3dff5b68522ba810906358ae5029b68110ea3b/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910", size = 1832712, upload-time = "2026-07-23T01:53:27.551Z" },
+ { url = "https://files.pythonhosted.org/packages/21/df/6061679faaf81fac746e7307c7adb71e858071a5d34c27583afefc64f543/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7", size = 1775014, upload-time = "2026-07-23T01:53:30.223Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/1d/f854878bbc69b88faefe924b619a34a6f59ec05fd387c77690667eaa75eb/aiohttp-3.14.3-cp311-cp311-win32.whl", hash = "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa", size = 456006, upload-time = "2026-07-23T01:53:34.97Z" },
+ { url = "https://files.pythonhosted.org/packages/73/0c/2af9d1674baccd1dbd47282a93d660a22e57ef6167c856deb24b4214fbab/aiohttp-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d", size = 481069, upload-time = "2026-07-23T01:53:39.673Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/76/88401ff3fc95e85c5fc38d588f36f55e61ecb64343b2bc8d69326f453cc0/aiohttp-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39", size = 453021, upload-time = "2026-07-23T01:53:43.749Z" },
+ { url = "https://files.pythonhosted.org/packages/18/d4/eb96299230e20acf2efae207cb8d69051f1f68e357e5ea5e479bf6fb097a/aiohttp-3.14.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5", size = 754690, upload-time = "2026-07-23T01:53:47.332Z" },
+ { url = "https://files.pythonhosted.org/packages/88/11/e7a70a209eb9a067c0d3212b518a0134e3484f5178c7533878b6b514d469/aiohttp-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228", size = 509484, upload-time = "2026-07-23T01:53:51.159Z" },
+ { url = "https://files.pythonhosted.org/packages/30/07/4bbc222cc8dbe31d4c3e8a5baad2286e4d42026ac0c570027b89afce6344/aiohttp-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee", size = 511949, upload-time = "2026-07-23T01:53:55.083Z" },
+ { url = "https://files.pythonhosted.org/packages/54/b9/42e74c46b7b7c794b995bbc1f573fb48950c38b19d8600c62a6804ee2d67/aiohttp-3.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a", size = 1765282, upload-time = "2026-07-23T01:53:59.662Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/ed/62bc4d74363ad346d518e0720363a949f63e2e23439a79eb5813d4d29bb3/aiohttp-3.14.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b", size = 1741511, upload-time = "2026-07-23T01:54:04.063Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/9f/181e8a8bc79e47d13c7fc4540bd7a3b729d9505609c61f392a8dd2fbfe55/aiohttp-3.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529", size = 1810680, upload-time = "2026-07-23T01:54:09.882Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/9a/dec94d6ad694552fe3424e3f1928d7a606a5d9d9433a04e7ecdd9d38ae7f/aiohttp-3.14.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787", size = 1905646, upload-time = "2026-07-23T01:54:13.475Z" },
+ { url = "https://files.pythonhosted.org/packages/52/b7/7cd31f29d6055bd711ae6e669367fba6f5ae9de463910a793e30556a8db7/aiohttp-3.14.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42", size = 1792122, upload-time = "2026-07-23T01:54:15.752Z" },
+ { url = "https://files.pythonhosted.org/packages/66/73/10b1ef93afa61f4963c746257b70ced619cf31a4798671de5fdb2608501d/aiohttp-3.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b", size = 1591127, upload-time = "2026-07-23T01:54:19.489Z" },
+ { url = "https://files.pythonhosted.org/packages/49/ed/3b203fa6de1b338c14acdc06bf6ca9b043b7944f005966958c2ced932cde/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043", size = 1725210, upload-time = "2026-07-23T01:54:24.129Z" },
+ { url = "https://files.pythonhosted.org/packages/28/b7/1c2aab8c706436dcc28598452488ac9cd7c409da815237c28c27d58993e6/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427", size = 1764848, upload-time = "2026-07-23T01:54:27.973Z" },
+ { url = "https://files.pythonhosted.org/packages/54/50/94c28f08b131c4bf10984ea2c7a536c9920608bb2d6e7f95642c30cc87b7/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d", size = 1777102, upload-time = "2026-07-23T01:54:31.775Z" },
+ { url = "https://files.pythonhosted.org/packages/13/d4/e7d09ba7d345fb2d74440fd2fa033c5e079fac05552927705986f41a364f/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0", size = 1580205, upload-time = "2026-07-23T01:54:34.518Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/84/072a91d68e1e1eb587985b54baab94221277f877e8ef274fc213a0ceae28/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d", size = 1797219, upload-time = "2026-07-23T01:54:36.995Z" },
+ { url = "https://files.pythonhosted.org/packages/e0/eb/aad34e897e668424d6e995da5dff8a4a09af93363d3392488772957a63aa/aiohttp-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19", size = 1768629, upload-time = "2026-07-23T01:54:40.103Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/2b/6bb88ddba0fecd9122aa3ebcad25996cf6c083a4a7040dbb3a4f97972af6/aiohttp-3.14.3-cp312-cp312-win32.whl", hash = "sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559", size = 451481, upload-time = "2026-07-23T01:54:42.547Z" },
+ { url = "https://files.pythonhosted.org/packages/76/9b/f2f8f108da17ecef2cc3efc424e8b7ad3782b1a8360f7b8eae8ced84f6ea/aiohttp-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a", size = 476845, upload-time = "2026-07-23T01:54:44.853Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/44/28dac80a8941b604f4da10ce21097614ca1bf905ce93dca28d8d7de9c1e7/aiohttp-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c", size = 448050, upload-time = "2026-07-23T01:54:47.087Z" },
+ { url = "https://files.pythonhosted.org/packages/57/be/5afd201cc0ab139029aadb75392efe85a293403d9dd3a3226161c21ce00c/aiohttp-3.14.3-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86", size = 506269, upload-time = "2026-07-23T01:54:49.075Z" },
+ { url = "https://files.pythonhosted.org/packages/22/09/dec8189d62b45ade009f6792a2264b942a90cb88aeaf181239933cd72c3c/aiohttp-3.14.3-cp313-cp313-android_21_x86_64.whl", hash = "sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627", size = 515166, upload-time = "2026-07-23T01:54:51.894Z" },
+ { url = "https://files.pythonhosted.org/packages/28/24/2854869d29ed8a8b19d74f9ec6629515f7e04d02dd329d9d179201e58e47/aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82", size = 486263, upload-time = "2026-07-23T01:54:54.223Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/dd/57187c8be2a35aea65eaee3bd2c3dcbbcf0204f5106c89637e3610380cd1/aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c", size = 492299, upload-time = "2026-07-23T01:54:56.236Z" },
+ { url = "https://files.pythonhosted.org/packages/b9/11/06ae6ed8f0d414edf4068861e233d8fe23ee699bfd4b3ceb8663db948a62/aiohttp-3.14.3-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f", size = 502235, upload-time = "2026-07-23T01:54:58.377Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/a3/559639c34a345d2cf7c52dff6838119f2eaf29eb508227b5b83f573af813/aiohttp-3.14.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80", size = 750883, upload-time = "2026-07-23T01:55:00.65Z" },
+ { url = "https://files.pythonhosted.org/packages/91/cd/41e131f13afd1e7b0172a9d9eda085ef90eb8439f41f0d279db81ed3ae60/aiohttp-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0", size = 508473, upload-time = "2026-07-23T01:55:02.945Z" },
+ { url = "https://files.pythonhosted.org/packages/bc/6b/e7f13410d391c6e55b4c007a8de024355389d7d459e3d64c42b2d33617e5/aiohttp-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf", size = 509190, upload-time = "2026-07-23T01:55:05.173Z" },
+ { url = "https://files.pythonhosted.org/packages/97/21/6464573e53d69672cc1eada3e5c5cb2d2efa82701e8305a0f2047a576967/aiohttp-3.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd", size = 1761478, upload-time = "2026-07-23T01:55:07.383Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/81/d217043a4c17fbce360905e3b2bdd20139ebc9a2de836d035d179c4da006/aiohttp-3.14.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807", size = 1735092, upload-time = "2026-07-23T01:55:09.803Z" },
+ { url = "https://files.pythonhosted.org/packages/a1/66/e13a02d0eeb1a9a502402a977abb4e4abff9fe4051c26f80558c57a7c975/aiohttp-3.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8", size = 1800546, upload-time = "2026-07-23T01:55:12.012Z" },
+ { url = "https://files.pythonhosted.org/packages/26/5e/57d42fca1d18cb5acc1cad945d017fabc5d6ae71d8a08ad66be8dc3ee544/aiohttp-3.14.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24", size = 1895250, upload-time = "2026-07-23T01:55:14.357Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/1c/7da8d08e74d56f00070822f9638ff3f1c563f8ad87d1efa996c87bfc8644/aiohttp-3.14.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5", size = 1789289, upload-time = "2026-07-23T01:55:16.668Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/0f/cf16bcf56896981c1a0319f5d5db9337994b5165730c48a8fa07e9b34be6/aiohttp-3.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4", size = 1586706, upload-time = "2026-07-23T01:55:18.913Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/6f/76eac12a7f2480e1e304f842efdb07db33256b0d9165b866b6ef0806c202/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9", size = 1724652, upload-time = "2026-07-23T01:55:21.296Z" },
+ { url = "https://files.pythonhosted.org/packages/39/b6/19c8c592baeeb94b75f966547d40c02ac7590902306ec5863d5c027cf506/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1", size = 1756239, upload-time = "2026-07-23T01:55:23.705Z" },
+ { url = "https://files.pythonhosted.org/packages/dc/c9/4e9383150296f97f873b680c4de8fb2cd88608fb9f48c79edcb111611abc/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371", size = 1769161, upload-time = "2026-07-23T01:55:26.082Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/1e/147bdc6cc5de5f3ab011be8bf5d6e786633249f22c20bae06f85e45f5387/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde", size = 1578759, upload-time = "2026-07-23T01:55:28.846Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/31/78388a9d6040ece2e11df62ea229a822cf5e52d238374b220ae9975b2623/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e", size = 1792025, upload-time = "2026-07-23T01:55:31.457Z" },
+ { url = "https://files.pythonhosted.org/packages/03/51/a3d29fdf2c25d796746af8ad6fe56a45d6256c38b0a8a2ed752e1160b3a2/aiohttp-3.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71", size = 1768477, upload-time = "2026-07-23T01:55:33.87Z" },
+ { url = "https://files.pythonhosted.org/packages/29/a6/442e18b5afeade534d877a2dc3c3e392aff8d49787890b0cf84790410267/aiohttp-3.14.3-cp313-cp313-win32.whl", hash = "sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0", size = 451069, upload-time = "2026-07-23T01:55:36.121Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/69/3d876ac02659f271cf7f6769f14a8e3de5b6e888ed8b5a7e998086a4cec8/aiohttp-3.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883", size = 476518, upload-time = "2026-07-23T01:55:38.303Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/0e/50d6e6471cd31edce8b282bdec59375a3a69124d8a989a0b1313355cae52/aiohttp-3.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2", size = 447676, upload-time = "2026-07-23T01:55:40.451Z" },
]
[[package]]
@@ -280,6 +290,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
]
+[[package]]
+name = "automat"
+version = "25.4.16"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e3/0f/d40bbe294bbf004d436a8bcbcfaadca8b5140d39ad0ad3d73d1a8ba15f14/automat-25.4.16.tar.gz", hash = "sha256:0017591a5477066e90d26b0e696ddc143baafd87b588cfac8100bc6be9634de0", size = 129977, upload-time = "2025-04-16T20:12:16.002Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/02/ff/1175b0b7371e46244032d43a56862d0af455823b5280a50c63d99cc50f18/automat-25.4.16-py3-none-any.whl", hash = "sha256:04e9bce696a8d5671ee698005af6e5a9fa15354140a87f4870744604dcdd3ba1", size = 42842, upload-time = "2025-04-16T20:12:14.447Z" },
+]
+
[[package]]
name = "babel"
version = "2.18.0"
@@ -302,6 +321,34 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" },
]
+[[package]]
+name = "boto3"
+version = "1.43.56"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore" },
+ { name = "jmespath" },
+ { name = "s3transfer" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/53/05/23e1aa8c9e4b0399a61e7fd65c4f9cc0625121f24760e37471f776404abb/boto3-1.43.56.tar.gz", hash = "sha256:57c90df9fb026f2e6ae22530861198130203733c5c9ec4e5cca3a4037f5a8db4", size = 112673, upload-time = "2026-07-24T19:31:48.606Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b8/57/3a960c9f581c00f2a591901b46e035ff79ab3956d16607f12306b3b8d483/boto3-1.43.56-py3-none-any.whl", hash = "sha256:feb699d4ab241ef5c1b80bb58277be2aaad365cd4b672d7817e0bc59ee45131b", size = 140026, upload-time = "2026-07-24T19:31:47.155Z" },
+]
+
+[[package]]
+name = "botocore"
+version = "1.43.56"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "jmespath" },
+ { name = "python-dateutil" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b9/cc/7f84a5d3071fe878380e9f610ab36ca87b8cbbc4aa81ba2727f90e1f3ea3/botocore-1.43.56.tar.gz", hash = "sha256:6c01f85f0ff9863076f4c761e74ee3aa96c5ccc1ad09fc1efd62ef8f2d22bf57", size = 15733117, upload-time = "2026-07-24T19:31:38.125Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/cd/86fe9e659e9699f62f8dd5ecd8c6725474334b23cab8aa71d82b5f56f1a4/botocore-1.43.56-py3-none-any.whl", hash = "sha256:aafc741f1b10f6fd63253eaf6ea029680c1ff436d87e1b8969d62aefa0c76976", size = 15418773, upload-time = "2026-07-24T19:31:34.758Z" },
+]
+
[[package]]
name = "certifi"
version = "2026.5.20"
@@ -465,6 +512,29 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
+[[package]]
+name = "constantly"
+version = "23.10.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4d/6f/cb2a94494ff74aa9528a36c5b1422756330a75a8367bf20bd63171fc324d/constantly-23.10.4.tar.gz", hash = "sha256:aa92b70a33e2ac0bb33cd745eb61776594dc48764b06c35e0efd050b7f1c7cbd", size = 13300, upload-time = "2023-10-28T23:18:24.316Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b8/40/c199d095151addf69efdb4b9ca3a4f20f70e20508d6222bffb9b76f58573/constantly-23.10.4-py3-none-any.whl", hash = "sha256:3fd9b4d1c3dc1ec9757f3c52aef7e53ad9323dbe39f51dfd4c43853b68dfa3f9", size = 13547, upload-time = "2023-10-28T23:18:23.038Z" },
+]
+
+[[package]]
+name = "courlan"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "babel" },
+ { name = "tld" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/bb/16/2a771612ee0b3acaa95ac21cc7e8a3319e815d6360f8ffc5987d1ce28499/courlan-1.4.0.tar.gz", hash = "sha256:fbbac7b7fcde2195ea08e707609503c81cf39c891e8d26cdb1fed4585782d63d", size = 208997, upload-time = "2026-06-01T17:30:17.306Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1f/38/ce65091ff20a16e06d17418c4353af5f56d3190821b1a06983c79ae79274/courlan-1.4.0-py3-none-any.whl", hash = "sha256:ad1dbdefd912ca7238d4607dc855df5df097f56bac175dd662c84eed3802f49e", size = 34193, upload-time = "2026-06-01T17:30:14.984Z" },
+]
+
[[package]]
name = "cryptography"
version = "49.0.0"
@@ -509,6 +579,30 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" },
]
+[[package]]
+name = "cssselect"
+version = "1.5.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/8e/5a/6d6fcf922709391fac986f0a03ad4546f4f45b94d10aeb6c1ee041599993/cssselect-1.5.0.tar.gz", hash = "sha256:3cbe82dd7acbee9ba9e5723b5f9e4749826912f1fb31cd7f92aabed5fde15b15", size = 47598, upload-time = "2026-07-27T09:17:34.189Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/60/e9/6734502f67533a752ea8b1c8f7f227c94eecf300252ba8bf23e3e59d8a36/cssselect-1.5.0-py3-none-any.whl", hash = "sha256:1d1aded98e82bdde447ded990a191fd6916177c4f0c914fb62eccd58e2ffcdcc", size = 20797, upload-time = "2026-07-27T09:17:33.04Z" },
+]
+
+[[package]]
+name = "dateparser"
+version = "1.4.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "python-dateutil" },
+ { name = "pytz" },
+ { name = "regex" },
+ { name = "tzlocal" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d3/f4/561c49bca97af561d34eed27e3e831135eb5cb88e754c1150be41820f5c6/dateparser-1.4.1.tar.gz", hash = "sha256:f265df13c0380e2e07543ba74b67c0681aaa1096981ffcd35227e1aa0cb81c7c", size = 314734, upload-time = "2026-06-15T08:45:47.659Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8b/7c/2e5dcf53909deddd0bf38cbe277ad9806be038276b1c6c436561b4d9b2e2/dateparser-1.4.1-py3-none-any.whl", hash = "sha256:f25d4e051a84be27a35bd297e3e1dc59ff78373701b89be352ba80372d22d0d0", size = 300503, upload-time = "2026-06-15T08:45:45.951Z" },
+]
+
[[package]]
name = "decorator"
version = "5.3.1"
@@ -933,16 +1027,19 @@ wheels = [
]
[[package]]
-name = "html5lib"
-version = "1.1"
+name = "htmldate"
+version = "1.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "six" },
- { name = "webencodings" },
+ { name = "charset-normalizer" },
+ { name = "dateparser" },
+ { name = "lxml" },
+ { name = "python-dateutil" },
+ { name = "urllib3" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215, upload-time = "2020-06-22T23:32:38.834Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/ad/1f/e7cf83e23d7b68105de8b874a8b36ba23b450d6f71388583e4ca3ce475ca/htmldate-1.10.0.tar.gz", hash = "sha256:a38df10772ab5d7dbb11896e3f6a852a8491fb1b0965465bc174e23fc2baae58", size = 44455, upload-time = "2026-06-01T17:43:53.437Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173, upload-time = "2020-06-22T23:32:36.781Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/17/d3356233c826c641f940983d9479eab27faec59d49f4070bc58e80fcc021/htmldate-1.10.0-py3-none-any.whl", hash = "sha256:9211dae35ab94147c8ed9e5fc2c9287a5cf31d2394cb7857e7f5dd814eb2aad6", size = 31561, upload-time = "2026-06-01T17:43:51.797Z" },
]
[[package]]
@@ -1043,6 +1140,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/49/79/621a7dbb80c70974f73a597275351ebe03ce5bc65cb5f8f4acb5859252bc/huggingface_hub-1.16.1-py3-none-any.whl", hash = "sha256:64340de934b9ce37857ef85a82de72f5629e8a270f9119eabb12bf495eb53c22", size = 668176, upload-time = "2026-05-21T18:39:58.596Z" },
]
+[[package]]
+name = "hyperlink"
+version = "21.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3a/51/1947bd81d75af87e3bb9e34593a4cf118115a8feb451ce7a69044ef1412e/hyperlink-21.0.0.tar.gz", hash = "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b", size = 140743, upload-time = "2021-01-08T05:51:20.972Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6e/aa/8caf6a0a3e62863cbb9dab27135660acba46903b703e224f14f447e57934/hyperlink-21.0.0-py2.py3-none-any.whl", hash = "sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4", size = 74638, upload-time = "2021-01-08T05:51:22.906Z" },
+]
+
[[package]]
name = "idna"
version = "3.16"
@@ -1073,6 +1182,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/7d/f9/97f2ca8bb3ec6e4b1d64f983ebe98b9a192faddff67fac3d6303a537e670/importlib_metadata-8.9.0-py3-none-any.whl", hash = "sha256:e0f761b6ea91ced3b0844c14c9d955224d538105921f8e6754c00f6ca79fba7f", size = 27220, upload-time = "2026-03-20T16:56:25.07Z" },
]
+[[package]]
+name = "incremental"
+version = "24.11.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+ { name = "tomli", marker = "python_full_version < '3.11'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ef/3c/82e84109e02c492f382c711c58a3dd91badda6d746def81a1465f74dc9f5/incremental-24.11.0.tar.gz", hash = "sha256:87d3480dbb083c1d736222511a8cf380012a8176c2456d01ef483242abbbcf8c", size = 24000, upload-time = "2025-11-28T02:30:17.861Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1d/55/0f4df2a44053867ea9cbea73fc588b03c55605cd695cee0a3d86f0029cb2/incremental-24.11.0-py3-none-any.whl", hash = "sha256:a34450716b1c4341fe6676a0598e88a39e04189f4dce5dc96f656e040baa10b3", size = 21109, upload-time = "2025-11-28T02:30:16.442Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
@@ -1082,6 +1204,29 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
]
+[[package]]
+name = "itemadapter"
+version = "0.13.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/52/47/4c75c5396941e653d5f864389964da6951e8f338c6739602dd778f62333e/itemadapter-0.13.1.tar.gz", hash = "sha256:fa139c7be2aa80f8874b2f23d165d5d4aa47c4b85c54ab530b567fd5f684f1b4", size = 32343, upload-time = "2026-01-08T17:56:38.863Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/db/a6/48805cef65b13644f1c23545dc525a7051581c84f5227efb1cd9a8ac9b02/itemadapter-0.13.1-py3-none-any.whl", hash = "sha256:f3c6b1babb4fb6cca4aa9061ef0b0c25c783c24a571c30e3667e7bcfea41815b", size = 18540, upload-time = "2026-01-08T17:56:37.29Z" },
+]
+
+[[package]]
+name = "itemloaders"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "itemadapter" },
+ { name = "jmespath" },
+ { name = "parsel" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/05/bd/916f4fd26e14e6ad292b69693ccca4f192bcaf9f817ba7d6f7162dbbd835/itemloaders-1.4.0.tar.gz", hash = "sha256:b5338308a819098f43525b7afc5f7d46ba338ba4710f5ebe7a21b3b47bb29929", size = 29740, upload-time = "2026-01-29T12:50:38.04Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ac/71/d9cd0e4c6a4aace991009fc47362ce9251be0fbcf2b6c533f918b31854d5/itemloaders-1.4.0-py3-none-any.whl", hash = "sha256:202b6f855299b4cadfdf78bb93a6cf977899e3c40c4c54524e120a444e65b5ac", size = 12188, upload-time = "2026-01-29T12:50:36.148Z" },
+]
+
[[package]]
name = "jinja2"
version = "3.1.6"
@@ -1170,13 +1315,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/8d/302cb2057b7513327b4d575cff6b1d066ee6431a5357fc3f8867cd684406/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a", size = 344469, upload-time = "2026-05-19T10:09:46.864Z" },
]
+[[package]]
+name = "jmespath"
+version = "1.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" },
+]
+
[[package]]
name = "json-repair"
-version = "0.59.10"
+version = "0.61.7"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d3/7c/e95bb03068572146eba37e8175c760f470ea0a6097310e16bbf2bc6e6457/json_repair-0.59.10.tar.gz", hash = "sha256:2e4b85537c752d8a513ea28fdad891e5ede32c83de745366b97f648b8c34ede7", size = 49133, upload-time = "2026-05-14T06:41:51.222Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/f0/a3/6001c2448ee54a80f35a2501b848f4bbd87987bd41ead8cc17367a2bfd56/json_repair-0.61.7.tar.gz", hash = "sha256:a3754543f050093efcda6c9ab00b20a236b5d082c8c622bc65b88fa74ff8d51f", size = 51573, upload-time = "2026-07-21T13:01:15.085Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ee/87/49b20c6b81493d55c311f711ed87319d0fbad8bd0bbfbe36e52103af36bd/json_repair-0.59.10-py3-none-any.whl", hash = "sha256:5468fa3eaadcc9b4a5646776bc4176e2fe5f374b5848a15f468cce3b60e3db0e", size = 47742, upload-time = "2026-05-14T06:41:49.812Z" },
+ { url = "https://files.pythonhosted.org/packages/76/da/7f9e2b0a1120b107a204bbab6d0ef7ff2ae37790bddc5ee21c9c1f961f3b/json_repair-0.61.7-py3-none-any.whl", hash = "sha256:45c99b8cffef404e846b60d3dc21fc6f0fd5a4595cebad169dfab083ffb8246a", size = 50146, upload-time = "2026-07-21T13:01:13.734Z" },
]
[[package]]
@@ -1206,6 +1360,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
]
+[[package]]
+name = "justext"
+version = "3.0.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "lxml", extra = ["html-clean"] },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/49/f3/45890c1b314f0d04e19c1c83d534e611513150939a7cf039664d9ab1e649/justext-3.0.2.tar.gz", hash = "sha256:13496a450c44c4cd5b5a75a5efcd9996066d2a189794ea99a49949685a0beb05", size = 828521, upload-time = "2025-02-25T20:21:49.934Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f2/ac/52f4e86d1924a7fc05af3aeb34488570eccc39b4af90530dd6acecdf16b5/justext-3.0.2-py2.py3-none-any.whl", hash = "sha256:62b1c562b15c3c6265e121cc070874243a443bfd53060e869393f09d6b6cc9a7", size = 837940, upload-time = "2025-02-25T20:21:44.179Z" },
+]
+
[[package]]
name = "kubernetes"
version = "36.0.0"
@@ -1419,6 +1585,23 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/db/a4/441aee36c6f6b249823d20fd91f9be9ab89d7c5a8ae542a4a4ca6d342d56/lxml-6.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ed21202aec73cda4d55d1ce57b389aadb90ffb044e6cd1080b8347efe1b1ec84", size = 3508989, upload-time = "2026-05-18T19:18:38.158Z" },
]
+[package.optional-dependencies]
+html-clean = [
+ { name = "lxml-html-clean" },
+]
+
+[[package]]
+name = "lxml-html-clean"
+version = "0.4.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "lxml" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/0a/63/195dfdde380a84df309e3bccf4384b034b745dba43426886f7ae623b4fba/lxml_html_clean-0.4.5.tar.gz", hash = "sha256:e2a4c7d5beedd17cd7b484d848a0571e54baa239a4f9df5546e3acba7f990560", size = 24142, upload-time = "2026-05-20T12:17:53.574Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6a/bd/6e2b76a6c5dee10397db9c929f0c5066766ec1036046f0335b7ca7ca08b8/lxml_html_clean-0.4.5-py3-none-any.whl", hash = "sha256:c76fcadd1e5bfb9b8bafc2200d51e4e78eb0dad67f56881c21dfb6484c7e7746", size = 14573, upload-time = "2026-05-20T12:17:52.215Z" },
+]
+
[[package]]
name = "markdown-it-py"
version = "3.0.0"
@@ -1451,19 +1634,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
]
-[[package]]
-name = "markdownify"
-version = "1.2.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "beautifulsoup4" },
- { name = "six" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/3f/bc/c8c8eea5335341306b0fa7e1cb33c5e1c8d24ef70ddd684da65f41c49c92/markdownify-1.2.2.tar.gz", hash = "sha256:b274f1b5943180b031b699b199cbaeb1e2ac938b75851849a31fd0c3d6603d09", size = 18816, upload-time = "2025-11-16T19:21:18.565Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/43/ce/f1e3e9d959db134cedf06825fae8d5b294bd368aacdd0831a3975b7c4d55/markdownify-1.2.2-py3-none-any.whl", hash = "sha256:3f02d3cc52714084d6e589f70397b6fc9f2f3a8531481bf35e8cc39f975e186a", size = 15724, upload-time = "2025-11-16T19:21:17.622Z" },
-]
-
[[package]]
name = "markupsafe"
version = "3.0.3"
@@ -1529,7 +1699,7 @@ wheels = [
[[package]]
name = "mcp"
-version = "1.27.1"
+version = "1.28.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -1547,9 +1717,9 @@ dependencies = [
{ name = "typing-inspection" },
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/38/83/d1efe7c2980d8a3afa476f4e3d42d53dd54c0ab94c27bee5d755b45c8b73/mcp-1.27.1.tar.gz", hash = "sha256:0f47e1820f8f8f941466b39749eb1d1839a04caddca2bc60e9d46e8a99914924", size = 608458, upload-time = "2026-05-08T16:50:12.601Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/fd/73/42d9596facebdb533b7f0b86c1b0364ef350d1f8ba78b1052e8a58b48b65/mcp-1.27.1-py3-none-any.whl", hash = "sha256:1af3c4203b329430fde7a87b4fcb6392a041f5cb851fd68fc674016ab4e7c06f", size = 216260, upload-time = "2026-05-08T16:50:10.547Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" },
]
[[package]]
@@ -1824,7 +1994,7 @@ wheels = [
[[package]]
name = "openrath"
-version = "1.3.0"
+version = "2.0.0rc1"
source = { editable = "." }
dependencies = [
{ name = "anthropic" },
@@ -1843,12 +2013,35 @@ opensandbox = [
{ name = "opensandbox-server" },
]
openviking = [
+ { name = "aiohttp" },
+ { name = "json-repair" },
{ name = "openviking" },
+ { name = "pillow" },
+ { name = "soupsieve" },
+]
+otel = [
+ { name = "opentelemetry-api" },
+ { name = "opentelemetry-sdk" },
+]
+postgres = [
+ { name = "psycopg", extra = ["binary", "pool"] },
+]
+redis = [
+ { name = "redis" },
+]
+s3 = [
+ { name = "boto3" },
+]
+server = [
+ { name = "httpx" },
+ { name = "starlette" },
+ { name = "uvicorn" },
]
[package.dev-dependencies]
dev = [
{ name = "mypy" },
+ { name = "opentelemetry-sdk" },
{ name = "pytest" },
{ name = "pytest-benchmark" },
{ name = "pytest-rerunfailures" },
@@ -1867,21 +2060,34 @@ docs = [
[package.metadata]
requires-dist = [
+ { name = "aiohttp", marker = "extra == 'openviking'", specifier = ">=3.14.1" },
{ name = "anthropic", specifier = ">=0.40.0" },
+ { name = "boto3", marker = "extra == 's3'", specifier = ">=1.40,<2" },
+ { name = "httpx", marker = "extra == 'server'", specifier = ">=0.28,<1" },
+ { name = "json-repair", marker = "extra == 'openviking'", specifier = ">=0.60.1" },
{ name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.80,<1.88" },
- { name = "mcp", specifier = ">=1.0.0" },
+ { name = "mcp", specifier = ">=1.28.1,<2" },
{ name = "openai", specifier = ">=1.0.0" },
- { name = "opensandbox", marker = "extra == 'opensandbox'", specifier = ">=0.1.13" },
+ { name = "opensandbox", marker = "extra == 'opensandbox'", specifier = ">=0.1.15" },
{ name = "opensandbox-code-interpreter", marker = "extra == 'opensandbox'", specifier = ">=0.1.2" },
- { name = "opensandbox-server", marker = "extra == 'opensandbox'", specifier = ">=0.2.1" },
- { name = "openviking", marker = "extra == 'openviking'", specifier = ">=0.4.7" },
+ { name = "opensandbox-server", marker = "extra == 'opensandbox'", specifier = ">=0.2.2" },
+ { name = "opentelemetry-api", marker = "extra == 'otel'", specifier = ">=1.36,<2" },
+ { name = "opentelemetry-sdk", marker = "extra == 'otel'", specifier = ">=1.36,<2" },
+ { name = "openviking", marker = "extra == 'openviking'", specifier = ">=0.4.11" },
+ { name = "pillow", marker = "extra == 'openviking'", specifier = ">=12.3.0" },
+ { name = "psycopg", extras = ["binary", "pool"], marker = "extra == 'postgres'", specifier = ">=3.2,<4" },
{ name = "pydantic", specifier = ">=2.0.0,<3" },
+ { name = "redis", marker = "extra == 'redis'", specifier = ">=6,<7" },
+ { name = "soupsieve", marker = "extra == 'openviking'", specifier = ">=2.8.4" },
+ { name = "starlette", marker = "extra == 'server'", specifier = ">=1.3.1,<2" },
+ { name = "uvicorn", marker = "extra == 'server'", specifier = ">=0.35,<1" },
]
-provides-extras = ["litellm", "opensandbox", "openviking"]
+provides-extras = ["litellm", "opensandbox", "openviking", "server", "postgres", "redis", "otel", "s3"]
[package.metadata.requires-dev]
dev = [
{ name = "mypy", specifier = ">=1.20.2" },
+ { name = "opentelemetry-sdk", specifier = ">=1.36,<2" },
{ name = "pytest", specifier = ">=9.0.3" },
{ name = "pytest-benchmark", specifier = ">=4.0.0" },
{ name = "pytest-rerunfailures", specifier = ">=15.0" },
@@ -1897,7 +2103,7 @@ docs = [
[[package]]
name = "opensandbox"
-version = "0.1.13"
+version = "0.1.15"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
@@ -1905,9 +2111,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "python-dateutil" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/3e/e2/d2716adfca0cce6af3913035372d2f8cbe6a836e595d4747e19481113439/opensandbox-0.1.13.tar.gz", hash = "sha256:eab4b6597b2941f0418fa186a377c15b01acb8549f24f84963e7c15434232977", size = 201287, upload-time = "2026-06-25T06:52:57.384Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/43/21/654a3d69815b09690e926d553f3f4a178640d1206000a1b49f5e22c8eb68/opensandbox-0.1.15.tar.gz", hash = "sha256:017abc9b399b88da51bf077d6fb94ee89b1783e601495e85ba85fed478fed1b0", size = 228729, upload-time = "2026-07-24T09:36:29.988Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/f1/57/74459959e69e4271929ab3658c5abcbbf977977d126ddd7d861bfde4d0e5/opensandbox-0.1.13-py3-none-any.whl", hash = "sha256:8decd1eb952a3b539fecaf443b025c24d6d4a535f62242abd11644bc20505570", size = 491625, upload-time = "2026-06-25T06:52:55.726Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/5c/ab87ea696531210790feb8f575471036fccba29dedaff201736f15bbb3a7/opensandbox-0.1.15-py3-none-any.whl", hash = "sha256:992b01490551f4d8e3f99caa25e34cb9d1690f0c5027eeebab912738291957d1", size = 538522, upload-time = "2026-07-24T09:36:28.277Z" },
]
[[package]]
@@ -1925,13 +2131,16 @@ wheels = [
[[package]]
name = "opensandbox-server"
-version = "0.2.1"
+version = "0.2.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "docker" },
{ name = "fastapi" },
{ name = "httpx", extra = ["socks"] },
{ name = "kubernetes" },
+ { name = "opentelemetry-api" },
+ { name = "opentelemetry-exporter-otlp-proto-http" },
+ { name = "opentelemetry-sdk" },
{ name = "pydantic" },
{ name = "pydantic-settings" },
{ name = "python-multipart" },
@@ -1942,9 +2151,9 @@ dependencies = [
{ name = "uvicorn", extra = ["standard"] },
{ name = "websockets" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/06/0e/3f8cfff895fb77ef0db0622f81c6e0c27fb645d5e73a10beb088dc99294b/opensandbox_server-0.2.1.tar.gz", hash = "sha256:7cea6dcb816f28b4e2686c70ec68d3ee477ae2c4b6a7ad15a2ffc2485249ad99", size = 166552, upload-time = "2026-06-29T11:28:46.264Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/65/c8/ef8d1a831ac441864c1ace299733c5431394a35010f98e21e0e83a5860a4/opensandbox_server-0.2.2.tar.gz", hash = "sha256:fa82dde68dd407c67d153d31a84ed89be0d8ef6aba52e48b93877c0a215e18d9", size = 180835, upload-time = "2026-07-20T10:30:47.165Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/d2/21/c8df684d2e3485692cb19fe987c8a9ca0d62bf26c1c142f5844657879d8d/opensandbox_server-0.2.1-py3-none-any.whl", hash = "sha256:884a630ebd32f9e9dec8c0195fafd34dafa2b7b96539554efbe98639c95bb892", size = 246161, upload-time = "2026-06-29T11:28:44.93Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/1a/c44162539fa348f90ea4a28725d25cae073a8ab10a1c6b126a37475f56c1/opensandbox_server-0.2.2-py3-none-any.whl", hash = "sha256:08de41d214b90860d4921b04cd6dcca101e8130f3ff8dd5c52e58f81c0fc3ef3", size = 267550, upload-time = "2026-07-20T10:30:45.957Z" },
]
[[package]]
@@ -2078,7 +2287,7 @@ wheels = [
[[package]]
name = "openviking"
-version = "0.4.7"
+version = "0.4.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "apscheduler" },
@@ -2095,7 +2304,6 @@ dependencies = [
{ name = "lark-oapi" },
{ name = "litellm" },
{ name = "loguru" },
- { name = "markdownify" },
{ name = "mcp" },
{ name = "olefile" },
{ name = "openai" },
@@ -2115,9 +2323,10 @@ dependencies = [
{ name = "python-multipart" },
{ name = "python-pptx" },
{ name = "pyyaml" },
- { name = "readabilipy" },
{ name = "requests" },
+ { name = "scrapy" },
{ name = "tabulate" },
+ { name = "trafilatura" },
{ name = "tree-sitter" },
{ name = "tree-sitter-c-sharp" },
{ name = "tree-sitter-cpp" },
@@ -2138,25 +2347,25 @@ dependencies = [
{ name = "xlrd" },
{ name = "xxhash" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ff/ad/a9c44e4c7af316a95dc4c808f2b481df02f661227b0d7eb4c30a944c4e1e/openviking-0.4.7.tar.gz", hash = "sha256:5ff7b5a72988ca24b8c497578c4b238100622e6c351b01ebb6d2a0b6467626fd", size = 55450411, upload-time = "2026-07-02T13:46:19.868Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/40/07/f2a02e74784810f56a76f15115a7a5d1ac6ca4a982970540de4734e5cae3/openviking-0.4.11.tar.gz", hash = "sha256:4c18cb5c01b737b8ec9d0e9212c0ad54ef29f7f244aa7da79ffc21259d886317", size = 57716155, upload-time = "2026-07-23T07:36:43.763Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/32/77/9d47f6c326085b3eaac69caf219611afdb74cad56d404b0a741ab26afb54/openviking-0.4.7-cp310-abi3-macosx_14_0_arm64.whl", hash = "sha256:51c8d3a8eb68772fb1d1b1bb57aaaf26ed654d2ff0213d8994a270d9c4ab544e", size = 18680099, upload-time = "2026-07-02T13:46:00.642Z" },
- { url = "https://files.pythonhosted.org/packages/0a/18/b61d8d669319d6395d86d51eaf10b321e437dd0a5dc32367c4d3e2610aaa/openviking-0.4.7-cp310-abi3-macosx_15_0_x86_64.whl", hash = "sha256:9134f2921218740be697d68cc3c9db5f7e38bfcb53464e55800a74e8bbf33ed8", size = 21055402, upload-time = "2026-07-02T13:46:04.527Z" },
- { url = "https://files.pythonhosted.org/packages/c8/ba/e98c4e0fbd2cc2a3c94cbe9816df1b94de582d19800087030d9029a10b0f/openviking-0.4.7-cp310-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:0cfdb0308a9cd37f23cec5424425962bf784a0f89f816f7d39f1abc2ebeb03da", size = 19729687, upload-time = "2026-07-02T13:46:07.77Z" },
- { url = "https://files.pythonhosted.org/packages/21/5a/6c0e6e3bc732c4e1335597102478608f9e6cdb582a64f68e5b91a34b8970/openviking-0.4.7-cp310-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:e98c13e1f8cf9c9c805323e86516ccf4ace94053e0b309e212e8b79b242350e3", size = 22227659, upload-time = "2026-07-02T13:46:11.434Z" },
- { url = "https://files.pythonhosted.org/packages/ee/9f/7dd3cbd41d3a8fe23a504f474a5cef7e67a6b13084049a32536bf7191ee8/openviking-0.4.7-cp310-abi3-win_amd64.whl", hash = "sha256:da2a032dcae0f025ad2fe1df0d3d4e6d5d37f9263deef78b973e9d125ea0d08b", size = 24679040, upload-time = "2026-07-02T13:46:14.999Z" },
+ { url = "https://files.pythonhosted.org/packages/a0/83/ea2dbb9fb03218785c81f0b1b380024e22d6af75d06bd42c91e43aa180e7/openviking-0.4.11-cp310-abi3-macosx_14_0_arm64.whl", hash = "sha256:4a0389f2c3de0eb41cc2f26ccedb89566d8719393c3ab37d2ee2895cf9a8ebee", size = 18980965, upload-time = "2026-07-23T07:36:24.082Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/db/5bce6b007e0645c6c541974eb14b35329a5a0db6b96561df675c37d94d25/openviking-0.4.11-cp310-abi3-macosx_15_0_x86_64.whl", hash = "sha256:f3ed8d86917fe3cd94421019fb997bb874ef1f95fd97bada614a10b1516aba77", size = 21346489, upload-time = "2026-07-23T07:36:28.034Z" },
+ { url = "https://files.pythonhosted.org/packages/19/9e/648b9528f157691f2df0c3673298af55390e85640bbb9405b28cbb21d5fd/openviking-0.4.11-cp310-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:ae67550704e2d30d1bc1b0f38c35101dc55b0492834021dcd1aee9792e78de2c", size = 20072135, upload-time = "2026-07-23T07:36:31.972Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/9a/a0ab4a57ea6363b4849169d1ec282012ed60ea65e984007f50ce5a64deaa/openviking-0.4.11-cp310-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:db7d58a9689651cabe3978caca089eb3fee62cf8ea6521492309f25c56dc0d05", size = 22577257, upload-time = "2026-07-23T07:36:35.429Z" },
+ { url = "https://files.pythonhosted.org/packages/58/a1/e2c41af0a5672ec79afe0e7e858a03d1c7edb513a81f0a69d1a0f32a096f/openviking-0.4.11-cp310-abi3-win_amd64.whl", hash = "sha256:858f3d7bf2ecb102744d6de704551f9df9b4fa4ab9adc2bdcdd500f8881bf6c8", size = 25023612, upload-time = "2026-07-23T07:36:38.955Z" },
]
[[package]]
name = "openviking-sdk"
-version = "0.1.3"
+version = "0.1.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/e0/46/8fe7438310208e1aaa99bad4db2393d56320c3a718db017d8b8ba4920515/openviking_sdk-0.1.3.tar.gz", hash = "sha256:032632f3d5b93a3781f070757295ba4891be11e1799d3cfd3ad5c84a908ff965", size = 30505, upload-time = "2026-07-03T02:49:05.798Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/e4/9c/b75da8d956bbfaf39288dd3cf7c734ba9225fba34e44362d02fbdb9a871d/openviking_sdk-0.1.5.tar.gz", hash = "sha256:f017dec938267aaea659122165f2872e189933a5604ba6d9ec0ae867b558ecaf", size = 33652, upload-time = "2026-07-23T06:18:56.211Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/6a/98/1f60859fc6a54b32ebbd4221ed5a777fe1c81828476959fe99a07ea2e1ca/openviking_sdk-0.1.3-py3-none-any.whl", hash = "sha256:20e94db83b7db58018d75a552b32a1bb5705a7b4ec48e2ea34829896921c562e", size = 20468, upload-time = "2026-07-03T02:49:04.625Z" },
+ { url = "https://files.pythonhosted.org/packages/53/c0/481ec44e2f98cf1afd47d4c115756dd4b1fa674caa4b99b0f72723d6fc33/openviking_sdk-0.1.5-py3-none-any.whl", hash = "sha256:f29af1c56e1a4477c881d584fa5178b5a34600847926cfe21fddd333ccb576ec", size = 21740, upload-time = "2026-07-23T06:18:54.864Z" },
]
[[package]]
@@ -2168,6 +2377,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
]
+[[package]]
+name = "parsel"
+version = "1.11.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cssselect" },
+ { name = "jmespath" },
+ { name = "lxml" },
+ { name = "packaging" },
+ { name = "w3lib" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/91/c8/4ace3a5c61e39ca21734a5715d0e076eea6200dd8daea2a5b99452f5a0d6/parsel-1.11.0.tar.gz", hash = "sha256:5925fe087eb16fc404a7ed91e31e2c1e2a9b230da4b64f34d81358c0d0e27e88", size = 106849, upload-time = "2026-01-29T07:19:23.388Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/08/23/4e0dae5e5bee14aea26dba003a682e621563451a20f751ed985810f818b6/parsel-1.11.0-py3-none-any.whl", hash = "sha256:bda82575df1774dd64e1c1396163f3cadb3e383e0f8080d43d45fa6705355daa", size = 14176, upload-time = "2026-01-29T07:19:22.255Z" },
+]
+
[[package]]
name = "pathspec"
version = "1.1.1"
@@ -2206,75 +2431,54 @@ wheels = [
[[package]]
name = "pillow"
-version = "12.2.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3a/aa/d0b28e1c811cd4d5f5c2bfe2e022292bd255ae5744a3b9ac7d6c8f72dd75/pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f", size = 5354355, upload-time = "2026-04-01T14:42:15.402Z" },
- { url = "https://files.pythonhosted.org/packages/27/8e/1d5b39b8ae2bd7650d0c7b6abb9602d16043ead9ebbfef4bc4047454da2a/pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97", size = 4695871, upload-time = "2026-04-01T14:42:18.234Z" },
- { url = "https://files.pythonhosted.org/packages/f0/c5/dcb7a6ca6b7d3be41a76958e90018d56c8462166b3ef223150360850c8da/pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff", size = 6269734, upload-time = "2026-04-01T14:42:20.608Z" },
- { url = "https://files.pythonhosted.org/packages/ea/f1/aa1bb13b2f4eba914e9637893c73f2af8e48d7d4023b9d3750d4c5eb2d0c/pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec", size = 8076080, upload-time = "2026-04-01T14:42:23.095Z" },
- { url = "https://files.pythonhosted.org/packages/a1/2a/8c79d6a53169937784604a8ae8d77e45888c41537f7f6f65ed1f407fe66d/pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136", size = 6382236, upload-time = "2026-04-01T14:42:25.82Z" },
- { url = "https://files.pythonhosted.org/packages/b5/42/bbcb6051030e1e421d103ce7a8ecadf837aa2f39b8f82ef1a8d37c3d4ebc/pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c", size = 7070220, upload-time = "2026-04-01T14:42:28.68Z" },
- { url = "https://files.pythonhosted.org/packages/3f/e1/c2a7d6dd8cfa6b231227da096fd2d58754bab3603b9d73bf609d3c18b64f/pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3", size = 6493124, upload-time = "2026-04-01T14:42:31.579Z" },
- { url = "https://files.pythonhosted.org/packages/5f/41/7c8617da5d32e1d2f026e509484fdb6f3ad7efaef1749a0c1928adbb099e/pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa", size = 7194324, upload-time = "2026-04-01T14:42:34.615Z" },
- { url = "https://files.pythonhosted.org/packages/2d/de/a777627e19fd6d62f84070ee1521adde5eeda4855b5cf60fe0b149118bca/pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032", size = 6376363, upload-time = "2026-04-01T14:42:37.19Z" },
- { url = "https://files.pythonhosted.org/packages/e7/34/fc4cb5204896465842767b96d250c08410f01f2f28afc43b257de842eed5/pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5", size = 7083523, upload-time = "2026-04-01T14:42:39.62Z" },
- { url = "https://files.pythonhosted.org/packages/2d/a0/32852d36bc7709f14dc3f64f929a275e958ad8c19a6deba9610d458e28b3/pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024", size = 2463318, upload-time = "2026-04-01T14:42:42.063Z" },
- { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" },
- { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" },
- { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" },
- { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" },
- { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" },
- { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" },
- { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" },
- { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" },
- { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" },
- { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" },
- { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" },
- { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" },
- { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" },
- { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" },
- { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" },
- { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" },
- { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" },
- { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" },
- { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" },
- { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" },
- { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" },
- { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" },
- { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" },
- { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" },
- { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" },
- { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" },
- { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" },
- { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" },
- { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" },
- { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" },
- { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" },
- { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" },
- { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" },
- { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" },
- { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" },
- { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" },
- { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" },
- { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" },
- { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" },
- { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" },
- { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" },
- { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" },
- { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" },
- { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" },
- { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" },
- { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" },
- { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" },
- { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" },
- { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" },
- { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" },
- { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" },
- { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" },
- { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" },
- { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" },
+version = "12.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" },
+ { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" },
+ { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" },
+ { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" },
+ { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" },
+ { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" },
+ { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" },
+ { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" },
+ { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" },
+ { url = "https://files.pythonhosted.org/packages/86/a5/444817a4d4c4c2417df00513086ca196f388d8f9ef40c2e4ccd1ad1af54b/pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b", size = 6472232, upload-time = "2026-07-01T11:53:59.767Z" },
+ { url = "https://files.pythonhosted.org/packages/63/c6/4bad1b18d132a50b27e1365e1ab163616f7a5bb56d330f66f9d1d9d4f9d4/pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a", size = 7233653, upload-time = "2026-07-01T11:54:02.066Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/16/00f91ab7760dc842f5aad55217e80fc4a7067a0604535249bc8a2d6d9870/pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26", size = 2568195, upload-time = "2026-07-01T11:54:04.622Z" },
+ { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" },
+ { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" },
+ { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" },
+ { url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" },
+ { url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" },
+ { url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" },
+ { url = "https://files.pythonhosted.org/packages/9d/ac/31fb64e1e7efb5a4b50cd3d92049ba89ac6e4d8d3bb6a74e15048ca3353e/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89", size = 4161684, upload-time = "2026-07-01T11:54:25.934Z" },
+ { url = "https://files.pythonhosted.org/packages/87/b4/9805e23d2b4d77842b468513841fda254ee42f0289d25088340e4ff46e2d/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace", size = 4255487, upload-time = "2026-07-01T11:54:27.935Z" },
+ { url = "https://files.pythonhosted.org/packages/df/39/ecf519435a200c693fe053a6ee4d835b41cf963a4dfc2551c4e637cb2a71/pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec", size = 3696433, upload-time = "2026-07-01T11:54:29.813Z" },
+ { url = "https://files.pythonhosted.org/packages/42/92/2fc3ffad878ae8dd5469ec1bc8eb83b71f48e13efdf68f02709003982a32/pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66", size = 5345889, upload-time = "2026-07-01T11:54:31.97Z" },
+ { url = "https://files.pythonhosted.org/packages/10/76/8803c13605b763d33d156c4678fc77f8443389c0c51c8aef707bb02015f4/pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35", size = 4780109, upload-time = "2026-07-01T11:54:34.026Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/01/e18aff37cb0b4aac47ac90f016d347a49aca667ef97f190b06ac2aabc928/pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65", size = 6263736, upload-time = "2026-07-01T11:54:36.131Z" },
+ { url = "https://files.pythonhosted.org/packages/f7/62/de5bdd77d935331f4f802edc11e4d82950f642caad6cb2f949837b8560e2/pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3", size = 6937129, upload-time = "2026-07-01T11:54:38.216Z" },
+ { url = "https://files.pythonhosted.org/packages/70/4d/105627a13300c5e0df1d174230b32fd1273062c96f7745fd552b945d1e1d/pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a", size = 6339562, upload-time = "2026-07-01T11:54:40.354Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/1d/f13de01a553988ab895ba1c722e06cf3144d4f57656fd5b81b6d881f1179/pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e", size = 7049439, upload-time = "2026-07-01T11:54:42.489Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/f9/066794cca041b969964f779ee5fa66a9498bbf34248ac39c5d7954e4198f/pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f", size = 6473287, upload-time = "2026-07-01T11:54:44.9Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/9b/7a58e61d62be561da3a356fe2384d4059a6345fc130e23ef1c36a5b81d24/pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8", size = 7239691, upload-time = "2026-07-01T11:54:47.141Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/b0/c4ed4f0ef8f8fa5ee8351537db6650bb8189f7e118842978dd6589065692/pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b", size = 2568185, upload-time = "2026-07-01T11:54:49.137Z" },
+ { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" },
+ { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" },
+ { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" },
+ { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" },
+ { url = "https://files.pythonhosted.org/packages/36/54/0169bc772ec491108b62f644f8ecf1fe5d8ae5ebafde2ee2142210166903/pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a", size = 7231786, upload-time = "2026-07-01T11:56:35.046Z" },
]
[[package]]
@@ -2380,6 +2584,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" },
]
+[[package]]
+name = "protego"
+version = "0.6.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/7d/1b/6b0ee60bb1561843bfc62f5c7c3cb1ef6147b47e829a5fd6b7fcd2752471/protego-0.6.2.tar.gz", hash = "sha256:88ff004544ce44e61269cc6f8735f7837d12e09bb77619fc94fbb26b72e5d137", size = 3137854, upload-time = "2026-06-25T09:33:16.361Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/61/10/cbd3c06603bb8b3e0e871df24ee793a6e3b53d8c4cc8763f1b8b936649aa/protego-0.6.2-py3-none-any.whl", hash = "sha256:714de21d82527c9be900066c3211b266985dd6a19b6e70c57e033fc1a589f3ff", size = 10296, upload-time = "2026-06-25T09:33:14.771Z" },
+]
+
[[package]]
name = "protobuf"
version = "6.33.6"
@@ -2395,6 +2608,90 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c4/72/02445137af02769918a93807b2b7890047c32bfb9f90371cbc12688819eb/protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901", size = 170656, upload-time = "2026-03-18T19:04:59.826Z" },
]
+[[package]]
+name = "psycopg"
+version = "3.3.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
+ { name = "tzdata", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" },
+]
+
+[package.optional-dependencies]
+binary = [
+ { name = "psycopg-binary", marker = "implementation_name != 'pypy'" },
+]
+pool = [
+ { name = "psycopg-pool" },
+]
+
+[[package]]
+name = "psycopg-binary"
+version = "3.3.4"
+source = { registry = "https://pypi.org/simple" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b7/bf/70d8a60488f9955cbbcd538beae44d56bb2f1d19e673b72788f2d343ff55/psycopg_binary-3.3.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b7bfff1ca23732b488cbca3076fc11bc98d520ee122514fdb17a8e20d3338f5a", size = 4609750, upload-time = "2026-05-01T23:24:20.06Z" },
+ { url = "https://files.pythonhosted.org/packages/db/b0/29e98ba210c9dbc75a6dc91e3f99b9e06ea901a62ca95804e02a1ae13e6b/psycopg_binary-3.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32a6fbf8481e3a370d0d72b860d35948a693cb01281da217f7b2f307636e591a", size = 4676700, upload-time = "2026-05-01T23:25:21.727Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/ab/3df087b3c12bf74e47c08204172b2fabb5a144679110d5c7ad12d9201323/psycopg_binary-3.3.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bdef84570ebbce1d42b4e7ea952d21c414c5f118ad02fee00c5625f35e134429", size = 5496319, upload-time = "2026-05-01T23:25:28.271Z" },
+ { url = "https://files.pythonhosted.org/packages/87/9a/f088207b4cd6772f9e0d8a91807e79fa2458d4eb9eb1ae406c68415f2bec/psycopg_binary-3.3.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa1cbc10768a796c96d3243656016bf4e337c81c71097270bb7b0ad6210d9765", size = 5171906, upload-time = "2026-05-01T23:25:34.004Z" },
+ { url = "https://files.pythonhosted.org/packages/48/45/4523a857f253871d75c22e1c2e79fd47e599e736bcba1bad58d83e24be02/psycopg_binary-3.3.4-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf7f73a4a792bc5db58a4b385d8a1467e8d468f7548702fb0ed1e9b7501b1c13", size = 6762621, upload-time = "2026-05-01T23:25:41.392Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/d1/925bf776503345bef428e6c45fb017d0139ddbe0e211814b585c4253dca8/psycopg_binary-3.3.4-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7b4d40c153fa352ab3cca530f3a0baedf7621b2ebcbd7f084009522c21788fc", size = 5006319, upload-time = "2026-05-01T23:25:51.419Z" },
+ { url = "https://files.pythonhosted.org/packages/6f/aa/99727337206fbba357ca084bf4ea8b29dc986f61842a2685859af61416db/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9b1c2533af01cd7648378599f82b0b8ae32f293296e6eec5753a625bc97ef28", size = 4535388, upload-time = "2026-05-01T23:25:57.957Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/a4/567ba2c37d19d8c2f63d836385dfd2495aa5897bbee6cfab104d9ee58624/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad3bc94054876155549fdaedf4a46d1ec69d39a5bcee377148afe498e84c4b8e", size = 4224544, upload-time = "2026-05-01T23:26:03.832Z" },
+ { url = "https://files.pythonhosted.org/packages/b7/23/86457f5a82731685d7701de7bfaa5eb783dd1fecbf875321897d9d9ce33a/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb4eed2079c01a4850bf467deacfab56d356d4225040170af03dc9958321242d", size = 3956282, upload-time = "2026-05-01T23:26:09.983Z" },
+ { url = "https://files.pythonhosted.org/packages/a7/d8/249456df16d47de082abd9b73bce8ccdeb0293eb12e590f9150c7cbdb788/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f80e3f2b5331dbbf0901bcb658056c03eeb2c1ef31d774afb0d61598b242e744", size = 4261736, upload-time = "2026-05-01T23:26:16.798Z" },
+ { url = "https://files.pythonhosted.org/packages/15/6b/c4abe228acafd8a385c1fb615d4f1e3c9b8ad7a4e4f0e84118ba3ffeed9c/psycopg_binary-3.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:574ea21a9651958f1535c5a1c649c7409e9168bcbffa29a3f2f961f58b322949", size = 3570620, upload-time = "2026-05-01T23:26:22.655Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/82/df3312c0ca083d5b43b352f27d4dd8b1e614bd334473074715d9e0000da4/psycopg_binary-3.3.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:612a627d733f695b1de1f9b4bd511c15f999a5d8b915d444bbd7dd71cf3370da", size = 4609813, upload-time = "2026-05-01T23:26:30.612Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/b5/d74d542458d3e8ac0571d8a88f57ca369999b9a82f4fa528052d0d7d3e4c/psycopg_binary-3.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:13a7f380824c35896dcac7fe0f61440f7ca49d6dc73f3c13a9a4471e6a3b302e", size = 4676799, upload-time = "2026-05-01T23:26:38.475Z" },
+ { url = "https://files.pythonhosted.org/packages/09/67/06bab9c60671999f4c6ceff1b334f3ac1f9fc5789eb467c714623ea21de9/psycopg_binary-3.3.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:276904e3452d6a23d474ef9a21eee19f20eed3d53ddd2576af033827e0ba0992", size = 5497050, upload-time = "2026-05-01T23:26:47.061Z" },
+ { url = "https://files.pythonhosted.org/packages/72/9b/023433e2b20f970de1e22d29132a95281277646da0b2e2879dd4ee94b8c1/psycopg_binary-3.3.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ab8cca8ef8fb1ccf5b048ae5bd78ba55b9e4b5d472e3ce5ca39ff4d2a9c249e4", size = 5172428, upload-time = "2026-05-01T23:26:56.708Z" },
+ { url = "https://files.pythonhosted.org/packages/08/cd/ae16da8fde228a38b2fe9269bbc13cf89e0186173f2265600f02d6a71e64/psycopg_binary-3.3.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7465bfe6087d2d5b42d4c53b9b11ca9f218e477317a4a162a10e3c19e984ba8e", size = 6762746, upload-time = "2026-05-01T23:27:07.023Z" },
+ { url = "https://files.pythonhosted.org/packages/4f/81/0ba09fa5f5f88779093a2541a8e02489825721f258ab88058b11d68b3eb5/psycopg_binary-3.3.4-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:22cdbf5f91ef7bb91fe0c5757e1962d3127a8010256eefd9c61fcaf441802097", size = 5006033, upload-time = "2026-05-01T23:27:12.221Z" },
+ { url = "https://files.pythonhosted.org/packages/73/6a/629136040cc3497adb442a305710b5913f2a754d4630fc3d3717c4c0df65/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e2631da29253a98bd496e6c4813b24e09a4fe3fb2a9e88513305d6f8747cce95", size = 4534175, upload-time = "2026-05-01T23:27:18.248Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/32/1027f843c6dc2d5d51960ee62cc0c2cf755a4c39455aff1371173edbef7d/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7f7668f30b9dd5163197e5cbf4e0efd54e00f0a859cc566ce56cfc31f4054839", size = 4224203, upload-time = "2026-05-01T23:27:24.3Z" },
+ { url = "https://files.pythonhosted.org/packages/0b/e1/380a724d9093c74adb14d4fce920ea8327838abb61f760b1448586b14a8e/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:cffc3408d77a27973f33e5d909b624cce683db5fc25964b02fe0aae7886c1007", size = 3954509, upload-time = "2026-05-01T23:27:30.815Z" },
+ { url = "https://files.pythonhosted.org/packages/db/cd/895893ae575a09c97ccfd5def070d88993d955ef34df45a881fd5ff506d6/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0579252a1202cd73e4da137a1426e2dae993ae44e757605344282af3a082848c", size = 4259551, upload-time = "2026-05-01T23:27:38.828Z" },
+ { url = "https://files.pythonhosted.org/packages/dd/c6/2330a20794e37a3ec609ef2fd8522919ec7a4395a1abf979a8e2d1775cd5/psycopg_binary-3.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:41f2ec0fea529832982bcb6c9415de3c86264ebe562b77a467c0fbcd7efbba8d", size = 3572054, upload-time = "2026-05-01T23:27:45.455Z" },
+ { url = "https://files.pythonhosted.org/packages/95/7d/03818e13ba7f36de93573c93ee3482006d3dfa8b0f8d28df511bad0a1a92/psycopg_binary-3.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089", size = 4591122, upload-time = "2026-05-01T23:27:56.162Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/b9/11b341edf8d54e2694726b273fe9652b254d989f4f63e3ac6816ad6b55f4/psycopg_binary-3.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578", size = 4669943, upload-time = "2026-05-01T23:28:04.522Z" },
+ { url = "https://files.pythonhosted.org/packages/8b/18/4665bacd65e7865b4372fcd8abb8b9186ada4b0025f8c2ca691b364a556c/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9", size = 5469697, upload-time = "2026-05-01T23:28:11.337Z" },
+ { url = "https://files.pythonhosted.org/packages/7c/b1/b83136c6e510593d9b0c759ba5384337bc4ad82d19fda675adc4b2703c84/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d", size = 5152995, upload-time = "2026-05-01T23:28:20.529Z" },
+ { url = "https://files.pythonhosted.org/packages/67/8d/a9821e2a648afe6091989929982a3b0f00b2631a859cb81379728f08fb75/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b", size = 6738180, upload-time = "2026-05-01T23:28:30.654Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/58/2e349e8d23905dc2317b80ac65f48fb6f821a4777a4e994a60da91c4850f/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070", size = 4978828, upload-time = "2026-05-01T23:28:37.277Z" },
+ { url = "https://files.pythonhosted.org/packages/45/48/57b00d03b4721878326122a1f1e6b0a90b85bcaec56b5b2f8ea6cfa45235/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68", size = 4509757, upload-time = "2026-05-01T23:28:43.078Z" },
+ { url = "https://files.pythonhosted.org/packages/25/37/33b47d8c007df69aec500df5889767c4d313748e8e9e27a2fef8a6dabcee/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16", size = 4190546, upload-time = "2026-05-01T23:28:50.016Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/c6/32b0835dbc2122617902b649d76a91c1e75406e76bf3d595b0c3bb5ffad6/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652", size = 3926197, upload-time = "2026-05-01T23:28:55.55Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/68/d190ef0c0c5b16ded07831dabc8ddd412f4cdab07ec6e30ed38d9bda0e1f/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e", size = 4236627, upload-time = "2026-05-01T23:29:05.336Z" },
+ { url = "https://files.pythonhosted.org/packages/25/8f/81dcbc2e8454b74d14881275ea45f00791052dac531a9fa8be1730d1685b/psycopg_binary-3.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4", size = 3560782, upload-time = "2026-05-01T23:29:11.967Z" },
+ { url = "https://files.pythonhosted.org/packages/09/43/13e9c406fbbf354580476e248a16b64802a376873ebe6339e30bb655572d/psycopg_binary-3.3.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7", size = 4590377, upload-time = "2026-05-01T23:29:18.782Z" },
+ { url = "https://files.pythonhosted.org/packages/22/be/2923cd7c3683e7afdecf4f10796a18de02f5c5ddc0969aa2ad0a8cdd3bbd/psycopg_binary-3.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31", size = 4669023, upload-time = "2026-05-01T23:29:25.884Z" },
+ { url = "https://files.pythonhosted.org/packages/96/a0/2c913d6fe13d6a8bd13597d36739bf47af063ad9399e402cfecab16f3c1e/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70", size = 5467423, upload-time = "2026-05-01T23:29:33.416Z" },
+ { url = "https://files.pythonhosted.org/packages/e7/38/205d10bc1ad0df4a21c5c51659126bd3ea0ef98fcad1e852f78c249bb9c3/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3", size = 5151137, upload-time = "2026-05-01T23:29:42.013Z" },
+ { url = "https://files.pythonhosted.org/packages/36/fc/f0381ddcd45eff3bb70dbca6823a996048d7f507b2ec3fc92c6fabc0fe87/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c", size = 6736671, upload-time = "2026-05-01T23:29:51.626Z" },
+ { url = "https://files.pythonhosted.org/packages/95/40/fa545ae152c24327651e5624e4902121e808270be36c10b12e9939be09bc/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae", size = 4979601, upload-time = "2026-05-01T23:29:56.961Z" },
+ { url = "https://files.pythonhosted.org/packages/86/e4/2f8a47ee97f90cd2b933d0463081d35631ff419de2b8c984a5f369857de0/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc", size = 4510513, upload-time = "2026-05-01T23:30:07.243Z" },
+ { url = "https://files.pythonhosted.org/packages/0e/0e/94e842ff4a7f98ed162580ca2e8b8864b28c1e0350f2443f8ee47f821167/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf", size = 4187243, upload-time = "2026-05-01T23:30:15.352Z" },
+ { url = "https://files.pythonhosted.org/packages/d0/83/fc6c174b672e29b7de996ea77b6cbddf46c891751c3355f6974292baa6b4/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260", size = 3927347, upload-time = "2026-05-01T23:30:21.186Z" },
+ { url = "https://files.pythonhosted.org/packages/e9/65/768364d4a97a15b1a7f47ba52688c1686f22941d8332a8398cefc468e25f/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf", size = 4236393, upload-time = "2026-05-01T23:30:26.211Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/3b/218efbc9e645becd80cdf651acda05f85cfe546b7a9c0458c7cbc8fe1f74/psycopg_binary-3.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38", size = 3564592, upload-time = "2026-05-01T23:30:31.764Z" },
+]
+
+[[package]]
+name = "psycopg-pool"
+version = "3.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/90/82/7a23d26039827ecd4ebe93905651029ddd307c5182ad59296dfb6f67b528/psycopg_pool-3.3.1.tar.gz", hash = "sha256:b10b10b7a175d5cc1592147dc5b7eec8a9e0834eb3ed2c4a92c858e2f51eb63c", size = 31661, upload-time = "2026-05-01T23:31:59.809Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/37/ed/89c2c620af0e1660354cd8aabf9f5b21f911597ce22acb37c805d6c86bc8/psycopg_pool-3.3.1-py3-none-any.whl", hash = "sha256:2af5b432941c4c9ad5c87b3fa410aec910ec8f7c122855897983a06c45f2e4b5", size = 40023, upload-time = "2026-05-01T23:31:53.136Z" },
+]
+
[[package]]
name = "py"
version = "1.11.0"
@@ -2560,16 +2857,16 @@ wheels = [
[[package]]
name = "pydantic-settings"
-version = "2.14.1"
+version = "2.14.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "python-dotenv" },
{ name = "typing-inspection" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/07/60/1d1e59c9c90d54591469ada7d268251f71c24bdb765f1a8a832cee8c6653/pydantic_settings-2.14.1.tar.gz", hash = "sha256:e874d3bec7e787b0c9958277956ed9b4dd5de6a80e162188fdaff7c5e26fd5fa", size = 235551, upload-time = "2026-05-08T13:40:06.542Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/ae/8d/f1af3832f5e6eb13ba94ee809e72b8ecb5eef226d27ee0bef7d963d943c7/pydantic_settings-2.14.1-py3-none-any.whl", hash = "sha256:6e3c7edfd8277687cdc598f56e5cff0e9bfff0910a3749deaa8d4401c3a2b9de", size = 60964, upload-time = "2026-05-08T13:40:04.958Z" },
+ { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" },
]
[[package]]
@@ -2593,6 +2890,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a9/cd/e0eda602060f9dc99068f8e54490812d9d34ebb134043ff0ae594cf721a4/pydata_sphinx_theme-0.18.0-py3-none-any.whl", hash = "sha256:fbe5401f26642d487e3c5b6dfcbf69b3b1d579e80dcc479a429632abe0a13929", size = 6200747, upload-time = "2026-05-20T08:32:26.646Z" },
]
+[[package]]
+name = "pydispatcher"
+version = "2.0.7"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/21/db/030d0700ae90d2f9d52c2f3c1f864881e19cef8cba3b0a08759c8494c19c/PyDispatcher-2.0.7.tar.gz", hash = "sha256:b777c6ad080dc1bad74a4c29d6a46914fa6701ac70f94b0d66fbcfde62f5be31", size = 38891, upload-time = "2023-02-17T20:11:13.106Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/66/0e/9ee7bc0b48ec45d93b302fa2d787830dca4dc454d31a237faa5815995988/PyDispatcher-2.0.7-py3-none-any.whl", hash = "sha256:96543bea04115ffde08f851e1d45cacbfd1ee866ac42127d9b476dc5aefa7de0", size = 12040, upload-time = "2023-02-17T20:11:11.991Z" },
+]
+
[[package]]
name = "pygments"
version = "2.20.0"
@@ -2619,6 +2925,19 @@ crypto = [
{ name = "cryptography" },
]
+[[package]]
+name = "pyopenssl"
+version = "26.3.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cryptography" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/74/b7/da07bae88f5a9506b4def6f2f4903cf4c3b8831e560dba8fa18ca08f758f/pyopenssl-26.3.0.tar.gz", hash = "sha256:589de7fae1c9ea670d18422ed00fc04da787bbde8e1454aea872aa57b49ad341", size = 182024, upload-time = "2026-06-12T20:28:07.458Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/18/1dd71c9b43192ab83f1d531ad6002dc81108ac36c475f79fb7a295abe2f4/pyopenssl-26.3.0-py3-none-any.whl", hash = "sha256:46367f8f66b92271e6d218da9c87607e1ef5a0bc5c8dea5bb3db82f395c385a3", size = 56008, upload-time = "2026-06-12T20:28:05.999Z" },
+]
+
[[package]]
name = "pypdfium2"
version = "5.8.0"
@@ -2648,6 +2967,12 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/fc/7a/f3dcefe6ee7389aad3ca1488c177e8fbf978206de21c7a99ccf487ea38ab/pypdfium2-5.8.0-py3-none-win_arm64.whl", hash = "sha256:3f17ed97ae8a5a1705301ca93af256a5b02f9009dee4e99c5e175831d46ebd7c", size = 3548362, upload-time = "2026-05-04T17:39:42.304Z" },
]
+[[package]]
+name = "pypydispatcher"
+version = "2.1.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d5/7b/65f55513d3c769fd677f90032d8d8703e3dc17e88a41b6074d2177548bca/PyPyDispatcher-2.1.2.tar.gz", hash = "sha256:b6bec5dfcff9d2535bca2b23c80eae367b1ac250a645106948d315fcfa9130f2", size = 23224, upload-time = "2017-07-03T14:20:51.806Z" }
+
[[package]]
name = "pytest"
version = "9.0.3"
@@ -2850,30 +3175,24 @@ wheels = [
]
[[package]]
-name = "readabilipy"
-version = "0.3.0"
+name = "queuelib"
+version = "1.9.0"
source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "beautifulsoup4" },
- { name = "html5lib" },
- { name = "lxml" },
- { name = "regex" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/b8/e4/260a202516886c2e0cc6e6ae96d1f491792d829098886d9529a2439fbe8e/readabilipy-0.3.0.tar.gz", hash = "sha256:e13313771216953935ac031db4234bdb9725413534bfb3c19dbd6caab0887ae0", size = 35491, upload-time = "2024-12-02T23:03:02.311Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/76/f3/d80ab8c7c91b8c42d9a2aa4dd97a8be1321e7b26000c2675b75e641d958c/queuelib-1.9.0.tar.gz", hash = "sha256:b12fea79fd8c1dd23e212b1f3db58003b773949801d4f4e6f34d882467d4a192", size = 11729, upload-time = "2026-01-29T11:19:37.065Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/dd/46/8a640c6de1a6c6af971f858b2fb178ca5e1db91f223d8ba5f40efe1491e5/readabilipy-0.3.0-py3-none-any.whl", hash = "sha256:d106da0fad11d5fdfcde21f5c5385556bfa8ff0258483037d39ea6b1d6db3943", size = 22158, upload-time = "2024-12-02T23:03:00.438Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/1c/8df7b461497b42fcc1e7c44529201975ec77b0e1ebecd00df4b1f096c1d4/queuelib-1.9.0-py3-none-any.whl", hash = "sha256:c5fd3bebf2c924446fa94fca6b72e81168f79cf4c2a9143b8b26f266a423fcf3", size = 13585, upload-time = "2026-01-29T11:19:35.616Z" },
]
[[package]]
name = "redis"
-version = "7.4.0"
+version = "6.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "async-timeout", marker = "python_full_version < '3.11.3'" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/7b/7f/3759b1d0d72b7c92f0d70ffd9dc962b7b7b5ee74e135f9d7d8ab06b8a318/redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad", size = 4943913, upload-time = "2026-03-24T09:14:37.53Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/0d/d6/e8b92798a5bd67d659d51a18170e91c16ac3b59738d91894651ee255ed49/redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", size = 4647399, upload-time = "2025-08-07T08:10:11.441Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/74/3a/95deec7db1eb53979973ebd156f3369a72732208d1391cd2e5d127062a32/redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec", size = 409772, upload-time = "2026-03-24T09:14:35.968Z" },
+ { 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]]
@@ -2994,6 +3313,18 @@ 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]]
+name = "requests-file"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "requests" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3c/f8/5dc70102e4d337063452c82e1f0d95e39abfe67aa222ed8a5ddeb9df8de8/requests_file-3.0.1.tar.gz", hash = "sha256:f14243d7796c588f3521bd423c5dea2ee4cc730e54a3cac9574d78aca1272576", size = 6967, upload-time = "2025-10-20T18:56:42.279Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e1/d5/de8f089119205a09da657ed4784c584ede8381a0ce6821212a6d4ca47054/requests_file-3.0.1-py2.py3-none-any.whl", hash = "sha256:d0f5eb94353986d998f80ac63c7f146a307728be051d4d1cd390dbdb59c10fa2", size = 4514, upload-time = "2025-10-20T18:56:41.184Z" },
+]
+
[[package]]
name = "requests-oauthlib"
version = "2.0.0"
@@ -3173,6 +3504,60 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/62/d5/bc97ff895ec35cf3925d4bd60f3b39d822f377a446906ec9bcc87405e59b/ruff-0.15.14-py3-none-win_arm64.whl", hash = "sha256:ff47b90a9ef6a40c9e2f3b479c1fb78531adf055b94c1eba0a7ba04b31951826", size = 11208607, upload-time = "2026-05-21T14:34:26.525Z" },
]
+[[package]]
+name = "s3transfer"
+version = "0.19.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "botocore" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/76/43/35e4d8aa320bffe8287fe8f65f578fa2d2db0a64212f0e710dce58267854/s3transfer-0.19.2.tar.gz", hash = "sha256:ba0309fd86be3c27dbf78cdd813c13c5e1df16e5874b99d2535ebbdfb9892993", size = 165592, upload-time = "2026-07-22T19:30:44.432Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/bc/e7/5c595c75e9f41a44f30e526eda465ea0b4eec93470e074e4a111b253f13a/s3transfer-0.19.2-py3-none-any.whl", hash = "sha256:d8168eccca828cbb2cd573675333f3bddd254313a9c42494b84c76b539e8ba25", size = 90216, upload-time = "2026-07-22T19:30:43.251Z" },
+]
+
+[[package]]
+name = "scrapy"
+version = "2.17.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "cryptography" },
+ { name = "cssselect" },
+ { name = "defusedxml" },
+ { name = "itemadapter" },
+ { name = "itemloaders" },
+ { name = "lxml" },
+ { name = "packaging" },
+ { name = "parsel" },
+ { name = "protego" },
+ { name = "pydispatcher", marker = "platform_python_implementation == 'CPython'" },
+ { name = "pyopenssl" },
+ { name = "pypydispatcher", marker = "platform_python_implementation == 'PyPy'" },
+ { name = "queuelib" },
+ { name = "service-identity" },
+ { name = "tldextract" },
+ { name = "twisted" },
+ { name = "w3lib" },
+ { name = "zope-interface" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/35/9f/9800513193aacb44825f0b9a75e4e6d4a0c416e9ed23ca3aac7374d03d17/scrapy-2.17.0.tar.gz", hash = "sha256:b536d14166b05e2183b19ae105a7af849cd14d4c1f70d3009d9b1828c0ab3d92", size = 1312077, upload-time = "2026-07-07T10:27:43.298Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/71/e8/30fbfcb45b35da9e24c6f1ae193688dc834cef3fd576a41d3a08ef771125/scrapy-2.17.0-py3-none-any.whl", hash = "sha256:a650a59e9425e7e4b4d59083f858df34ec9a5a8292b3e35671d444fb56fe5085", size = 350445, upload-time = "2026-07-07T10:27:41.59Z" },
+]
+
+[[package]]
+name = "service-identity"
+version = "26.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "cryptography" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/61/87/ad52e2c582c0f0e7f0a1b86950494c38d67422dc0f5ed9044a5fb9569a49/service_identity-26.1.0.tar.gz", hash = "sha256:6358c52882c96e66ac4a55eb3a72c7dd4a70763f8cc6fa4e70abde2656f4bf3b", size = 42898, upload-time = "2026-05-30T12:04:55.184Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/93/eb/2433e1af4ff903499144de4846569fb3300b816179ae99a03c2f011b666a/service_identity-26.1.0-py3-none-any.whl", hash = "sha256:68c32dadbb69135fb951077677e07cd7f6031020f3a8c8f47a28cda8a0742118", size = 11370, upload-time = "2026-05-30T12:04:53.911Z" },
+]
+
[[package]]
name = "sgmllib3k"
version = "1.0.0"
@@ -3226,11 +3611,11 @@ wheels = [
[[package]]
name = "soupsieve"
-version = "2.8.3"
+version = "2.9.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/d9/38/e12680bbe6b4f8f3d17adcaf38d26850aa756c85cf4a80e79fc12a018fe8/soupsieve-2.9.1.tar.gz", hash = "sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba", size = 122261, upload-time = "2026-07-21T16:57:17.452Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/2c/437fe806897c2d6cfdc3ee43a18da8bf8e568530a4ae9bac781541ca9896/soupsieve-2.9.1-py3-none-any.whl", hash = "sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c", size = 37404, upload-time = "2026-07-21T16:57:16.421Z" },
]
[[package]]
@@ -3463,6 +3848,30 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/4d/bc07d1f1635d4897a202acc0ae11c2886eaa7325c359ba4741b47bf8e225/tiktoken-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6c43a675ca14f6f2749ba7f12075d37456015a24b859f2517b9beb4ef30807ec", size = 873820, upload-time = "2026-05-15T04:50:59.528Z" },
]
+[[package]]
+name = "tld"
+version = "0.13.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/5c/5d/76b4383ac4e5b5e254e50c09807b3e13820bed6d6c11cd540264988d6802/tld-0.13.2.tar.gz", hash = "sha256:d983fa92b9d717400742fca844e29d5e18271079c7bcfabf66d01b39b4a14345", size = 467175, upload-time = "2026-03-06T23:50:34.498Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9e/90/39a85a4b63c84213e78b3c17d22e1bf45328acf8ebb33ef93be30d0a3911/tld-0.13.2-py2.py3-none-any.whl", hash = "sha256:9b8fdbdb880e7ba65b216a4937f2c94c49a7226723783d5838fc958ac76f4e0c", size = 296743, upload-time = "2026-03-06T23:50:32.465Z" },
+]
+
+[[package]]
+name = "tldextract"
+version = "5.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "filelock" },
+ { name = "idna" },
+ { name = "requests" },
+ { name = "requests-file" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/65/7b/644fbbb49564a6cb124a8582013315a41148dba2f72209bba14a84242bf0/tldextract-5.3.1.tar.gz", hash = "sha256:a72756ca170b2510315076383ea2993478f7da6f897eef1f4a5400735d5057fb", size = 126105, upload-time = "2025-12-28T23:58:05.532Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/6d/42/0e49d6d0aac449ca71952ec5bae764af009754fcb2e76a5cc097543747b3/tldextract-5.3.1-py3-none-any.whl", hash = "sha256:6bfe36d518de569c572062b788e16a659ccaceffc486d243af0484e8ecf432d9", size = 105886, upload-time = "2025-12-28T23:58:04.071Z" },
+]
+
[[package]]
name = "tokenizers"
version = "0.23.1"
@@ -3538,6 +3947,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" },
]
+[[package]]
+name = "trafilatura"
+version = "2.1.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "courlan" },
+ { name = "htmldate" },
+ { name = "justext" },
+ { name = "lxml" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/e8/19/24833e905df2d80e3bb67424f95febcc17709a1f61a522120bc438afca70/trafilatura-2.1.0.tar.gz", hash = "sha256:f689e2116fc89c7bc0b9a296d01dcfe2eb0b5455f8c371a77dc0db1f06a05643", size = 263876, upload-time = "2026-06-07T17:43:31.829Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0e/78/4ad99d79aee2784f49f20fd0a29058ce4c032fe4439047924c43521cd211/trafilatura-2.1.0-py3-none-any.whl", hash = "sha256:0eded5207a806445ddebbe36eae30b9035fe6a2f233c36f6fe82663fca8b9d30", size = 134600, upload-time = "2026-06-07T17:43:28.404Z" },
+]
+
[[package]]
name = "tree-sitter"
version = "0.25.2"
@@ -3729,6 +4156,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/e4/81f9a935789233cf412a0ed5fe04c883841d2c8fb0b7e075958a35c65032/tree_sitter_typescript-0.23.2-cp39-abi3-win_arm64.whl", hash = "sha256:05db58f70b95ef0ea126db5560f3775692f609589ed6f8dd0af84b7f19f1cbb7", size = 274052, upload-time = "2024-11-11T02:36:09.514Z" },
]
+[[package]]
+name = "twisted"
+version = "26.4.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "attrs" },
+ { name = "automat" },
+ { name = "constantly" },
+ { name = "hyperlink" },
+ { name = "incremental" },
+ { name = "typing-extensions" },
+ { name = "zope-interface" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/db/97/6e9beb1e78247ae6dc34114f27d538cf2cb183c4afcd3609dfdf2b0439c8/twisted-26.4.0.tar.gz", hash = "sha256:dbfd0fe1ee409d0243fdd7a6a6ff14f4948cec1fd78e0376291f805e1501fae9", size = 3575095, upload-time = "2026-05-11T11:24:51.861Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/a6/57/bcf4e2370dd218c9aa68a9140a65d86729c73f1d529f7e94786c2766fc72/twisted-26.4.0-py3-none-any.whl", hash = "sha256:dc25ea0ebf6511c24f03232ee9f4afa54b291c5d897990e3a39cc4d14a1ef4c0", size = 3230362, upload-time = "2026-05-11T11:24:49.5Z" },
+]
+
[[package]]
name = "typer"
version = "0.25.1"
@@ -3893,6 +4338,15 @@ ark = [
{ name = "pydantic" },
]
+[[package]]
+name = "w3lib"
+version = "2.4.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c0/91/b2eb59c2cf243de5de1e91c963655df78c015509f51297685a8c86a27b8c/w3lib-2.4.1.tar.gz", hash = "sha256:8dd69ee39ff6398d708c793abc779c334a69bac7cee1cdf71736c669ed6be864", size = 48494, upload-time = "2026-03-20T09:50:27.477Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/66/c3/f8b216cbd742e5b84c40f045204c764ccb7524d2aeab021054ec69446b0a/w3lib-2.4.1-py3-none-any.whl", hash = "sha256:40930132907e68de906a5b89331ab8c8ff4f01bd35b5539ef7896017d814138d", size = 21695, upload-time = "2026-03-20T09:50:26.187Z" },
+]
+
[[package]]
name = "watchfiles"
version = "1.2.0"
@@ -3974,15 +4428,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/f9/45d021e4a5cc7b9dd567f7cbb06d3b75f751a690063fb6cc7ec60f4e46b7/watchfiles-1.2.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a88fc94e647bc4eec523f1caa540258eb71d14278b9daf72fa1e2658a98df0f0", size = 457771, upload-time = "2026-05-18T04:30:56.331Z" },
]
-[[package]]
-name = "webencodings"
-version = "0.5.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" },
-]
-
[[package]]
name = "websocket-client"
version = "1.9.0"
@@ -4337,3 +4782,38 @@ sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0
wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" },
]
+
+[[package]]
+name = "zope-interface"
+version = "8.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/08/dc/50550cfcbb2ea3cbca5f1d7ed05c8aa840f831a0f2d63aec0a953f7c590e/zope_interface-8.5.tar.gz", hash = "sha256:7a3ba1c5877f0f3e3906b02ddf793abed2becc2948116414ce0e1dd820b68d6d", size = 257957, upload-time = "2026-05-26T06:50:14.574Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/b6/43/9cd98bee951d23848de690ba2809f87e3b22c67c370987acc960da15ad37/zope_interface-8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0c8aa2bf8f3911ef37b87deb1bbe225a310e6eb6522a16d77f5d8330c4f6fbe", size = 210951, upload-time = "2026-05-26T06:49:00.178Z" },
+ { url = "https://files.pythonhosted.org/packages/17/0f/8f1a29966bcf863e3a2121edcafb81c55715de7886bcc9544749cc79e7da/zope_interface-8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:efe234a0fafb4b6b1602e9be9245b97c2bf06d67c07af5a4bc3c0438978b555c", size = 211309, upload-time = "2026-05-26T06:49:02.732Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/9f/37e564eaaf85e3abc1ada40a79fa43f2ab45bdb67431b0ec0fe29e4763e2/zope_interface-8.5-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:dabeb6fe1228d411994f300811edc6866fff0cdcbc9cef98a78f05ea0da42e37", size = 254881, upload-time = "2026-05-26T06:49:04.303Z" },
+ { url = "https://files.pythonhosted.org/packages/06/61/e6501d8ea7a2cac3217e03f404e1f98c1df7191d83cfe86b1895fbba5dac/zope_interface-8.5-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:147a9442dcc2b7339ecdb1be2b3cdb098e90462e39425054053ebfb50d99125a", size = 259811, upload-time = "2026-05-26T06:49:06.373Z" },
+ { url = "https://files.pythonhosted.org/packages/91/15/bfa25ef480b02af6e9452c478483fec75e87c9e2b60c407fd0b1f6054b9c/zope_interface-8.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a17e681224267880707c9ec9e730ad9a1ad2d65c371256843efba6cf48711b58", size = 260358, upload-time = "2026-05-26T06:49:08.317Z" },
+ { url = "https://files.pythonhosted.org/packages/64/51/2b518072fea76242da64451d501c69b7b5ccdef9b57fead584ccf1c180d5/zope_interface-8.5-cp310-cp310-win_amd64.whl", hash = "sha256:d178968a1a611df30549a717d1624cb38ca810347339e3e37b7baa6f6781a170", size = 214822, upload-time = "2026-05-26T06:49:10.441Z" },
+ { url = "https://files.pythonhosted.org/packages/ce/f1/83ad110fb847413affe71609bb50e59e1aa082e1236030122227c7c283d3/zope_interface-8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:afc66ccaef2a3c0bef6ca02aad40d29a39276389dad16a8eac36f9f385e4d057", size = 211426, upload-time = "2026-05-26T06:49:12.595Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/a7/6b6e0c31ac240cb9fc015ae9ed45ca54be886c18fcf7bfa2377a4d7a8785/zope_interface-8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28044972187245d7a309e4699319bfdbd2ffcbf7176d1d4ddf5adffb2dea80f", size = 211850, upload-time = "2026-05-26T06:49:14.474Z" },
+ { url = "https://files.pythonhosted.org/packages/37/36/7599ecabcf80ce4fef2e1ef3c5ac0d4696b61f03f724cc44022f4d226af9/zope_interface-8.5-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:03bbecc7982af713d7499d4084bc03916413d17ffd45f89009348cc0c1d9e376", size = 260711, upload-time = "2026-05-26T06:49:16.568Z" },
+ { url = "https://files.pythonhosted.org/packages/03/3e/1774b0ee46ccbb5498ee3c33ece40315b6ef58bc71957be94bd345340bc1/zope_interface-8.5-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf917009a4a7457c7290225a019f4a0aa706d96accd2cfdba2418d3bc1fcde2f", size = 265277, upload-time = "2026-05-26T06:49:18.656Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/09/e533b2ffabaae4e5d5730d6768a591cf335defe8e37bec2ad905d09be656/zope_interface-8.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:31cff25b2aaedb5267e6e77b1e9be6b0ec4f622032de8a069202b8ffacda7dc2", size = 266369, upload-time = "2026-05-26T06:49:20.174Z" },
+ { url = "https://files.pythonhosted.org/packages/49/4a/3ebe6a4c122b2d5340db45cbe7e490663d3228b172710ec71060cd5d541e/zope_interface-8.5-cp311-cp311-win_amd64.whl", hash = "sha256:17a3114bbdddb5e75e5784cdf318944636190cbbc72d357ef9fb1a8b0351f955", size = 215161, upload-time = "2026-05-26T06:49:21.799Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/59/056ad97af5b16db1975ee98ec7ab03d2ce3f3355efad904ced1dbce0e39f/zope_interface-8.5-cp311-cp311-win_arm64.whl", hash = "sha256:aab6bb5bee10f38ea688b95ba054396b67f613552d2c8378be7fcb2d2fba7646", size = 213481, upload-time = "2026-05-26T06:49:25.085Z" },
+ { url = "https://files.pythonhosted.org/packages/97/cc/b84123a948f3162a34623e188922827cd845244fdd043ed20f8d02228caa/zope_interface-8.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8e6ee90c2e6de7c37058d5fa41f123c8b13a312db8d1e0fb5840d7f4bcdff9c9", size = 212165, upload-time = "2026-05-26T06:49:26.566Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/78/cbceec44f1b27208a76c1a688c131302685852406a23df5aab68324109cc/zope_interface-8.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c1adc90d3576b3b4c4de4953e6002c37bef28b78d7fa54c1bbfd0c50f022fe7c", size = 212341, upload-time = "2026-05-26T06:49:28.182Z" },
+ { url = "https://files.pythonhosted.org/packages/e1/c3/005032195ff3b210c139b7c560ed5c534e844b0907d8e44d2b3d8919305e/zope_interface-8.5-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:e6347b8d8d12c5eca6502450a92be30079b7acfade2c4f693efa0deb8871b06e", size = 265296, upload-time = "2026-05-26T06:49:29.741Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/66/1036543d6a66bc04c19df3cf650f3ad938a002ab0a443c24e23e8de5e8b9/zope_interface-8.5-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5e970dabea777a24b0b0bbf9dae3ab75ce8b2d8e948edf4875627034b21f3560", size = 270689, upload-time = "2026-05-26T06:49:31.767Z" },
+ { url = "https://files.pythonhosted.org/packages/30/4c/8b56259558cace4414e753ca6740396a1f59d4a95ddb55b4658600408670/zope_interface-8.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f0b48ccadaa9839e09ff81e969703cecb3f402c813bfe8b958652e699bea69f5", size = 270280, upload-time = "2026-05-26T06:49:33.489Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/ea/649908c83aa8fdb7faf2ddca4d3cf6fb8f2157121267dc56e8f72681e26c/zope_interface-8.5-cp312-cp312-win_amd64.whl", hash = "sha256:e0e311f1277468c08fd59a2b41f71b43d25dff639789d364747acd1705c0df6e", size = 215019, upload-time = "2026-05-26T06:49:35.607Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/97/da13037b4c563e4df32eedbc819f8c00b754af494f68211e3dffd48d52da/zope_interface-8.5-cp312-cp312-win_arm64.whl", hash = "sha256:652b73107a04159ec6c020db6c1543d4f1e8f4d069bd2aac88a947820923517b", size = 213569, upload-time = "2026-05-26T06:49:37.317Z" },
+ { url = "https://files.pythonhosted.org/packages/f4/8c/4c15755d701f2ec0e80d64a18e1ebaf5be2c584c0ec153fd516f5d13eada/zope_interface-8.5-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:28e80457c134d1fa57a7d758004dece348654e1b1467ac22dcdc20fc1d127c52", size = 212512, upload-time = "2026-05-26T06:49:38.996Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/2e/4360c54c465db042cc8fbeeec92abac28b4cedbf6ba63c1f092fd08a190f/zope_interface-8.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:09495ce9d559c06b70f2d4855b3e4f48a822a9ddc8be1d30c5b4e5be14ae1ace", size = 212541, upload-time = "2026-05-26T06:49:41.186Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/a5/692a2b8d70f78e848793231d5fae5fecbf8d0cccd73430fdc34802a6d3c1/zope_interface-8.5-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:7849ad8fa90763cc1087f4dda78ca3a233e950b3e08fac7079297c9cafbbd7bb", size = 265191, upload-time = "2026-05-26T06:49:43.449Z" },
+ { url = "https://files.pythonhosted.org/packages/70/8d/454a9cfc7a050c394ab4f11b3371f7897828b7415e096afff724637e65e0/zope_interface-8.5-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5578c9421ca409a1f39f153d6f7803e4cde01da592ec75a9ac5e1b777d18d33b", size = 270626, upload-time = "2026-05-26T06:49:45.425Z" },
+ { url = "https://files.pythonhosted.org/packages/51/8c/db8409cfa3575b8e9b4800babd7d49f8228433cd1f0c56814bd0ada49c33/zope_interface-8.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e1bd7d96b4ca5fa311f54c9eac16dce4886b428c1531dbe06067763ccdf123b4", size = 270444, upload-time = "2026-05-26T06:49:47.025Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/df/a386940e41469ef615e100a216d8b386521e9e598817147f87932ca203c4/zope_interface-8.5-cp313-cp313-win_amd64.whl", hash = "sha256:0c8123d2a4dfde2a613c7cb772605477724782c20bc2e0ad1d9435376a6a44a3", size = 215021, upload-time = "2026-05-26T06:49:48.478Z" },
+ { url = "https://files.pythonhosted.org/packages/89/75/477eb5669b6b2a7a843decd1a075e9b1971a8720017654143a7183abd3d9/zope_interface-8.5-cp313-cp313-win_arm64.whl", hash = "sha256:6d02be14f3173c6c7288bc2fdf530090c01c3cf8764ad46c68024686f364278e", size = 213610, upload-time = "2026-05-26T06:49:50.01Z" },
+]