kraenzle-ritter / preservation-strategy
A machine-readable preservation strategy for archives: JSON Schema (Draft 2020-12), a framework-free validator and an export of its rules as PAR Business Rules.
Package info
github.com/kraenzle-ritter/preservation-strategy
pkg:composer/kraenzle-ritter/preservation-strategy
Requires
- php: ^8.2
- ext-json: *
- opis/json-schema: ^2.3
Requires (Dev)
- laravel/pint: ^1.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
An archive's digital preservation strategy, machine-readable: who is responsible for what, which measures may be taken without asking, what is excluded, which rules apply, and how it relates to the NDSA Levels and the DPC Rapid Assessment Model. A JSON Schema (Draft 2020-12), two examples, a framework-free PHP validator, and an export of the rules as PAR Business Rules.
Written for Anton, the archival information system of Kränzle & Ritter, where an archive gives a preservation mandate in one of two variants. It can be used without Anton.
Why
Format rules have registries: Archivematica's Format Policy Registry, the Preservation Action Registries (PAR), our own format-policy. They say which tool does what to which format. They do not say who decides, what may happen without asking, or what is left alone. That is what a preservation strategy has to say, and what this schema adds. Where a rule is concerned, it follows PAR.
The document
| Field | What it says |
|---|---|
id, version, issued, validFrom, supersedes |
the strategy, its version (Fassung) and dates; id stays across versions |
archive |
name, ISIL, tenant |
variant |
kr: the provider carries digital preservation (package «Technische Betreuung»); own: the archive carries it, the provider migrates on its order |
writtenBy |
provider under kr, archive under own |
policy |
the preservation policy it rests on |
responsibilities |
overall, digitalPreservation, logReview, formatRiskAssessment, formatList, formatRules, migration: a role each (archive, provider, shared), never a person |
riskAssessment |
sources consulted (e.g. NARA), and whether they bind |
measures |
lossyAllowed; consultation: ask for each measure, or only above the booked storage and for extraordinary effort |
exclusions |
formats (PUIDs) and holdings (persistent addresses) no measure touches |
ingest |
keep the delivered file when a conversion on ingest changes it; report or reject invalid files |
findings |
days within which the provider reports a damaged or missing file |
formatPolicy |
the catalogue the rule keys come from |
businessRules |
the rules, shaped after the PAR Business Rule (below) |
standards |
NDSA Levels (level per area, who carries which requirement) and DPC RAM (sections A–K) |
extensions |
anything else, under keys starting with x- |
The schema checks what follows from the variant: under own the archive writes the file, carries digital preservation and is asked for each measure; under kr the provider does, asks only about storage and effort, and names a format policy. The overall responsibility is always the archive's. Without lossyAllowed, every rule in phase preservation keeps the ingested file.
See examples/kr.json, the strategy Kränzle & Ritter writes for an archive with the package «Technische Betreuung», and examples/own.json, an archive's own. Names and numbers in them are examples.
Rules
| Field | PAR Business Rule | |
|---|---|---|
id |
id.name |
unique within the strategy; the strategy's id is the namespace |
description, notes |
same | |
formats |
formats |
PUIDs instead of parIdentifier |
formatFamilies |
formatFamilies |
labels |
preservationActionTypes |
preservationActionTypes |
PREMIS event type codes (mig, nor, val, …), as PAR uses them |
preservationActions |
preservationActions |
a formatPolicyRule key or a PAR action guid, with priority |
phase |
– | preingest (its result is the ingested file) or preservation |
targetFormats |
– (openpreserve/par#38) | formats a migration may produce |
keepsOriginal |
– | whether the file before the rule stays |
inForce, decided |
– | in force; decided by whom and when |
Versions and confirmation
A changed strategy takes a new version. Whether a new version needs a new confirmation is the program's to decide. In Anton: under kr, a rule Kränzle & Ritter adds or changes gives a new version without a new confirmation; the archive confirms again when its own choices change (variant, lossyAllowed, exclusions, ingest, findings) or when the storage needed grows beyond what is booked.
Installation
composer require kraenzle-ritter/preservation-strategy
Usage
use KraenzleRitter\PreservationStrategy\Validator; $result = (new Validator())->validate($json); // string | array | stdClass $result->valid; // false as soon as one finding is an error $result->errors; // list<ValidationError>: path, keyword, message, warning $result->warnings(); // the findings that leave it valid
Beyond the schema, the validator checks that every rule id occurs once, and warns when an excluded format is named by a rule in force (the exclusion wins). Given the catalogue the rule keys come from, it also checks that each key exists, is not retired, and converts into the formats the strategy says:
use KraenzleRitter\PreservationStrategy\ArrayFormatPolicyRules; $catalogue = new ArrayFormatPolicyRules([ 'pdfx_pdfa2b' => ['target' => ['fmt/477']], 'tiff_zip' => [], ]); $result = (new Validator($catalogue))->validate($json);
Implement FormatPolicyRules to read the catalogue from elsewhere, e.g. from kraenzle-ritter/format-policy's repository.
Export to PAR
use KraenzleRitter\PreservationStrategy\ParExport; $rules = (new ParExport())->businessRules($json); // list of PAR Business Rules (v1.2.0)
Rules in force only. Formats are named in the PRONOM namespace, actions by their format-policy key; what PAR has no field for (phase, target formats, whether the original is kept) goes into notes. Each parIdentifier gets a UUID v5 as its guid: for the namespace url over the name, otherwise over the name within a UUID v5 of the namespace. The tests validate the export against the PAR schemas.
Sources
- Preservation Action Registries (Open Preservation Foundation, Apache 2.0): the Business Rule, PREMIS event types as action types. No PAR code or schema is part of this package; the tests use the PAR schemas v1.2.0 as fixtures, under their licence.
- NDSA Levels of Digital Preservation v2.1 and the DPC Rapid Assessment Model v3: referred to, not reproduced.
- The SCAPE control-policy ontology (openpreserve/policies, 2014) addressed the same question in RDF; nothing of it is used here.
Testing
composer test # PHPUnit composer analyse # PHPStan
License
MIT