Docs

Adapter certification

An interface is a promise. Certification is how an adapter proves it kept it, in a form someone else can check.

Profiles

A profile is a named set of checks written against an interface, not an implementation: cacheStoreCertificationProfile, jobStoreCertificationProfile, storageAdapterCertificationProfile, runtimeAdapterCertificationProfile, and eventDeliveryCertificationProfile. Domain-specific seams define their own with defineCertificationProfile, which validates the profile at module load, so a check naming an undeclared capability fails before any adapter runs.

Certify an adapter

TS
// doc-check: skip - createRedisCache stands in for the adapter under test
import { test } from "bun:test"
import {
  assertAdapterCertification,
  cacheStoreCertificationProfile,
  certifyAdapter,
} from "@nifrajs/testing/certification"

test("the Redis cache adapter satisfies the cache contract", async () => {
  const report = await certifyAdapter({
    profile: cacheStoreCertificationProfile(),
    adapterId: "redis-cache",
    // A FRESH adapter per check, so one failure cannot contaminate the next.
    createAdapter: () => createRedisCache(url),
    cleanup: (adapter) => adapter.clear(),
  })

  assertAdapterCertification(report) // throws, naming every failed check
})

Profiles are structural and dependency-free. A third-party adapter can certify itself in its own test suite without adopting anything else, which is the point: trust becomes portable rather than something we vouch for.

The report is the evidence

JSON
{
  "schemaVersion": 1,
  "ok": true,
  "profile": { "id": "cache-store", "version": 1 },
  "adapterId": "redis-cache",
  "capabilities": [
    { "capability": "read-write", "status": "passed", "checks": ["set-get", "delete"] },
    { "capability": "tag-invalidation", "status": "passed", "checks": ["invalidate-tag"] }
  ],
  "evidenceHash": "9f2c..."
}

The capability matrix is the useful artifact. It says what an adapter supports, per capability, with the checks that back each one. verifyAdapterCertification recomputes evidenceHash, so a stored report can be checked rather than believed.

Failures carry a class, not a message

A failed check records the error class only. Provider messages routinely carry connection strings, tokens, and payload fragments, and evidence is meant to be shared, so it never becomes a place credentials leak. Cleanup errors cannot turn a failed functional check into a pass.