Skip to main content

presidio-hardened-vol-assign

A production-ready Python CLI tool (pva) implementing the multi-objective volunteer assignment model from:

Rabiei, P., Arias-Aranda, D., & Stantchev, V. (2023). Introducing a novel multi-objective optimization model for volunteer assignment in the post-disaster phase: Combining fuzzy inference systems with NSGA-II and NRGA. Expert Systems With Applications, 226, 120142.

The tool combines three Fuzzy Inference Systems with NSGA-II and NRGA to produce Pareto-optimal volunteer assignment solutions for post-disaster Emergency Department staffing.


Installation

pip install presidio-hardened-vol-assign
# or with uv:
uv add presidio-hardened-vol-assign

Requirements: Python 3.11+


Quick start

1. Prepare input CSVs

volunteers.csv — one row per volunteer:

Column Description Range
volunteer_id Unique identifier string
skill_type triage or er_nurse —
skill_level Proficiency score 0–10
distance_ed_<ED_ID> Distance to each ED (km) 0–100
difficulty_tolerance Willingness to work under pressure 0–10
volunteer_id,skill_type,skill_level,distance_ed_ED1,distance_ed_ED2,difficulty_tolerance
V1,triage,8.0,5.0,12.0,7.0
V2,triage,6.5,3.0,8.5,5.0
V3,er_nurse,9.0,15.0,4.0,8.0

eds.csv — one row per vacancy:

Column Description Range
ed_id Emergency Department identifier string
vacancy_type triage or er_nurse —
num_patients Current patient load 0–100
emergency_level ED criticality score 0–10
ed_id,vacancy_type,num_patients,emergency_level
ED1,triage,40,8.0
ED2,er_nurse,25,6.5

2. Run the solver

pva assign \
  --volunteers volunteers.csv \
  --eds eds.csv \
  --solver both \
  --seed 42 \
  --output results/

Terminal output:

Problem: 3 volunteers, 2 vacancies | solver: both | pop: 100  gen: 200

┌─────────────────────────────┐
│    Results — NSGA2          │
├──────────────┬──────────────┤
│ Metric       │        Value │
├──────────────┼──────────────┤
│ NNS          │            4 │
│ MID          │       0.3821 │
│ SM           │       0.0412 │
│ HV           │       0.4156 │
│ CPU time     │        1.24s │
└──────────────┴──────────────┘
  Pareto CSV  → results/pareto_nsga2_20240101T120000.csv
  Assignments → results/assignments_nsga2_20240101T120000.csv
  Metrics     → results/metrics_nsga2_20240101T120000.json

┌─────────────────────────────┐
│    Results — NRGA           │
├──────────────┬──────────────┤
│ Metric       │        Value │
├──────────────┼──────────────┤
│ NNS          │            3 │
│ MID          │       0.3904 │
│ SM           │       0.0387 │
│ HV           │       0.4021 │
│ CPU time     │        1.18s │
└──────────────┴──────────────┘
  Pareto CSV  → results/pareto_nrga_20240101T120000.csv
  Assignments → results/assignments_nrga_20240101T120000.csv
  Metrics     → results/metrics_nrga_20240101T120000.json

3. Output files

pareto_<solver>_<timestamp>.csv — one row per Pareto-front solution:

solver,solution_id,z1,z2
nsga2,0,0.312451,0.421300
nsga2,1,0.298760,0.445810
nsga2,2,0.341200,0.398750
  • z1 — mean importance of unmet nursing needs (minimise)
  • z2 — mean volunteer preference dissatisfaction (minimise)

assignments_<solver>_<timestamp>.csv — per-assignment details for each solution:

solution_id,volunteer_id,ed_id,vacancy_type,fis1_score,fis2_score,fis3_score
0,V1,ED1,triage,0.312451,0.0,0.198300
0,V3,ED2,er_nurse,0.0,0.421300,0.145200

metrics_<solver>_<timestamp>.json — summary metrics:

{
  "solver": "nsga2",
  "nns": 4,
  "mid": 0.382100,
  "sm": 0.041200,
  "hv": 0.415600,
  "cpu_time_sec": 1.240
}

pva.log — structured JSON-lines security event log (no PII):

{"ts": "2024-01-01T12:00:00+00:00", "level": "INFO", "version": "0.2.0", "event": "presidio-hardened-vol-assign loaded", "audit_status": "ok", "n_vulnerabilities": 0}

