- Go 95.1%
- Shell 4.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Relative links out of the repository do not resolve on the public forge. The README's contributing section now matches CONTRIBUTING. Link: #1 Signed-off-by: Justin Simpson <jsimpson@artefactual.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
| .forgejo/workflows | ||
| cmd | ||
| docs | ||
| internal | ||
| LICENSES | ||
| reports | ||
| scripts | ||
| .gitignore | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| DCO | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
| REUSE.toml | ||
provenant-import
The legacy on-ramp for Provenant: it ingests an Archivematica AIP and produces the OCFL object that Provenant attestations bind to.
Status: prototype; one package at a time; not integrated with shipped products.
It is one of two producers in Provenant's two producers, one substrate, one verifier architecture (ADR-06):
Legacy path: Archivematica AIP (.tar/.7z/dir) --> provenant-import --> OCFL object -+
Direct path: live workload (Spike 02) -------------------------------> OCFL object -+
v
provenant-attest (METS -> attestations)
v
provenant-verify (UNCHANGED, both paths)
provenant-import absorbed the conversion core of the now-retired a11a2ocfl
PoC: 7z/tar/dir extraction, BagIt parse, METS capture, and the OCFL builder
(sha512 manifest + a fixity bridge from the bag's native manifest). The lossy
JSON-LD PREMIS step and the home-grown OCFL validator were dropped: Provenant
reads PREMIS-in-METS directly (in provenant-attest) and validates with stock
rocfl.
In the article
This repository is experiment one of the article "Computed and Asserted": copy a real Archivematica AIP, whole, into an OCFL object, then check every payload file against the manifest the AIP itself carries. Figure 1 of the article is the equivalence table this tool writes.
The command:
provenant-import --profile b --reports work/reports aip/CSVmultiLevel.tar work/object
What that run recorded (captured 2026-09-04, the run figure 1 was rendered from):
| Source payload entries | Preserved by digest | Dropped per profile | Unaccounted |
|---|---|---|---|
| 19 | 18 | 1 | 0 |
- 19 payload files are listed in the AIP's own
manifest-sha256.txt. - 18 are in the OCFL object under a matching digest.
- 1 is dropped on purpose, and the drop is recorded: the transfer METS
(
data/objects/submissionDocumentation/transfer-CSVmultiLevel-<uuid>/METS.xml). It is submission documentation from the transfer, not the preservation payload. The AIP's own METS is kept and round-trips (the report saystrue). - The import took 0.24 s of wall clock in that run: under half a second.
import-report.md, written next to the object, is the record of the equivalence:
the counts above, the dropped file by name with the reason, and the bag wrapping
files that profile b leaves behind. Nothing is unaccounted for.
The input is an Archivematica AIP made from the CSVmultiLevel sample transfer in
archivematica-sampledata.
It is a 15 MB tar and is not part of this repository.
Usage
provenant-import [--profile b] <input.tar|input.7z|input-dir> <output-dir>
Import profiles (ADR-06 section 2a)
What of the source AIP the OCFL object preserves is an operator choice. In every profile the source METS stays authoritative (SC-9); they differ in how much of the original bag wrapping travels with the object.
--profile |
What the object holds | When |
|---|---|---|
b (default) |
METS + digital objects (lean preservation view) | the usual case |
c |
as b, plus the native manifest-*.txt / tagmanifest-*.txt as preserved evidence |
keep the source's own fixity record |
a |
v1 = the opaque original archive; v2 = Provenant's extracted output |
bit-level fidelity to the submission; uses OCFL versioning (P9) |
See docs/import-build-decisions.md for the rationale behind the default and the profile-(a) subject-granularity model.
Import-event facts + equivalence report
Alongside the OCFL object, each import writes two files to --reports (default
reports/):
import-event.json- the machine-readable FACTS of the crossing (object id, profile, source AIP identity + sha256, a deterministic event id, and an equivalence check: every source payload entry is preserved in the object by digest, or accounted for as an intentional drop; plus the METS round-trip and the bag wrapping dropped per profile).provenant-importdoes not sign;provenant-attest -import-event import-event.jsonreads this record and signs it as onePreservationEvent(ADR-05 keeps signing in attest).import-report.md- the human equivalence/import report. It doubles as the delete-after-verify safety record: it shows that every byte the source bag certified is either present in the object (verifiable by digest) or listed as a reasoned drop, so the source AIP can be deleted once the signed attestations verify.
Both are per-run output and are gitignored.
Build & test
The module targets Go 1.26.
Building the binary. go build ./... is a compile check only: it matches
several packages (the internal/... libraries and the command), so Go compiles
them to confirm they build and then discards the executables; no binary is
written. To produce the actual binary, build the command package:
go build ./cmd/provenant-import # writes ./provenant-import (cwd)
go build -o bin/provenant-import ./cmd/provenant-import # explicit output path
go install ./cmd/provenant-import # installs to $GOBIN, else $GOPATH/bin (~/go/bin)
The /provenant-import build output is gitignored. Run it with:
./provenant-import --profile b <input.tar|input.7z|input-dir> <output-dir>
Testing.
go test ./...
That runs on a bare clone: nothing needs to be staged. The reader, the three
profiles, the import-event facts and the CLI are tested against a small synthetic
AIP that internal/aip/aiptest builds in a temp
dir as a directory and as a .tar. The .7z path uses one committed synthetic
fixture of about 1 KB; its
provenance note says how it was made.
Where rocfl is installed the tests also validate
every object they build with it.
Testing against real AIPs (opt-in). Real Archivematica packages are not part of
this repository. The opt-in cases run the same code over three specific packages,
found by name under the directory that PROVENANT_TESTDATA names:
PROVENANT_TESTDATA=/path/to/staged go test ./...
PROVENANT_TESTDATA=/path/to/staged scripts/acceptance.sh # needs rocfl
The _real test cases and the acceptance script look for these paths:
Path under $PROVENANT_TESTDATA |
Form | What it exercises |
|---|---|---|
teste-cd7634fb-98bc-40f3-ada2-60a78a1be329/ |
extracted BagIt directory | directory input; 42 payload entries, 41 preserved, 1 dropped |
aips/CSVmultiLevel-76b9e633-de6e-437c-a3d3-80f7f6b2c48c.tar |
POSIX tar | the article's AIP: 19 / 18 / 1 |
aips/PreservationCopies-a03ae51c-0c87-4abc-9269-3221c6c932e2.7z |
7z | md5-only manifest, so no sha256 fixity bridge (ADR-01 case 3) |
With the variable unset those cases are skipped and say so. You do not need all
three: a package that is not staged is skipped by name. A directory that holds none
of them fails the tests, so a mistyped path cannot pass for coverage.
scripts/acceptance.sh runs every profile over every staged package, validates each
object with rocfl, and writes reports/acceptance.md.
CI. CI of record runs on the maintainers' sovereign runner; the public copy
runs the same workflows where the host allows. The workflows are in
.forgejo/workflows/: ci.yml (build, test, vet, gofmt,
govulncheck) and compliance.yml (REUSE lint and the DCO sign-off check).
AI assistance
This code was written with AI assistance (Anthropic's Claude), and that is
disclosed: AI-assisted commits carry a Co-Authored-By: trailer. The policy
mirrors the Linux kernel's. AI-assisted contributions are permitted and must be
disclosed. An AI cannot provide the Signed-off-by: a human signs off every
commit on main and thereby takes responsibility for the contribution's origin
and licensing under the DCO. Nothing reaches main on an AI's authority
alone (ADR-08).
Licensing & contributing
REUSE-compliant: code is Apache-2.0, docs are CC-BY-4.0
(ADR-07). Every file carries
an SPDX header or is declared in REUSE.toml.
You are welcome to fork the repository, try it out, and open issues. For now the repository is read-only except to its maintainer, and pull requests are not accepted. CONTRIBUTING.md says how commits here are made.