GDPR RoPA
The Record of Processing Activities that GDPR Article 30 requires a controller to keep and to produce on request. Activities are registered in the running application rather than maintained as a separate document, so the record describes the deployment that exists.
An activity is refused unless it carries an id, a name, its purposes, a legal basis and the categories of data it processes, and the legal basis has to be one of the six Article 6 bases. A record that cannot answer those questions is not one a supervisory authority will accept.
The register exports as JSON, CSV or Markdown, and every registration, change, removal and export is recorded in the audit chain, so the register's own history shows when the controller knew what.
b.gdpr.ropa.create(opts?) #
{
controller: object, // name and contact of the controller
dpo: object, // data protection officer's details
supervisoryAuthority: object, // the authority the controller answers to
now: object, // function returning epoch ms; for tests
audit: object, // audit instance, or false to stay silent
}
Open a Record of Processing Activities. The returned register answers register, update, remove, get, list and export, and carries VALID_LEGAL_BASES, the six Article 6 bases it will accept.
A controller that is not an object raises gdpr-ropa/bad-controller, since the controller's identity is the first thing an Article 30 record has to state.
register(activity) requires id, name, purposes, legalBasis and dataCategories: a non-object activity raises gdpr-ropa/bad-activity, a missing or non-string id gdpr-ropa/bad-id, any other absent required field gdpr-ropa/missing-field, and a legalBasis outside consent, contract, legal-obligation, vital-interests, public-task and legitimate-interests raises gdpr-ropa/bad-legal-basis. Registering an id already present raises gdpr-ropa/duplicate-id rather than replacing the activity.
update(id, patch) merges the patch over the stored activity and then applies the same required-field and legal-basis checks to the result, so a patch that clears name or purposes raises gdpr-ropa/missing-field and the stored activity is left alone. A record can only leave the register carrying every Article 30 §1 field. A field that is absent raises gdpr-ropa/missing-field; one that is present but unusable raises gdpr-ropa/bad-field, which covers a name that is not a non-empty string and a purposes or dataCategories that is not a non-empty array of names, since a record whose purposes is [] answers the Article 30 question with nothing. id keeps gdpr-ropa/bad-id and legalBasis gdpr-ropa/bad-legal-basis, which names the six bases.
A stored activity is frozen, with purposes and dataCategories copied and frozen too, and that frozen record is what register, update, get and list answer with. So clearing the array you passed to register, or assigning to a field of the record you got back, does not reach the register: either would otherwise put an activity the validation refused into the next export. update raises gdpr-ropa/bad-patch for a non-object patch, and update and remove raise gdpr-ropa/not-found for an id the register does not hold. get answers null instead, since asking whether an activity is registered is an ordinary question rather than an error.
export({ format }) renders the register as json, csv or markdown; any other format raises gdpr-ropa/bad-format. controller, dpo and supervisoryAuthority are carried into the exported document, which is what makes the output something to hand to an authority rather than a list of rows.
var b = require("@blamejs/core");
var ropa = b.gdpr.ropa.create({ controller: { name: "Acme GmbH" } });
ropa.register({
id: "billing",
name: "Customer billing",
purposes: ["invoicing"],
legalBasis: "contract",
dataCategories: ["name", "address"],
});
ropa.list().length; // → 1
ropa["export"]({ format: "markdown" });