4. Re-compute metrics from a saved Pareto CSV

pva metrics --pareto results/pareto_nsga2_20240101T120000.csv

5. Check version and security status

pva version
presidio-hardened-vol-assign 0.2.0
Dependency audit: OK (last checked: 2024-01-01 12:00 UTC, 0 vulnerabilities)

CLI reference

pva assign   [--model  ed-staffing|humanitarian]   (default: ed-staffing)

             # ed-staffing model inputs:
             --volunteers <csv>  --eds <csv>
             # humanitarian model inputs:
             --people <csv>      --centers <csv>

             [--solver  nsga2|nrga|nrga-ranked|greedy|exact|both|all]   (default: both)
             [--seed    <int>]              (reproducibility)
             [--pop-size <int>]             (default: 100)
             [--generations <int>]          (default: 200)
             # humanitarian hard-constraint mode (optional):
             [--hard-capacity]              (enforce centre capacity via repair)
             [--max-distance <km>]          (cap distance for low-mobility people)
             [--mobility-threshold <0-10>]  (default: 3.0)
             [--output  <dir>]              (default: ./results)
             [--emit-evidence]              (signed evidence record; default off)

pva allocate-people  --people <csv> --centers <csv>   [solver/seed/... as above]
             # convenience alias for `assign --model humanitarian`
             # also accepts --hard-capacity / --max-distance / --mobility-threshold
             # inherits --emit-evidence

pva verify-evidence  --evidence <json> --trust <json>
             # offline, fail-closed verification of an evidence record; exit 0/1

pva metrics  --pareto <csv>     (auto-detects 2- or 3-objective fronts)

pva show     --pareto <csv> [--pareto <csv> ...]   (overlay solvers)
             [--output <png|svg>] [--title <str>]

pva benchmark [--model humanitarian|ed-staffing]
              [--size  small|large|both]   (default: both)
              [--instances <int>]          (default: 10, per size)
              [--solver nsga2|nrga|nrga-ranked|greedy|both|all]
              [--seed <int>]               (default: 42)
              [--pop-size <int>] [--generations <int>]
              [--check-repro]              (report bit-for-bit REP)
              [--baseline]                 (add greedy comparator + Wilcoxon HV test)
              [--exact]                    (add exact weighted-sum comparator)
              [--output <dir>]

pva sensitivity [--model humanitarian|ed-staffing]
              # inputs as for `assign` (--people/--centers or --volunteers/--eds)
              [--factors <csv>]            (default: -0.2,-0.1,0,0.1,0.2)
              [--solver ...] [--seed <int>] [--pop-size <int>] [--generations <int>]
              [--output <dir>]

pva ablation  [--model humanitarian|ed-staffing]
              # inputs as for `assign` (--people/--centers or --volunteers/--eds)
              [--solver ...] [--seed <int>] [--pop-size <int>] [--generations <int>]
              [--output <dir>]

pva serve     [--host <addr>]              (default: 127.0.0.1)
              [--port <int>]               (default: 8000)
              [--cors-origin <origin>]     (repeatable; not needed for the bundled UI)
              [--reload]                   (dev only)
              # interactive demo GUI; requires the 'web' extra

pva build-demo [--output <dir>]            (default: ./dist-demo)
              [--grid compact|full]        (default: compact)
              [--workers <int>]            (default: one per core)
              # pre-solve the GUI into a static site for hosting without Python

pva version

Sensitivity analysis

pva sensitivity probes how robust the Pareto front is to FIS rule-base specification uncertainty: it rescales the FIS output scores by each --factors perturbation (e.g. ±10 %, ±20 %), re-runs the solver(s), and writes sensitivity_<ts>.csv with (factor, solver, NNS, MID, SM, HV, cpu_time_sec). The unperturbed FIS scores are computed once, so the sweep is cheap and deterministic under --seed.

pva sensitivity --model humanitarian \
  --people people.csv --centers centers.csv \
  --factors -0.2,-0.1,0,0.1,0.2 --solver both --seed 42 --output results/

Objective ablation (indicator validation)

pva ablation provides empirical evidence that each qualitative indicator contributes distinct, non-redundant information. It re-solves the problem with each objective dropped from the optimisation in turn, then measures the dropped objective — and the overall hypervolume — back in the full objective space, writing ablation_<ts>.csv:

  • Δ dropped — how much worse the dropped objective gets (mean over the front) when it is no longer optimised. Large = the indicator is doing real work that no other objective drives for free (non-redundant).
  • Δ HV — full-space hypervolume lost by ignoring the objective.

A near-zero Δ would flag an indicator the other objectives already capture. Deterministic under --seed.

pva ablation --model humanitarian \
  --people people.csv --centers centers.csv \
  --solver nsga2 --seed 42 --output results/

Solvers

--solver Algorithm
nsga2 NSGA-II (crowding-distance elitism)
nrga Lightweight NRGA — front-fill with uniform random tie-break
nrga-ranked Canonical NRGA — rank-biased roulette-wheel survival (Al Jadaan et al., 2008); use this for results comparable to the NRGA literature
greedy Non-evolutionary baseline — deterministic weighted-sum constructive heuristic swept over the objective simplex; a literature-style comparator the GAs are measured against (see Baseline comparison below)
exact Exact weighted-sum baseline — the scalarisation solved to optimality per weight (Hungarian assignment for ed-staffing; MILP for humanitarian); a stronger, globally-optimal-per-scalarisation comparator than greedy
both nsga2 + nrga
all nsga2 + nrga + nrga-ranked

Benchmarking & reproducibility

pva benchmark generates the paper's instance sizes deterministically (humanitarian: 5 centres/150 people and 10/300; ed-staffing: 5/75 and 10/150), runs the solver(s) on each, and prints a Table-3-style mean ± std summary for NNS, MID, SM, HV, and CPU time, written to benchmark_<ts>.{csv,json}. With --check-repro each instance is solved twice and the fraction of bit-for-bit identical results is reported as REP — treating reproducibility on stock hardware as a first-class resilience criterion.

pva benchmark --model humanitarian --instances 10 --seed 42 --check-repro

Baseline comparison & significance testing

Comparing only NSGA-II against NRGA shows which algorithm wins, not whether the framework beats an existing allocation method. --solver greedy provides a non-evolutionary baseline: a deterministic weighted-sum constructive heuristic swept across the objective simplex (each weight vector yields one greedy allocation; the non-dominated subset is the baseline front). It is reproducible regardless of --seed.

For a stronger comparator, --solver exact (or pva benchmark --exact) solves the weighted-sum scalarisation to optimality at each weight — an exact bipartite assignment (Hungarian) for ed-staffing, or a MILP for the humanitarian model (z1/z2 exact, centre balance via a linear capacity-overload surrogate; the true FIS objectives are reported on the optimal assignment). It is globally-optimal-per-scalarisation, so it is a much harder baseline to beat than the myopic greedy. Both comparators use the existing scipy dependency.

pva benchmark --baseline / --exact run those comparators on every instance and add greedy / exact rows to the Table-3 summary. When ≥ 2 solvers and ≥ 5 instances are present, the benchmark also runs a Wilcoxon rank-sum test on the per-instance hypervolume distributions (each solver vs. a reference — the greedy baseline if present, else NSGA-II), prints a significance table, and writes stats_<ts>.csv.

pva benchmark --model humanitarian --solver all --baseline --exact --instances 10 --seed 42

Figures

pva show renders publication-quality Pareto figures from the pareto_*.csv files. Two-objective fronts give a Z1–Z2 scatter; three-objective fronts give the three pairwise projections (Z1–Z2, Z1–Z3, Z2–Z3) plus a 3-D scatter, with solvers overlaid. Requires the viz extra (pip install 'presidio-hardened-vol-assign[viz]').

pva show --pareto results/pareto_nsga2_*.csv --pareto results/pareto_nrga_*.csv \
         --output results/fronts.png --title "Humanitarian allocation"

Humanitarian allocation model (v0.2.0)

A second model allocates affected people to relief centres, optimising three objectives via three new Fuzzy Inference Systems. It runs through the same CLI, side by side with the ED-staffing model:

pva assign --model humanitarian \
  --people people.csv --centers centers.csv \
  --solver both --seed 42 --output results/

# equivalently, via the convenience alias (and the canonical NRGA variant):
pva allocate-people \
  --people people.csv --centers centers.csv \
  --solver nrga-ranked --seed 42 --output results/

people.csv — one row per affected person:

Column Description Range
person_id Unique identifier string
vulnerability Priority/need (elderly, injured, children) 0–10
mobility Personal transport access (0 = immobile) 0–10
group_size People moved together (optional, default 1) 1–20
distance_center_<center_id> Distance to each centre (km) 0–100

centers.csv — one row per relief centre:

Column Description Range
center_id Unique centre identifier string
capacity Nominal capacity (people) 1–5000
service_level Resource/quality level 0–10
road_accessibility Route condition / access 0–10

Objectives (all minimised):

Objective FIS
z1 Unfairness of people prioritisation Fairness FIS
z2 Transportation infeasibility Transportation Feasibility FIS
z3 Centre overcrowding / imbalance Center Allocation Balance FIS

The output pareto_*.csv carries z1,z2,z3; assignments_*.csv carries person_id, center_id, fairness, transport, overcrowding.

Hard capacity & transport limits

By default the humanitarian model treats capacity as a soft objective (z3 overcrowding) and transport as a feasibility objective (z2). For settings where those are firm operational limits, --hard-capacity switches on a constraint mode: a deterministic repair guarantees no centre exceeds its capacity (people are placed most-constrained-first; overflow goes to the nearest centre with spare room), and --max-distance caps how far a low-mobility person (mobility below --mobility-threshold) may be sent. The soft model remains the default and is unchanged.

pva assign --model humanitarian --people people.csv --centers centers.csv \
  --hard-capacity --max-distance 30 --mobility-threshold 3 --solver both --seed 42

The membership functions and the explicit Mamdani rule tables for all three FIS are documented — with a fully worked numeric example — in docs/fis-worked-example.md. Ready-to-run synthetic datasets live under examples/ (small/ = 12 people / 3 centres, paper_scale/ = 150 / 5); regenerate them with python examples/generate_examples.py.

pva assign --model humanitarian \
  --people examples/paper_scale/people.csv \
  --centers examples/paper_scale/centers.csv \
  --solver both --seed 42 --output results/

Metrics explained

Metric Description
HV (primary) Hypervolume — area/volume of objective space dominated by the front relative to reference point (1, …, 1) (higher = better). Captures both convergence and diversity, so it is the headline quality indicator
NNS Number of Non-dominated Solutions — Pareto front size
SM Spacing Metric — standard deviation of nearest-neighbour inter-solution distances (lower = more uniform spread)
MID (diagnostic) Mean Ideal Distance — mean Euclidean distance from each solution to the ideal point (0, …, 0). Retained for backward-compatibility with the 2023 paper, but reported as a diagnostic only: it favours solutions near the ideal point, whereas every Pareto-front member is an equally valid trade-off, so it is not a sound stand-alone quality measure — prefer HV

Security

presidio-hardened-vol-assign applies the Presidio hardening profile:

  • CSV sanitisation — schema, types, and value ranges validated before any computation
  • Path traversal guard — --output paths are resolved to absolute form; .. traversal is rejected
  • Secure logging — volunteer IDs only; no names, addresses, or other PII written to logs
  • Dependency audit — pip-audit runs at startup and in CI; unpatched CVEs trigger a warning
  • CodeQL analysis — automated on every push and weekly schedule

To report a vulnerability, see SECURITY.md.


Evidence-carrying allocation

Any pva assign (or allocate-people) run can emit a signed, content-addressed evidence record — one JSON file per solver — that binds the run's inputs, configuration, seed, Pareto front, and assignments into a single document that a third party can verify offline, with nothing but the record and the signer's key. This is the humanitarian instantiation of evidence-carrying decisions (computational jurisprudence; Stantchev 2026, arXiv, ID pending).

# HMAC-SHA256 (stdlib-only; no extra dependency)
export PVA_EVIDENCE_KEY=$(python -c "import secrets;print(secrets.token_hex(32))")
pva assign --model humanitarian --people people.csv --centers centers.csv \
  --solver nsga2 --seed 42 --output results/ --emit-evidence
#   Evidence → results/evidence_nsga2_<timestamp>.json

# Verify offline (fail-closed, exit 0/1)
cat > trust.json <<EOF
{"pva-local": {"alg": "hmac-sha256", "secret": "$PVA_EVIDENCE_KEY"}}
EOF
pva verify-evidence --evidence results/evidence_nsga2_*.json --trust trust.json

The flag is off by default; behaviour is byte-identical when it is not set. When it is set but no key is present, emission fails closed — no unsigned record is ever written. Ed25519 signing is available via the optional crypto extra (pip install 'presidio-hardened-vol-assign[crypto]', key in PVA_EVIDENCE_ED25519_KEY); HMAC needs no extra dependency.

Record schema presidio-hardened/allocation-evidence@1. The hashed content carries: the model and tool version; the solver, seed, pop_size, and generations; a PII-free snapshot of each input CSV ({filename, sha256, row_count} — hashes only, never row contents); the objective labels; the Pareto front (objective values as decimal strings); a digest of the assignments CSV (person→centre mappings are not inlined — the hashed content carries only its SHA-256, and the envelope names the file); and the metrics (NNS/MID/SM/HV as decimal strings). Per family convention (presidio-evidence / evidence-ref@1), canonical JSON has sorted keys and compact separators, and bare floats are rejected — every number is encoded as its shortest round-trip decimal string (the arch-translucency ADR-0010 precedent), so the record is deterministic across runs and platforms.

Content / envelope split (determinism). The volatile generated_at timestamp and the emitter identity live in the envelope, outside the hashed content. So under a fixed --seed and fixed inputs the content_hash is reproducible byte-for-byte — the same guarantee the reproducibility (REP) metric makes for the fronts themselves. The detached signature is taken over {content_hash, signer}.

What the record proves: that this rule-base/solver configuration, on these inputs (identified by hash), with this seed, produced this Pareto front and this assignments digest — and that the signer attests to it.

What it does not prove: it does not prove the model is right (the FIS rule bases and objectives are a modelling choice, not a fact); and it does not prove the execution was uncompromised (a tampered host could sign a faithful record of a corrupted run). It is an integrity-and-provenance seal over a computation, not a correctness or trusted-execution proof.


Interactive demo GUI (pva serve)

A small browser front-end that lets a non-specialist explore the models without writing a CSV. It is a front-end for the same solver code — no reimplementation.

pip install "presidio-hardened-vol-assign[web]"
pva serve                 # http://127.0.0.1:8000/
pva serve --host 0.0.0.0 --port 8080     # e.g. inside a container

Three presets, mapping onto the two models:

Preset Model Mode
Volunteers → Emergency Departments ed-staffing 2 objectives
People in need → relief centres humanitarian soft capacity
Last mile under hard capacity limits humanitarian --hard-capacity + max distance

Pick a preset, set the situation with sliders, and the page returns the full trade-off set. A slider walks along that set — the map, the objective bars and the per-centre load table update live — so the point that there is no single right answer is visible rather than asserted. Preset buttons jump to the best solution for each objective and to a balanced compromise. The chosen allocation downloads as CSV, and the equivalent pva command for the run is shown on the page.

Instances are synthetic. People, centres, volunteers and EDs are generated from (preset, slider values, seed) on a 70 km × 70 km grid. Nothing is uploaded and nothing is stored, so a public instance holds no personal data, and any run can be reproduced exactly from the settings shown on screen.

Running it in public

The server is built on presidio-hardened-fastapi, so locked-down CORS, the security header set (default-src 'self' CSP included) and per-IP rate limiting apply on construction. On top of that, the demo:

  • caps every run at 300 units, 20 sites, 200 generations and 200 population;
  • rate-limits /api/run to 12 requests per minute per IP;
  • runs each solve in a worker process under a 45 s wall-clock timeout, killing the worker if it overruns;
  • memoises the fuzzy precompute per instance, so changing only the algorithm or the generation count re-solves in well under a second.

It has no authentication. Put it behind a reverse proxy with TLS before exposing it, and treat it as a demo rather than an operational planning tool.

A container image is provided:

docker build -t pva-demo .
docker run --rm -p 8080:8080 pva-demo

Hosting it as a static site (pva build-demo)

The GUI needs Python only for the solve itself — the trade-off slider, map, objective bars, load table and CSV export all run in the browser on a payload it already holds. So the demo can be pre-solved and hosted on plain static hosting, with no server-side runtime at all:

pva build-demo --output ./dist-demo          # compact grid: 648 runs, ~10 min
pva build-demo --output ./dist-demo --grid full

