Skip to content

Repository files navigation

validation-answer

Normalizes qualified signature-validation reports (EU DSS behind a signing API) into one stable, wire-ready answer shape — so every service and UI renders the same fields from one place, instead of hand-copying the answer struct per consumer.

go get github.com/gmb-lib/go-validation-answer

See CHANGELOG.md for what each release changed, and what it means for code that already uses this library, before you bump.

Zero dependencies (standard library only). Import path package name: answer.

Why

The upstream validation report is relayed verbatim by the validation service, and its layout varies across API versions: the signer identity may be nested under signerExt or sit at the signature entry's top level; timestamps may be flat (timeStamp, ocspResponceTime — upstream spelling) or nested under info (bestSignatureTime, ocspResponseCreationTime); the included-file list may be ["a.pdf"] or [{"filename":"a.pdf"}], under validatedDocument or at the data level. NormalizeReport reads the known layouts with fallback resolution and produces one answer.

The answer (also the JSON wire contract)

res, err := answer.NormalizeReport(rawReport) // the verbatim {data:{…}} bytes

answer.Validation — document-level verdict (PASSED / INDETERMINATE / FAILED), pass, container form, signed-file names, and signatures[] (answer.Signature: per-signature verdict, format profile, legal-meaning level, signer identity, signing / revocation / max-validity times, warnings, errors). The top-level per-signer fields mirror the first signature for single-signature callers. signatureId / documentId / reportId / validatedAt are caller context, set by the serving side — validatedAt is when the validation actually ran (RFC 3339): validation is time-anchored (revocation can post-date it), so an answer served later than it was produced renders "as of" that moment, never as current.

Rules baked in:

  • Verdicts are mapped, never recomputed: TOTAL-PASSED/TOTAL-FAILED map directly; anything else is INDETERMINATE. The overall verdict fails on any failed signature and passes only when every signature passed and the report's own counts agree.
  • Levels map to legal meaning (QESIGQES, QESEALSEAL, ADESIG*/ADESEAL*AdES); unknown codes pass through visibly rather than being guessed.
  • An organisation's registration number is preferred over a bare serial; a single PDF's placeholder "file list" is dropped rather than surfaced.
  • Timestamps pass through as RFC 3339 (a legacy locale format is converted).
  • In-process extras (SignaturesCount, ValidSignaturesCount, ValidationLevel — e.g. ARCHIVAL_DATA after an archive timestamp) are available on the struct but deliberately off the wire.

The wire key set is pinned by a test (TestWireContractKeys) — changing it is an explicit, reviewed act, never a side effect.

Scope / non-goals

  • No validation calls, no HTTP — bytes in, answer out.
  • No cryptographic interpretation; presence/verdict mapping only.
  • The verbatim report itself is not reshaped or re-served by this package.

Contributing

Bug reports and pull requests are welcome. CONTRIBUTING.md names the gate a change has to pass, what a change to this library needs, and the sign-off every commit carries.

Suspected vulnerabilities go through the private route in SECURITY.md — never a public issue.

License

MIT — see LICENSE.

About

Normalizes qualified signature-validation reports into one stable, wire-ready answer, so every service and UI renders the same fields

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages