---
title: "Architecture"
description: "How OpenEPCIS handles identity, isolation, events, and GS1 conformance — the four things that distinguish the platform."
canonical_url: "https://openepcis.io/docs/platform-overview/architecture"
last_updated: "2026-07-02T20:31:22.542Z"
---

![OpenEPCIS auth, DLS and reactive pipeline](/img/architecture.svg)

Four cross-cutting concerns shape every OpenEPCIS module.

1. [Authentication: one identity, three ways in](#authentication-one-identity-three-ways-in)
2. [Multi-tenant isolation at the data layer](#multi-tenant-isolation-at-the-data-layer)
3. [Live events without polling](#live-events-without-polling)
4. [GS1 conformance contract](#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](/docs/platform-overview/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.

<diagram-image alt="Request identity forwarded to OpenSearch Security for tenant DLS" src="/diagrams/platform-tenant-isolation">



</diagram-image>

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:

<diagram-image alt="Capture writes to the event store; subscriptions match live" src="/diagrams/platform-capture-subscriptions">



</diagram-image>

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.

### 1. Identifiers are GS1 Digital Link at rest

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

- [Feature matrix](/docs/platform-overview/feature-matrix) — capabilities by edition.
- [Modules → Resolver](/docs/platform-overview/modules/resolver) — the GS1 conformance surface.
- [Modules → EPCIS Events](/docs/platform-overview/modules/epcis-events) — capture, query, and streaming subscriptions in context.
- [Roadmap](/docs/platform-overview/roadmap) — Verifiable Credentials, sub-tenant scoping, event-to-resolver promotion.