The result is a self-contained directory (index.html, app.js, style.css, config.json, runs/**.json, .htaccess) that deploys like any static site. build-demo flips a <meta name="pva-mode"> marker in the page, and the frontend then fetches a prebaked payload instead of posting to /api/run.

What changes for the visitor: sliders step through the pre-solved positions rather than moving freely, and the seed picker offers a fixed set of synthetic affected areas. Everything after the solve behaves identically.

Grid points are addressed by the index of each slider position, never by the value, so the Python builder and the JavaScript frontend cannot disagree about how to format a number. A test asserts that key format on both sides.

Sizes for the compact grid: 648 runs, ~46 MB on disk, largest single payload ~156 kB — but the bundled .htaccess enables mod_deflate, and these payloads compress about 15x, so a visitor downloads roughly 10 kB per run.

Evidence records over HTTP

Setting PVA_EVIDENCE_KEY (or PVA_EVIDENCE_ED25519_KEY) in the server environment enables "evidence": true on POST /api/run, which returns a signed evidence record for the run through the same code path as --emit-evidence. The generated instance is materialised to a temporary directory so the record hashes real input CSVs, and the directory is removed before the response is sent. Without a key the field is reported as unavailable rather than returning an unsigned record.


Roadmap

See PRESIDIO-REQ.md for full version deliberations.

Version Status Description
v0.1.0 Released MVP: FIS + NSGA-II + NRGA, CSV I/O, Pareto metrics (ED-staffing model)
v0.2.0 Released Humanitarian allocation model (3 new FIS, 3 objectives) side by side with the ED model; N-D metrics + reproducibility metric; benchmark + sensitivity + figure export. See docs/v0.2.0-plan.md
v0.3.0 Released Evidence-carrying allocation (--emit-evidence / verify-evidence); interactive Pareto explorer as a browser GUI (pva serve)
v0.4.0 Released Published relief-allocation model in the demo, with exact deciders (weighted-sum rule, MIP) and a compiled FIS evaluator; static demo build (pva build-demo); experiment drivers and result manifests (experiments/)
v0.5.0 Released Near-optimal multiplicity and tie-breaking, capacity-aware local search, solver time budget and seeding, repair forms; reproducible instance generator; drivers and results for the allocation-model audit (MDPI Systems)
v0.5.1 Released Corrected ULPP objective (ulpp_objective="left_out") and the reruns behind the correction to Appl. Sci. 2026, 16, 7581
v0.6.0 Released Python 3.11+ (clears every open dependency advisory); string enums are StrEnum; single ci-ok CI gate
next Planned Real-world data connectors (pva import: Excel roster, HTTPS REST vacancy feed); bring-your-own-CSV in the demo GUI

License

MIT


SDLC

This repository is on the open-source baseline of the PRESIDIO hardened-family SDLC (report · PDF). The controls measured for it, and any open gaps, are its row in the applicability matrix.

Metadata

Release files for presidio-hardened-vol-assign 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for presidio-hardened-vol-assign 0.6.0
File Size Uploaded Provenance Actions
presidio_hardened_vol_assign-0.6.0.tar.gz 757.9 kB With provenance Details for presidio_hardened_vol_assign-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for presidio-hardened-vol-assign 0.6.0
File Interpreter ABI Platform Actions
presidio_hardened_vol_assign-0.6.0-py3-none-any.whl Python 3 none any Details for presidio_hardened_vol_assign-0.6.0-py3-none-any.whl

Total release size: 945.0 kB

Release files / presidio_hardened_vol_assign-0.6.0.tar.gz

Download URL presidio_hardened_vol_assign-0.6.0.tar.gz
Size 757.9 kB
Tags Source
SHA-256 checksum
How to use checksums
853c4306d20a6348b0aa10fb54319537c04f7e0fb5e37fd929c216ddba32b25d
BLAKE2b-256 checksum
How to use checksums
04be2b465ca8fa0b23d124d8fcb06c7863bc891eb429be3085470a4800634fd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Release files / presidio_hardened_vol_assign-0.6.0-py3-none-any.whl

Download URL presidio_hardened_vol_assign-0.6.0-py3-none-any.whl
Size 187.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
057e310db4c1228ff9dc603d782a4c5f4286efd52f25bb64cbe32c5a0de80860
BLAKE2b-256 checksum
How to use checksums
d1afe52817719d63affc3e3c002ad370a60ae67b4dd5f4a4e29b38d346718168
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Security for presidio-hardened-vol-assign 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for presidio_hardened_vol_assign-0.6.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page