Open Certificate Standard

Version 1 Draft for consultation

Every record claiming this version carries the identifier https://opencertificatestandard.org/v1. This page is what it points to.

Status

A publicly available specification for the form, content and handling of compliance certificates issued for residential property. It is published openly so anyone can test a certificate against it, including competing software companies, letting agents and landlords.

The law comes first. Nothing here overrides a statutory requirement, a British Standard or a scheme rule. Where this standard and the law differ, the law applies. Conformance is not a legal opinion. It does not by itself make a certificate valid, because validity also rests on the competence of whoever carried out the inspection and on the accuracy of what they wrote down.

Licence: CC BY 4.0. You may implement, quote and build on this standard, with attribution. Test vectors and tooling are MIT.

The keywords MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are used as defined in RFC 2119.

1 · What this standard governs

A compliance certificate is any document issued by a competent person that records the inspection, testing, servicing or commissioning of an installation or appliance at a property, where someone else may later rely on it. That someone else might be a landlord, an agent, a tenant, a local authority, an insurer, a court, or a national register.

This standard governs the record. The document is one way of showing it.

If a certificate's identity is the bytes of one PDF, that PDF becomes the legal record. The layout can never be corrected. The software is stuck on the same PDF library forever. A document with a real mistake in it cannot be fixed, because fixing it makes it look tampered with. If the identity is the data instead, a PDF, a web page and a printout of the same record are all equally valid. None of them is the record.

It does not cover inspection method, test procedure, competence or classification coding. Those belong to BS 7671, the Gas Safe Register, OFTEC, HETAS, BS 5839 and the relevant statutory instruments. This standard starts where the inspection finishes.

2 · The record

A record is a JSON object. Only spec, rules, issuedAt and recordVersion are required. Everything else is built from whatever the certificate actually answered, and the checks in §4 decide what that means. A missing answer is reported as missing. Nothing is filled in on its behalf.

{
  "spec":       "https://opencertificatestandard.org/v1",
  "subject":    { "address", "postcode" },
  "dutyHolder": { "name", "address" },
  "issuer":     { "name", "registration", "scheme" },
  "inspection": { "date", "type", "typeName" },
  "items":      [ { "description", "location", "outcome", "defects" } ],
  "rules":      { "schemaId", "version" },
  "issuedAt":   "RFC 3339 instant, UTC, millisecond precision",
  "recordVersion": 1,
  "supersedes": "hash of the record this one replaces"
}

No company name appears in the format. A competitor will not adopt a format with a rival's name inside every document, and this standard is worth nothing unless other people implement it.

A correction is a new record that names the hash of the one it replaces. Records are never edited. The one it replaces stays checkable.

3 · Canonicalisation and hashing

A record's identity is the SHA-256 of its canonical serialisation. The algorithm identifier is jcs-sha256-v1 and MUST be stored beside the hash.

An algorithm identifier never changes meaning. A new algorithm gets a new identifier, and both stay checkable. Redefining an existing one would break every hash already issued.

Rules

  1. Serialise per RFC 8785 (JSON Canonicalization Scheme). Object keys sorted by UTF-16 code unit, no insignificant whitespace, ECMAScript number formatting. A locale-aware sort does not conform.
  2. Absent, null, "" and whitespace mean the same thing. The key is dropped before hashing. Implementations are most likely to disagree here. Get it wrong and two systems give the same certificate two different identities.
  3. An empty container is absent. Test this after normalising its members, so [], {} and an object whose values are all blank are treated the same way. Writing "dutyHolder": {} and leaving the key out MUST produce the same hash.
  4. An array element is never dropped. A blank entry becomes null and keeps its place. Removing it would renumber every item after it and attach a defect to the wrong appliance. A list with no elements is absent. A list holding one blank entry is not.
  5. Strings are Unicode NFC and trimmed. Two strings that look identical can hold different code points. Without normalising them they hash differently, and whoever is checking cannot tell that apart from tampering.
  6. false and 0 are answers. Never drop them. Treating them as absent erases "no" from a safety record.
  7. Refuse NaN, Infinity and integers beyond 253. Do not coerce them. JSON.stringify turns NaN into null, so a corrupt meter reading would otherwise hash as a legitimate blank.
  8. Dates are YYYY-MM-DD in the local day the work was done. Do not convert the timezone. An early-morning inspection converted to UTC lands on the previous day, and the date on a safety record sets when the next one is due.
  9. The moment of issue is RFC 3339 UTC at millisecond precision. The same instant reaches different systems written different ways. Hashing the spelling gives one certificate two identities.

Nine test vectors exercise every rule above. Each carries the record, its canonical string and its hash. Compare the canonical string first. A mismatch there points at one serialisation rule. A mismatch on the hash alone only tells you something differs somewhere.

4 · Conformance

Three cumulative levels. A certificate at one level meets every criterion at the levels below it.

LevelNameThe question it answers
AValidDoes it contain everything the law names?
AAHandoverCan a non-expert read it and act on it?
AAAEvidencedCan you prove, later, what was issued and to whom?

Every check is written so software can decide it. A check that cannot be run automatically does not belong here.

Level A: the particulars

IDCriterion
A1The name and address of the landlord or their agent are present, where the certificate is issued in respect of let premises. Not blank, not "as above", not a name alone.
A2The address of the subject property is present with its postcode, stated separately from A1.
A3The issuer's name and registration number are present.
A5The date the inspection was carried out is stated, and is not in the future.
A6Every item inspected is individually described and located. A count, a room, or "all appliances" does not satisfy A6.
A7An unambiguous outcome in words is stated for every item. Colour or tick style alone does not satisfy A7.
A8Defects are recorded, or an explicit statement that none were identified. Blank does not mean none.

Two kinds of failure. Keep them apart. A check fails either because the person filling the form left a box empty, or because the form has no box to leave empty. The engineer can fix the first before issuing. Only whoever maintains the form can fix the second. Software that treats them the same and refuses to issue on either will refuse whole certificate types, for a reason nobody holding the phone can do anything about.

Levels AA and AAA cover the document and the evidence around it: a page-one summary, the next-due date, a real text layer, a minimum type size, predictable file naming, a verification link, proof of service, retention, supersession chains and property-pack export. These are recorded rather than blocking.

5 · Claiming conformance

A conformance claim MUST state the version of the standard, the level claimed, the certificate types covered, the date, and who is making the claim. Do not claim a level without running the checks. Do not claim a level while any check is unrun.

6 · Open questions

These are real questions, not rhetorical ones. Comments wanted on all of them. Open an issue, or write to [email protected].