Backfill evidence to MinIO
How to land CI evidence, compliance close-out packs, and break-glass audit records into the `developer-ci-evidence` bucket on MinIO with the right prefix, lifecycle, and read scope.
This task covers landing evidence in MinIO — the lab’s S3-compatible object store running on its own VM. “Evidence” means anything that must survive a session but is too large or too auditable to live in Git: CI run logs, Trivy scan output, SBOM blobs, release artifact archives, smoke-test transcripts, compliance close-out packs, break-glass audit records.
The contract is small: the bucket is developer-ci-evidence, the prefix conventions are fixed, the lifecycle is encoded as policy on MinIO. A backfill follows the same five steps regardless of evidence shape.
When this task runs
- At the close of a CI run that produced evidence in the workspace and needs to land in MinIO.
- At the close of a compliance phase chain (PCI-DSS baseline, file-integrity baseline) — the evidence pack lands in MinIO with the right prefix and lifecycle.
- After a break-glass action — the audit record under
opp-full-plat/reports/break-glass/is copied into MinIO for long-term retention. - On lifecycle audit. Per the day-1 handoff cadence — confirm the prefixes and lifecycle still match the policy.
What is in scope
The single bucket developer-ci-evidence with five established prefixes:
| Prefix | What lives there | Lifecycle (expiration) |
|---|---|---|
builds/ | Per-build artefact blobs (jars, container manifests, build logs) | 90 days |
releases/ | Tagged release artefacts (only items intended as the canonical release) | 365 days |
sbom/ | SBOM JSON / SPDX blobs | 365 days |
trivy/ | Trivy scan output (SARIF + JSON) | 180 days |
smoke/ | Smoke-test transcripts and probe outputs | 30 days |
Out of scope:
- Per-cluster backups (OADP) — those land in their own MinIO bucket (
oadp-spoke-dc-v6-backups) with the OADP-operator-controlled lifecycle. - Database backups (CNPG, future Quay PG) — those follow the CNPG operator’s BackupSchedule resource.
- Vault Raft snapshots — those land via the Vault snapshot API and live under a separate path.
Pre-checks
-
Confirm MinIO reachability.
. "$MINIO_WRITER_ENV" # writer env file in local secrets dir curl -s -o /dev/null -w "%{http_code}\n" \ "${MINIO_ENDPOINT}/${MINIO_BUCKET}/?location" # 200 (or similar AWS-style response)Or with
mc:mc alias set lab "${MINIO_ENDPOINT}" "${MINIO_ACCESS_KEY}" "${MINIO_SECRET_KEY}" mc ls lab/${MINIO_BUCKET}/Expected: the five prefixes are listed.
-
Confirm credential scope. The writer credential has write access to all five prefixes; the reader credential at
minio-developer-ci-evidence-reader.envis list/get only. -
Identify the evidence’s prefix and lifecycle. Match the evidence type to one of the five prefixes. If the evidence does not fit, do not invent a new prefix — file an issue under #229 to propose the new prefix and its lifecycle.
-
Open the GitHub issue. Branch prefix
evidence/<phase-or-control>if the backfill needs an MR.
The change
Step 1 — Stage the evidence locally
Collect the evidence files into a flat directory or a single archive:
mkdir -p /tmp/evidence-stage/<phase>/
cp <evidence files> /tmp/evidence-stage/<phase>/
ls -la /tmp/evidence-stage/<phase>/
For compliance close-out packs, the convention is one .tar.gz per phase containing the sanitized auditor-facing markdown plus the supporting scan output:
tar czf /tmp/evidence-stage/pci-baseline-2026-05-11.tar.gz \
-C /home/ze/opp-full-plat/reports/pci-dss/ \
spoke-dc-v6-pci-dss-v4-baseline-2026-05-11.md \
spoke-dc-v6-pci-dss-v4-baseline-2026-05-11-evidence/
Step 2 — Compute checksums
The evidence is paired with a checksum file to prove it has not been tampered with:
cd /tmp/evidence-stage/<phase>/
sha256sum * > SHA256SUMS
cat SHA256SUMS
The SHA256SUMS file is the audit anchor — it lands in MinIO alongside the evidence and is referenced from the close-out issue.
Step 3 — Upload
mc cp /tmp/evidence-stage/<phase>/ \
lab/${MINIO_BUCKET}/<prefix>/<phase>/
# (the trailing slash on the source is important — mc cp behaves like rsync)
For a one-shot file:
mc cp /tmp/evidence-stage/pci-baseline-2026-05-11.tar.gz \
lab/${MINIO_BUCKET}/releases/pci-baseline/pci-baseline-2026-05-11.tar.gz
mc cp /tmp/evidence-stage/SHA256SUMS \
lab/${MINIO_BUCKET}/releases/pci-baseline/SHA256SUMS
Step 4 — Confirm the lifecycle
The bucket has lifecycle rules per the table at the top of this page. Confirm the rule for the prefix is in place:
mc ilm rule list lab/${MINIO_BUCKET}
Expected: a rule per prefix with the expected expiration period.
If you uploaded under a new sub-prefix (e.g., releases/pci-baseline/), the parent prefix’s lifecycle still applies. Sub-prefixes inherit lifecycle from the parent.
If the lifecycle needs to change (and only if it has to), the change is in the MinIO admin surface, not in S3 API metadata:
# Example: change the trivy/ lifecycle from 180 to 365 days
mc ilm rule add --expire-days 365 --prefix "trivy/" lab/${MINIO_BUCKET}
# (review existing rule first; replace as needed via `mc ilm rule remove ... && mc ilm rule add ...`)
Lifecycle changes are infrequent — every change should have a tracked issue justifying the new retention.
Step 5 — Record the upload
The GitHub issue (or the active session report) captures:
- The MinIO path:
s3://${MINIO_BUCKET}/<prefix>/<phase>/<filename>. - The SHA256 of every uploaded file (from
SHA256SUMS). - The lifecycle expiration date computed from the upload date.
- The reader credential or signed URL the auditor can use to fetch the evidence (read-only credential, not the writer).
For audit-record uploads after a break-glass action, the issue is the break-glass audit issue from runbooks/break-glass-procedure.md.
Validation
A backfill is complete when all of the following are true:
- The evidence is in MinIO at the expected path:
mc stat lab/${MINIO_BUCKET}/<prefix>/<phase>/<filename>succeeds. - The
SHA256SUMSfile is co-located and the sums match the staged copies. - The bucket’s lifecycle rule still covers the prefix (
mc ilm rule listincludes the prefix and the expiration). - The reader credential can list and get the evidence:
mc lsandmc catfrom a different shell usingminio-developer-ci-evidence-reader.envsucceeds. - The session report references the MinIO path.
Prevention
Three guardrails:
- Never invent a new prefix without an issue. The five-prefix convention is the lifecycle contract. Adding
audit/becausecompliance/“didn’t feel right” silently bypasses the lifecycle policy. - Always co-locate
SHA256SUMSwith the evidence. Auditors prove tamper-evidence from the checksum; without it the evidence is just “files we uploaded”. - Use the reader credential for distribution. Sharing the writer credential externally is a credential exfiltration; the reader credential is what auditors and downstream consumers use.
Worked example — compliance close-out backfill
The PCI-DSS baseline close-out on 2026-05-11 produced:
reports/pci-dss/spoke-dc-v6-pci-dss-v4-baseline-2026-05-11.md— sanitized auditor-facing summaryreports/pci-dss/spoke-dc-v6-pci-dss-v4-baseline-2026-05-11-evidence/— supporting scan output
Flow:
cd /home/ze/opp-full-plat/reports/pci-dss
tar czf /tmp/pci-baseline-2026-05-11.tar.gz \
spoke-dc-v6-pci-dss-v4-baseline-2026-05-11.md \
spoke-dc-v6-pci-dss-v4-baseline-2026-05-11-evidence/
sha256sum /tmp/pci-baseline-2026-05-11.tar.gz > /tmp/pci-baseline-2026-05-11.SHA256SUMS
. "$MINIO_WRITER_ENV" # writer env file in local secrets dir
mc alias set lab "${MINIO_ENDPOINT}" "${MINIO_ACCESS_KEY}" "${MINIO_SECRET_KEY}"
mc cp /tmp/pci-baseline-2026-05-11.tar.gz \
lab/${MINIO_BUCKET}/releases/pci-baseline/
mc cp /tmp/pci-baseline-2026-05-11.SHA256SUMS \
lab/${MINIO_BUCKET}/releases/pci-baseline/SHA256SUMS
# Validate:
mc stat lab/${MINIO_BUCKET}/releases/pci-baseline/pci-baseline-2026-05-11.tar.gz
mc ilm rule list lab/${MINIO_BUCKET} | grep releases
# Expect: lifecycle 365 days, applies to releases/ prefix
The session report referenced s3://developer-ci-evidence/releases/pci-baseline/pci-baseline-2026-05-11.tar.gz with the SHA256 and the 2027-05-11 expiration date.
References
opp-full-plat/connection-details/minio.md(the canonical MinIO endpoint + credential custody doc)- ADR
0019-nexus-only-image-supply-chain.md(image supply; MinIO is for evidence, not images) opp-full-plat/reports/pci-dss/(the source compliance evidence packs)opp-full-plat/runbooks/break-glass-procedure.md(break-glass audit records that also land here)- Issues: #229 (this section)