PDF/A

What PDF/A-1b actually requires

A tour of the check groups gopdfrab's PDF/A-1b profile is built from, what each one is really asking, and which of them real documents fail most often.

"PDF/A-1b conformant" is one boolean. gopdfrab answers it with a set of checks organised into groups, covering ISO 19005-1 clauses 6.1 through 6.9 plus generic ISO 32000 object-model conformance. Other implementations slice the same clauses differently. Here is what each of these groups is actually asking.

The groups

File structure

Checks.Structure

6.1.x — file header, trailer, xref, object framing, limits

Common failures: Encrypted document, Embedded files, LZW compression, Broken cross-reference table

Colour

Checks.Colour

6.2.2 OutputIntent, 6.2.3.x device colours, 6.2.9–10

Common failures: Missing OutputIntent, Device colour without OutputIntent

Images and XObjects

Checks.Image

6.2.4-6.2.7 image/form/PostScript XObjects

Transparency

Checks.Transparency

6.2.8 transfer functions, 6.4 soft masks/blend modes/alpha

Common failures: Transparency in PDF/A-1, Transfer function present

Fonts

Checks.Font

6.3.x embedding, subsets, metrics, encoding

Common failures: Font not embedded, Glyph not in font

Annotations

Checks.Annotation

6.5.x annotation types and dictionaries

Common failures: Missing appearance stream

Actions

Checks.Action

6.6.x action types and additional actions

Common failures: JavaScript or launch action

Metadata

Checks.Metadata

6.7.x XMP metadata, extension schemas, PDF/A identifier

Common failures: XMP / Info mismatch

Logical structure

Checks.LogicalStructure

6.8 tagged PDF structure hierarchy and marked content

Interactive forms

Checks.Form

6.9 interactive forms

Object model

Checks.ObjectModel

Generic ISO 32000 object-model conformance, independent of PDF/A

One idea, restated in every group

Read the groups together and the same requirement keeps reappearing. Nothing may depend on the environment. A font by name depends on the machine. Device colour depends on the output device. Encryption depends on a key. JavaScript depends on an engine. An annotation without an appearance stream depends on the viewer's taste.

One group is not PDF/A at all

Checks.ObjectModel asks a different question. Is this even valid PDF? The checks behind it are derived from the Arlington PDF Model , and they are separable on purpose. A file can be flawless PDF that fails PDF/A, and it can carry a PDF/A identifier while containing a dictionary ISO 32000 does not permit.

Where the standard is ambiguous

Not every clause has one reading. Where ISO 19005-1 admits two, the Isartor suite encodes the strict one and veraPDF, as the reference implementation, settled on a more lenient one. gopdfrab's default PDFA1B profile follows veraPDF, and Legacy1B is the spec-literal reading.

go
// Verify against the legacy Isartor-derived profile instead of the
// veraPDF-aligned default
v, err := doc.Verify(gopdfrab.Legacy1B)

Checks are data, not a fixed list

The registry is queryable, and a profile is a set you can add to or subtract from. That is useful when you want structural checks without the archival ones, or when one clause is genuinely not your problem.

go
// Start from the full profile and remove checks
p := gopdfrab.PDFA1B.
	RemoveCheck(gopdfrab.Checks.Structure.FileHeaderSignature).
	RemoveCheck(gopdfrab.Checks.Font.SimpleNotEmbedded)

res, err := doc.Verify(p)

// Or start from an empty profile and add only what you need
p2 := gopdfrab.PDFA1B.Clear().
	AddCheck(
		gopdfrab.Checks.Transparency.ImageWithSoftMask,
		gopdfrab.Checks.Metadata.PDFAIdentifierMissing,
	)

res2, err := doc.Verify(p2)

It is worth resisting the temptation to use this on a failing document. Simply removing the failed check does not make the document conformant. It just makes your validator quiet. The error reference exists to make the other route easier.