Architecture

How OpenEPCIS handles identity, isolation, events, and GS1 conformance — the four things that distinguish the platform.

5 min read

OpenEPCIS auth, DLS and reactive pipeline
OpenEPCIS auth, DLS and reactive pipeline

Four cross-cutting concerns shape every OpenEPCIS module.

  1. Authentication: one identity, three ways in
  2. Multi-tenant isolation at the data layer
  3. Live events without polling
  4. GS1 conformance contract

Authentication: one identity, three ways in

A customer's users can sign in with whichever credential their organisation already uses:

  • OIDC bearer token — for systems integrated with the customer's identity provider.
  • Session cookie — for browser-based access to admin or operator UIs.
  • API key + secret — for service-to-service traffic and SDK calls.

All three flows converge on a single authenticated identity. Each customer (tenant) lives in its own Keycloak realm, resolved automatically from the request's hostname. Roles travel on the identity and gate the REST endpoints.

For one-off sharing — for example sending a regulator a direct link to a specific batch — the platform mints short-lived capability tokens scoped to one URL and one HTTP method. No broader account access is granted.

Wallet-agnostic Verifiable Credentials (OID4VC)

The same Keycloak realm that handles sign-in is also a Verifiable Credential Issuer. Keycloak's native implementation of the OpenID Foundation's verifiable-credentials stack — OID4VCI for issuance, OID4VP for verifiable-presentation flows, SIOPv2 for self-issued OpenID identities — turns each tenant's realm into a standards-conformant VC issuer without bolting on a separate identity stack.

Credentials are issued in whichever format the holder's wallet expects. The platform's lead is sd-jwt-vc because selective disclosure is part of the format itself — a holder can prove "recycled-cobalt share is above the regulated threshold" without revealing the exact percentage — and the other accepted formats are jwt_vc_json, ldp_vc and ISO mDoc.

Because the issuance surface is open OpenID-Foundation protocol rather than a proprietary wallet integration, the platform interoperates with every OID4VC-compliant wallet already in production or in pilot — the EU Digital Identity Wallet under eIDAS 2.0, the Catena-X Managed Identity Wallet inside its dataspace, enterprise business wallets, sector-specific wallets, holder apps on mobile. OpenEPCIS doesn't ship a wallet and doesn't pick a winner; it speaks the protocol every wallet camp is converging on.

Trusted subjects

The verifier side is where the real interoperability work lives. A credential is only as useful as the verifier's certainty that the issuer is who they claim to be. OpenEPCIS expects to maintain a globally-scoped trust list of accepted issuers — not EU-only and not product-category-only — so a verifier looking at a presented credential can confirm the issuer's identity, the credential's binding, and the revocation status against a single, openly-maintained list rather than chasing per-region or per-sector registries.

What ships today is the protocol layer — OID4VCI / OID4VP / SIOPv2 issuance and verification surfaces on every Keycloak realm. The named credential schemas (EPCISCommissioningCredential, DPPBatteryPassportCredential, EUDRDueDiligenceCredential, UNTPDigitalConformityCredential and the rest) and the capture-to-issuance pipeline that fires a VC the moment the underlying event or attestation is recorded are the next strategic roadmap item.

Multi-tenant isolation at the data layer

This is the architecture's headline.

The application does not rewrite queries to inject a tenant filter. It forwards the authenticated identity to OpenSearch and lets OpenSearch's Security plugin enforce Document-Level Security server-side. If the application's authorisation code is wrong, the data layer is still right.

flowchart TD
    ar(["Authenticated<br/>request"]) --> client["<b>OpenSearch client</b><br/>request-scoped"]
    client --> spi["<b>Identity forwarded</b><br/>to the data layer"]
    spi --> os["<b>OpenSearch Security</b><br/>validates identity<br/>applies tenant DLS<br/>returns matching docs only"]

    classDef accent fill:#fef3f2,stroke:#d92d20
    class spi accent

Background workloads (capture pipelines, scheduled subscriptions) use an explicit admin path — no silent privilege change at runtime.

Where it's still binary

Access today is binary per tenant: a user sees everything in their organisation or nothing. Row-level scoping (GLN-, EPC-range-, or biz-location-bound visibility) is a roadmap item.

Live events without polling

EPCIS subscriptions in OpenEPCIS are live — matches fire at the moment an event is indexed, not on a poll interval. Same model serves WebSocket clients and HTTP webhooks:

flowchart TD
    cap(["/capture"]) --> store["<b>Event store</b><br/>hash-deduplicated<br/>tenant-isolated"]
    store --> match["<b>Subscriptions matched live</b><br/>against new event"]
    match --> ws["WebSocket"]
    match --> wh["Webhook"]

Scheduled (cron-style) subscriptions sit alongside streaming for clients that want batch-style delivery — nightly digests, periodic compliance pulls — and clients opt into them explicitly.

Pagination on long-running queries survives client reconnects, so a regulator pulling six months of events can drop and resume without restarting the scan.

GS1 conformance contract

Three discipline rules apply platform-wide. Together they make every OpenEPCIS deployment conformant with GS1 EPCIS 2.0 and the GS1 Conformant Resolver standard.

Every EPC, business location, and read point is stored as a Digital Link URI (e.g. https://id.example.com/01/04012345999990/21/123456). Clients that still expect EPC URN form get it on demand at query time — but the canonical form, the form everything compares against, is Digital Link.

2. Masterdata lives on the resolver, not inside events

EPCIS documents are lean. They carry identifiers; the descriptive payload (product name, organisation details, place data, certifications) sits on the resolver and is fetched by the consumer that needs it. Masterdata is registered once via POST /products/{gtin}, POST /organizations/{gln}, POST /places/{loc} — and from that single record, the resolver auto-derives a dozen standard GS1 link types (gs1:pip, gs1:productImage, gs1:audioFile, gs1:relatedVideo, gs1:safetyInfo, gs1:certificationInfo, gs1:nutritionalInfo, gs1:instructions, gs1:recallStatus, gs1:serviceInfo, gs1:productSustainabilityInfo).

3. The deployment is self-describing

A working OpenEPCIS instance publishes the discovery document the GS1 Conformant Resolver standard expects — at the spec-mandated path /.well-known/gs1resolver. The point is that any downstream system (GS1's own Global Office resolver, a partner registry, a market-surveillance tool) can find the deployment automatically and read what it offers, instead of being hand-configured against it. That's what "GS1 Conformant" means in the standard's sense.


See also

Last updated: