diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..06b8885
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+/.venv/
+/.vscode/
+**/__pycache__/
+*.log
+/generated/*/
+*.zip
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..431b02b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "ontology-management-base"]
+ path = ontology-management-base
+ url = git@github.com:GAIA-X4PLC-AAD/ontology-management-base.git
+[submodule "service-characteristics"]
+ path = service-characteristics
+ url = https://gitlab.com/gaia-x/technical-committee/service-characteristics-working-group/service-characteristics.git
diff --git a/README.md b/README.md
index 3c40519..54fa25c 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,201 @@
-# DEMIM Credentials
-
-## Content
-A public repository containing examples for (verifiable) credentials, associated json-ld context definitions and json manifests. The crendetials are used in the [Decentralized Digital Membership Management](https://identity.ascs.digital).
-The DID of issuers and subjects and the UUIDs of the credentials have been aligned with the content of the following example [revocation registry](https://better-call.dev/ghostnet/KT1PZFXebyGvRFG8enbuVL9nrvTi4krYqeKt/storage.)
-
-## Examples
-There are two types of json-ld examples for the credentials. The member credentials and the user credential. The member credential is used to e.g. register a company with an application like e.g. [Simpulse](https://simpulse.de) for creating the company profile with minimal validated information. The user credential is used in asc(s ecosystem applications to set initial rights and roles.
-The examples are once given with an external context definition and also with the attributes defined inline in the credential context itself. This is necessary as third-party libraries like [didkit](https://github.com/spruceid/didkit) do not allow external context loading due to security implications.
-
-## Manifests
-The manifest files are provided to render an identity card in a SSI wallet like e.g. [altme](https://altme.io) according to the identity foundation [wallet rendering specification](https://identity.foundation/wallet-rendering/).
-
-## Todos
-The context json files need to be hosted at https://schema.ascs.digital/AscsUserCredential/v1.
-All terms need to be hosted as .pdf files at https://media.ascs.digital/terms/.
-
-## Resources
-* [Implementation Guide](https://www.w3.org/TR/vc-imp-guide/#creating-new-credential-types)
-* [w3c credentials v1](https://www.w3.org/2018/credentials/v1)
-* [w3c vc-json-schema](https://w3c.github.io/vc-json-schema/)
-* [json schema specification](https://json-schema.org/specification)
-* [public schemas](https://schema.org/)
-* [transform tools](https://transform.tools/)
-* [json-ld best practices](https://w3c.github.io/json-ld-bp/?specStatus=ED)
-* [version 4 uuid](https://www.uuidgenerator.net/version4)
-* [module: pkh-tezos](https://did.js.org/docs/api/modules/pkh_tezos/)
-* [did-pkh-method-draft](https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md)
-* [Multiassets](https://multiformats.io/)
-* [Content Identifier (CID)](https://docs.ipfs.tech/concepts/content-addressing/#what-is-a-cid)
-* [POC Content Identifier](https://github.com/GAIA-X4PLC-AAD/poc-ipfs-content-identifier)
+# SimpulseID Credentials for the ENVITED Ecosystem
+
+This repository contains the **Verifiable Credential (VC)** building blocks used by
+[https://identity.ascs.digital/](https://identity.ascs.digital/)
+to manage identities and memberships in the **ENVITED Ecosystem** of the
+_Automotive Solution Center for Simulation e.V. (ASCS e.V.)_.
+
+The repository provides:
+
+- JSON-LD **contexts** for all SimpulseID credential types
+- Example **Verifiable Credentials** (VC v2, OIDC4VP-ready)
+- Example **did:web** DID documents for participants, programs, users, and admins
+- **Wallet manifests** for card rendering in SSI wallets (e.g. Altme)
+- RDF/OWL **ontologies** and SKOS vocabularies aligning with the Gaia-X Trust Framework and ENVITED Ecosystem Specifications (EVES)
+
+All of this is intended to be **publicly hostable** and consumable by wallets, verifiers and services in the ENVITED ecosystem.
+
+---
+
+## Installation
+
+If you want to use the validation scripts from 📁 `ontology-management-base/src` then you need to isntall the following dependencies:
+
+```bash
+# On Windows use python instead of python3
+sudo apt-get install python3-full
+python3 -m venv .venv/
+source .venv/bin/activate # On Windows use: source .venv/Scripts/activate
+python3 -m pip install -r ontology-management-base/requirements.txt
+python3 -m pip install -r requirements.txt
+# Example check
+python3 ontology-management-base/src/check_jsonld_against_shacl_schema.py examples/simpulseid-administrator-credential.json
+```
+
+---
+
+## Repository structure
+
+### `contexts/`
+
+JSON-LD context documents used by SimpulseID credentials, for example:
+
+- `SimpulseIdCredentials.json` – main context for:
+ - `simpulseid:Participant`
+ - `simpulseid:AscsBaseMembership`
+ - `simpulseid:AscsEnvitedMembership`
+ - `simpulseid:Administrator`
+ - `simpulseid:User`
+- `HarbourCredentials.json` – additional context for status / revocation information
+- SKOS / code list contexts (e.g. legal form vocabulary)
+
+These files are meant to be hosted under:
+
+- `https://schema.ascs.digital/...`
+
+and are referenced from the example credentials via their `@context` arrays.
+
+---
+
+### `examples/`
+
+Example **Verifiable Credentials** that show how the contexts and ontologies are intended to be used.
+
+Typical credential subjects include:
+
+- **Participant** – organizational identity (e.g. BMW)
+- **ASCS Base Membership** – base membership in ASCS e.V.
+- **ASCS ENVITED Membership** – ENVITED program membership, linked to base membership
+- **Administrator** – natural person with administrative rights in ENVITED / ASCS
+- **User** – natural person with initial roles/rights in ENVITED ecosystem applications
+
+Each VC uses:
+
+- `https://www.w3.org/ns/credentials/v2` (VC Data Model v2)
+- SimpulseID context from this repo
+- Harbour context for `credentialStatus`
+- `harbour:CRSetEntry` + `statusPurpose: "revocation"` for revocation status
+- `gx:*` terms to stay compatible with the **Gaia-X Credential Format** and Trust Framework
+
+#### `examples/did-web/`
+
+Example **did:web DID documents** that correspond to identifiers used in the credentials, e.g.:
+
+- Participants (`did:web:did.ascs.digital:participants:...`)
+- Programs (`did:web:did.ascs.digital:programs:...`)
+- Users & administrators (`did:web:did.ascs.digital:users:...`)
+- Services (`did:web:did.ascs.digital:services:...`)
+
+These demonstrate:
+
+- How organizational DIDs (ASCS, ENVITED programs, participants) are modelled
+- How user/admin DIDs are defined _without leaking personal data_
+- How to support key rotation and multiple chains (e.g. Tezos + Etherlink/EVM) via `blockchainAccountId`
+
+In production, these DID documents are intended to be hosted under:
+
+- `https://did.ascs.digital/...`
+
+---
+
+### `manifests/`
+
+Wallet **rendering manifests** for each credential type, following the
+[Decentralized Identity Foundation Wallet Rendering specification](https://identity.foundation/wallet-rendering/).
+
+They are used by wallets like **Altme** to:
+
+- Render credential “cards” with titles, subtitles and key properties
+- Show important fields such as:
+ - organization name, legal form, VAT ID
+ - membership program and hosting organization
+ - user/admin name, email, affiliation
+ - links to terms & conditions and privacy policies
+- Map `credentialSubject` properties and dates (`issuanceDate`, `expirationDate`) to UI elements
+
+Each manifest references:
+
+- A SimpulseID schema / type (e.g. `simpulseid:Participant`)
+- The issuer DID of the manifest (typically an ASCS did:web)
+
+---
+
+### `ontologies/`
+
+RDF/OWL ontologies and vocabularies that define the **formal semantics** of SimpulseID types and properties, aligned with:
+
+- **Gaia-X Trust Framework 24.11**
+- **ENVITED Ecosystem Specifications (EVES)**
+- **schema.org** and **vCard** where appropriate
+
+Key elements include:
+
+- `SimpulseIdOntology.ttl`
+
+ - Classes:
+ - `simpulseid:Participant` ⊑ `gx:LegalPerson`, `schema:Organization`
+ - `simpulseid:AscsBaseMembership`, `simpulseid:AscsEnvitedMembership` ⊑ `schema:ProgramMembership`
+ - `simpulseid:Administrator`, `simpulseid:User` ⊑ `gx:NaturalPerson`, `schema:Person`
+ - Program classes for base and ENVITED memberships
+ - Properties:
+ - `simpulseid:legalForm` → SKOS `simpulseid:LegalForm` concepts
+ - `simpulseid:termsAndConditions` → `gx:TermsAndConditions` resources
+ - `simpulseid:baseMembership` linking ENVITED membership to base membership
+ - Address modelling:
+ - `gx:Address` with **vCard** properties:
+ - `vcard:street-address`
+ - `vcard:postal-code`
+ - `vcard:locality`
+ - `vcard:region`
+ - `gx:countryCode` for ISO country codes
+
+- Legal form SKOS vocabulary (e.g. `legalForm-v1.jsonld`)
+ - Code list of legal forms (`AG`, `GmbH`, `LLC`, `BenCom`, etc.)
+ - Used via `simpulseid:LegalForm` and `simpulseid:legalForm` in credentials
+
+These ontologies are the **ground truth** for what the JSON-LD contexts and examples mean at RDF level.
+
+---
+
+## Intended usage within `https://identity.ascs.digital/`
+
+The artifacts in this repository are used by the **ENVITED Ecosystem identity services** to:
+
+- Issue and verify **Gaia-X compatible** Verifiable Credentials
+- Support **self-sovereign identity** login flows via the **SSI-to-OIDC bridge**
+- Provide consistent semantics for:
+ - ENVITED participants (organizations)
+ - ASCS base memberships
+ - ENVITED program memberships
+ - Administrative and user roles
+- Render credential cards in SSI wallets for a smooth UX
+
+Typical flow:
+
+1. A participant (organization) is onboarded and receives a **Participant VC**.
+2. The organization receives **ASCS base membership** and optionally **ENVITED membership** credentials.
+3. Individual administrators and users receive **Admin/User VCs**, bound to opaque did:web identifiers under `did.ascs.digital`.
+4. Wallets like Altme use the **contexts** and **manifests** from this repo to display these credentials.
+5. Services behind `identity.ascs.digital` use the **ontologies** and **Gaia-X compatible structures** to perform trust and membership checks.
+
+---
+
+## References
+
+Some relevant specifications and resources:
+
+- W3C Verifiable Credentials Data Model v2
+
+- W3C Verifiable Credential Vocabulary (VC v2)
+
+- Gaia-X Credential Format & Trust Framework (24.11)
+
+- DIF Wallet Rendering specification
+
+- JSON-LD 1.1 & best practices
+
+
+- JSON Schema
+
+- schema.org
+
diff --git a/contexts/AscsMemberCredential.json b/contexts/AscsMemberCredential.json
deleted file mode 100644
index 87f58f3..0000000
--- a/contexts/AscsMemberCredential.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "@version": 1.1,
- "@protected": true,
- "AscsMemberCredential": "https://schema.ascs.digital/AscsMemberCredential#",
- "AscsIssuer": {
- "@id": "https://schema.ascs.digital/AscsMemberCredential#AscsIssuer",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url"
- }
- },
- "AscsMember": {
- "@id": "https://schema.ascs.digital/AscsMemberCredential#AscsMember",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url",
- "address": "http://schema.org/address",
- "vatID": "http://schema.org/vatID",
- "isAscsMember": "http://schema.org/Boolean",
- "isEnvitedMember": "http://schema.org/Boolean",
- "privacyPolicy": "https://schema.org/termsOfService",
- "articlesOfAssociation": "https://schema.org/termsOfService",
- "contributionRules": "https://schema.org/termsOfService"
- }
- },
- "PostalAddress": {
- "@id": "http://schema.org/PostalAddress",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "streetAddress": "http://schema.org/streetAddress",
- "postalCode": "http://schema.org/postalCode",
- "addressLocality": "http://schema.org/addressLocality",
- "addressCountry": "https://schema.org/addressCountry"
- }
- }
-}
\ No newline at end of file
diff --git a/contexts/AscsUserCredential.json b/contexts/AscsUserCredential.json
deleted file mode 100644
index 2886fbc..0000000
--- a/contexts/AscsUserCredential.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "@version": 1.1,
- "@protected": true,
- "AscsUserCredential": "https://schema.ascs.digital/AscsUserCredential/v1#",
- "AscsIssuer": {
- "@id": "https://schema.ascs.digital/AscsUserCredential/v1#AscsIssuer",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url"
- }
- },
- "AscsUser": {
- "@id": "https://schema.ascs.digital/AscsUserCredential/v1#AscsUser",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "email": "https://schema.org/email",
- "address": "http://schema.org/address",
- "isAscsMember": "http://schema.org/Boolean",
- "isEnvitedMember": "http://schema.org/Boolean",
- "privacyPolicy": "https://schema.org/termsOfService"
- }
- },
- "PostalAddress": {
- "@id": "http://schema.org/PostalAddress",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "streetAddress": "http://schema.org/streetAddress",
- "postalCode": "http://schema.org/postalCode",
- "addressLocality": "http://schema.org/addressLocality",
- "addressCountry": "https://schema.org/addressCountry"
- }
- }
-}
\ No newline at end of file
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..7e275bd
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,146 @@
+# SimpulseID Credential Examples
+
+This folder contains **reference examples** for all Verifiable Credentials used in the
+ENVITED Ecosystem operated by ASCS e.V.
+
+These examples demonstrate:
+
+- the JSON-LD structure using the public contexts in `/contexts`
+- the semantics defined in `/ontologies`
+- correct use of did:web identifiers for:
+ - participants (organizations)
+ - ASCS programs (base membership, ENVITED membership)
+ - users and administrators (opaque non-PII identifiers)
+- correct Gaia-X–compatible modelling of addresses, legal forms, and terms & conditions
+- revocation status entries using the Harbour Credentials context
+
+The examples serve as a canonical blueprint for services integrating with
+****.
+
+---
+
+## Structure of the Examples
+
+### 1. Verifiable Credentials
+
+Each credential in this folder uses:
+
+- `https://www.w3.org/ns/credentials/v2` (VC Data Model v2)
+- `simpulseid_context.jsonld` (main context)
+- `harbour_context.jsonld` (credential status)
+- `harbour:CRSetEntry` with `statusPurpose: "revocation"`
+
+Types included:
+
+- **Participant Credential**
+ Identity of an organization (e.g., BMW), aligned with Gaia-X `gx:LegalPerson`.
+
+- **ASCS Base Membership Credential**
+ Proof of base membership in ASCS e.V.
+
+- **ENVITED Membership Credential**
+ Extends the base membership and links to a program DID.
+
+- **Administrator Credential**
+ Natural person with elevated rights, issued and controlled by ASCS.
+
+- **User Credential**
+ Natural person affiliated with a participant, issued by the participant’s admin.
+
+All credentials use **did:web subject identifiers** for users and admins:
+
+- opaque
+- non-PII
+- key-rotation capable
+- hosted under:
+ `https://did.ascs.digital/users/...`
+
+---
+
+## 2. did:web Documents
+
+Examples under `examples/did-web/` illustrate:
+
+- Participant DIDs controlled by organizations
+ (`did:web:did.ascs.digital:participants:ascs`, `participants:bmw`, …)
+
+- Program DIDs controlled by ASCS
+ (`did:web:did.ascs.digital:programs:ascs-base-membership`, …)
+
+- User and Administrator DIDs:
+ Opaque, privacy-preserving identifiers that _only_ expose verification keys.
+
+Each DID document supports:
+
+- Tezos account (did:pkh)
+- Etherlink/EVM account (`blockchainAccountId: eip155:42793:...`)
+- Key rotation (through verificationMethod lists)
+
+No DID document contains personal data.
+
+---
+
+## 3. Wallet Rendering Manifests
+
+The manifests in `/manifests` define how SSI wallets such as **Altme** render cards using the
+Decentralized Identity Foundation **Wallet Rendering Specification**.
+
+Each manifest:
+
+- references the correct SimpulseID credential type
+- defines which properties appear on the card
+- includes human-readable fallback titles
+- is issued by the ASCS organizational DID (`did:web:did.ascs.digital:participants:ascs`)
+
+---
+
+## 4. Notes on Issuance Model
+
+### Participant Credentials
+
+Issued by ASCS upon onboarding of an organization into the ENVITED ecosystem.
+
+### Program Membership Credentials
+
+Base membership and ENVITED membership are issued by ASCS.
+
+### Administrator Credentials
+
+Issued by ASCS to individuals acting on behalf of ASCS or participants.
+
+### User Credentials
+
+Issued by participant administrators to individuals.
+These credentials use an opaque user DID under `did.ascs.digital` to support:
+
+- privacy (no PII in DID)
+- key rotation
+- multi-chain keys (Tezos + Etherlink)
+
+---
+
+## 5. Revocation
+
+Example credentials reference a `credentialStatus` entry:
+
+- `harbour:CRSetEntry`
+- `statusPurpose: "revocation"`
+- `id` pointing to a `did:web` revocation registry fragment
+
+The DID document for the registry includes a **service endpoint** pointing to the actual registry.
+
+---
+
+## 6. Tooling
+
+You may use:
+
+- **jsonld-cli** for JSON-LD normalization and checking
+- **didkit** for signing / verifying VC Data Model v2 credentials
+- **jq** for inspection and debugging
+- **JSON Schema** for linting examples where applicable
+
+---
+
+This folder is meant as a **reference implementation** for developers integrating
+SimpulseID credentials into ENVITED applications and services.
diff --git a/examples/did-web/README.md b/examples/did-web/README.md
new file mode 100644
index 0000000..975b0c5
--- /dev/null
+++ b/examples/did-web/README.md
@@ -0,0 +1,245 @@
+# Example did:web Documents for SimpulseID
+
+This folder contains example **did:web DID documents** for entities used in the
+SimpulseID / ENVITED identity ecosystem. These examples demonstrate how program,
+participant, administrator, and user identifiers are published under the
+`did.ascs.digital` domain.
+
+All documents in this folder are **examples only** and contain placeholder JWS
+signatures (`EXAMPLE_SIGNATURE_*`) and placeholder JWK values. When deploying
+these DIDs, replace the placeholder signatures and keys with real material
+generated by the appropriate entity (ASCS or delegated admin user).
+
+---
+
+## Core Trust Model (SimpulseID Best Practice)
+
+### did:web control
+
+SimpulseID uses **did:web**, which means:
+
+- The **controller in practice is always ASCS**, because ASCS operates the
+ `did.ascs.digital` web server.
+- All DID Documents declare:
+
+ ```json
+ "controller": "did:web:did.ascs.digital:services:trust-anchor"
+ ```
+
+ This expresses that all published DIDs are governed by the **ASCS trust
+ anchor service**.
+
+### Signatures = Attestations
+
+The `proof` section in each DID Document:
+
+- **does not grant control**,
+- it **attests** that ASCS (or BMW, where relevant) approves the content.
+
+The true controlling entity for all did:web documents is always the
+`services:trust-anchor` DID, because it owns the hosting infrastructure.
+
+---
+
+## Program DID Documents
+
+Programs represent SimpulseID system-level definitions. They have stable
+identifiers:
+
+- `did:web:did.ascs.digital:programs:ascs-base-membership`
+- `did:web:did.ascs.digital:programs:ascs-envited-membership`
+- `did:web:did.ascs.digital:programs:simpulseid-user`
+- `did:web:did.ascs.digital:programs:simpulseid-administrator`
+
+They must be hosted at:
+
+- `https://did.ascs.digital/programs//did.json`
+
+Programs are always:
+
+- **controlled by**: `services:trust-anchor`
+- **signed by**: `participants:ascs`
+- **never storing personal keys**
+- **never delegating signing authority**
+
+---
+
+## Participant DIDs
+
+Participant DIDs represent **Gaia-X Legal Persons**, such as:
+
+- `did:web:did.ascs.digital:participants:ascs`
+- `did:web:did.ascs.digital:participants:bmw`
+
+Participant DIDs contain:
+
+- organizational metadata (`schema:Organization`, `gx:LegalPerson`)
+- a list of **delegated admin user keys** in `verificationMethod`
+- **active delegated admin keys** in `assertionMethod`
+- **revoked delegated admin keys** in `verificationMethod`
+ with a `"revoked"` timestamp
+
+### Important: BMW has no own cryptographic keys
+
+BMW intentionally **does not hold a participant-level key**.
+
+Instead:
+
+- **admin users sign “on behalf of BMW”**
+- BMW’s DID lists **active admin keys** under `assertionMethod`
+- Old admin keys remain listed with:
+
+ ```json
+ "revoked": ""
+ ```
+
+ but their `id` (the hash fragment) stays **unchanged** so that
+ any existing references from credentials remain valid.
+
+### Hash fragment naming convention
+
+Because DID URLs with hash fragments are referenced from credentials and other
+documents, **fragments MUST be stable over the lifetime of the key**. They
+MUST NOT be renamed when the key is revoked.
+
+SimpulseID uses a simple, incremental naming scheme per network:
+
+```uri
+#-key-
+```
+
+Examples:
+
+- `#tezos-key-1`
+- `#etherlink-key-1`
+- `#etherlink-key-2`
+
+When a key is revoked:
+
+- keep the `id` (e.g. `#etherlink-key-2`) unchanged,
+- add a `"revoked": ""` field to the corresponding
+ `verificationMethod` entry,
+- remove that key from `assertionMethod`.
+
+---
+
+## User DIDs
+
+User DIDs live at:
+
+- `did:web:did.ascs.digital:users/`
+
+Properties:
+
+- **DID controlled by**: `services:trust-anchor`
+- **keys controlled by the user**:
+
+ ```json
+ "controller": "did:web:did.ascs.digital:users/"
+ ```
+
+- used for personal authentication and signatures
+- contain no organization metadata
+
+User DID Documents are signed by ASCS as attestation of correct structure.
+
+---
+
+## Administrator DIDs
+
+An administrator is **not** a different DID type.
+
+Admin status is expressed through:
+
+- an **AdministratorCredential** issued by ASCS
+- Harbour CRSet revocation for demotion
+- BMW (or other participant) updating its participant DID to include the
+ admin user's keys in `assertionMethod`
+
+Admin promotion/demotion is reflected only in:
+
+- **credentials**
+- **participant DID** (delegated key listing)
+
+The user DID does **not** structurally change when becoming an admin.
+
+---
+
+## Trust Anchor DID
+
+`did:web:did.ascs.digital:services:trust-anchor` is the authoritative DID that:
+
+- asserts ownership of the SimpulseID infrastructure
+- governs all did:web documents hosted under `did.ascs.digital`
+- signs all program, participant, user, admin, and service DIDs
+
+All other DIDs reference:
+
+```json
+"controller": "did:web:did.ascs.digital:services:trust-anchor"
+```
+
+---
+
+## Revocation Registry DID
+
+The revocation registry lives at:
+
+- `did:web:did.ascs.digital:services:revocation-registry`
+
+It contains a `CRSetRevocationRegistryService` with:
+
+- CRSet registry API URL
+- blockchain contract URN
+- GitHub repository link
+- scientific publication reference
+
+Credentials refer to status entries using:
+
+```json
+"credentialStatus": {
+ "type": "harbour:CRSetEntry",
+ "id": "did:web:did.ascs.digital:services:revocation-registry#"
+}
+```
+
+---
+
+## Deployment Notes
+
+To deploy these DIDs in production:
+
+1. Store each DID at:
+
+ ```url
+ https://did.ascs.digital/.../did.json
+ ```
+
+2. Replace placeholder values:
+
+ - `EXAMPLE_SIGNATURE_*`
+ - JWKs
+ - blockchain addresses
+
+3. Ensure:
+
+ - MIME type `application/did+json`
+ - correct hosting paths
+ - TLS integrity
+
+4. For key rotation:
+
+ - add new admin user keys
+ - update `assertionMethod`
+ - annotate old keys with `"revoked"` (without renaming their `id`)
+
+5. For admin lifecycle:
+
+ - issue or revoke `AdministratorCredential`
+ - update participant DID key status accordingly
+
+---
+
+These did:web examples form the public reference implementation for the
+SimpulseID trust anchor, identity lifecycle, and delegation model used in the
+ENVITED Ecosystem.
diff --git a/examples/did-web/simpulseid-participant-bmw-did.json b/examples/did-web/simpulseid-participant-bmw-did.json
new file mode 100644
index 0000000..5acf70e
--- /dev/null
+++ b/examples/did-web/simpulseid-participant-bmw-did.json
@@ -0,0 +1,88 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org"
+ ],
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "alsoKnownAs": [
+ "https://did.ascs.digital/participants/bmw"
+ ],
+ "verificationMethod": [
+ {
+ "id": "did:web:did.ascs.digital:participants:bmw#tezos-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e",
+ "blockchainAccountId": "tezos:NetXnHfVqm9iesp:tz1SfdVU1mor3Sgej3FmmwMH4HM1EjTzqqeE",
+ "revoked": "2025-08-06T10:15:00Z"
+ },
+ {
+ "id": "did:web:did.ascs.digital:participants:bmw#tezos-key-2",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "blockchainAccountId": "tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8"
+ },
+ {
+ "id": "did:web:did.ascs.digital:participants:bmw#etherlink-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "blockchainAccountId": "eip155:42793:0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
+ }
+ ],
+ "assertionMethod": [
+ "did:web:did.ascs.digital:participants:bmw#tezos-key-2",
+ "did:web:did.ascs.digital:participants:bmw#etherlink-key-1"
+ ],
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:participants:bmw#org-metadata",
+ "type": "OrganizationMetadataService",
+ "serviceEndpoint": "https://www.bmwgroup.com/"
+ }
+ ],
+ "organization": {
+ "@context": [
+ "https://schema.ascs.digital/SimpulseId/v1/credentials",
+ "https://schema.org"
+ ],
+ "@id": "did:web:did.ascs.digital:participants:bmw",
+ "type": [
+ "simpulseid:Participant",
+ "gx:LegalPerson",
+ "schema:Organization"
+ ],
+ "legalName": "Bayerische Motoren Werke Aktiengesellschaft",
+ "legalForm": "AG",
+ "registrationNumber": {
+ "@type": "gx:VatID",
+ "countryCode": "DE",
+ "vatID": "DE129273398"
+ },
+ "duns": "313995269",
+ "email": "imprint@bmw.com",
+ "website": "https://www.bmwgroup.com/",
+ "legalAddress": {
+ "@type": "gx:Address",
+ "streetAddress": "Petuelring 130",
+ "postalCode": "80809",
+ "addressLocality": "München",
+ "countrySubdivisionCode": "DE-BY",
+ "country": "DE"
+ },
+ "headquartersAddress": {
+ "@type": "gx:Address",
+ "streetAddress": "Petuelring 130",
+ "postalCode": "80809",
+ "addressLocality": "München",
+ "countrySubdivisionCode": "DE-BY",
+ "country": "DE"
+ }
+ },
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:20:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_PAYLOAD_BMW"
+ }
+}
diff --git a/examples/did-web/simpulseid-program-administrator-did.json b/examples/did-web/simpulseid-program-administrator-did.json
new file mode 100644
index 0000000..aae9b00
--- /dev/null
+++ b/examples/did-web/simpulseid-program-administrator-did.json
@@ -0,0 +1,41 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials"
+ ],
+ "id": "did:web:did.ascs.digital:programs:simpulseid-administrator",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:programs:simpulseid-administrator#program-metadata",
+ "type": "ProgramMetadataService",
+ "serviceEndpoint": {
+ "@type": [
+ "schema:CreativeWork",
+ "simpulseid:AdministratorProgram"
+ ],
+ "@id": "https://did.ascs.digital/programs/simpulseid-administrator",
+ "name": "SimpulseID Administrator Program",
+ "description": "Program definition for SimpulseID administrators who manage participant onboarding, user roles, and membership credentials within the ENVITED Ecosystem.",
+ "about": "Administrator-level SimpulseID credentials with elevated permissions for managing organizations and memberships.",
+ "publisher": {
+ "@type": "schema:Organization",
+ "name": "Automotive Solution Center for Simulation e.V. (ASCS)",
+ "url": "https://ascs.digital/"
+ },
+ "inLanguage": "en",
+ "datePublished": "2025-08-05",
+ "termsOfService": "https://media.ascs.digital/terms/simpulse_id_terms_2025-08-05.pdf#cidv1",
+ "privacyPolicy": "https://media.ascs.digital/terms/administrator_privacy_policy_2025-08-05.pdf#cidv1"
+ }
+ }
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:02:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImFzY3MtZGlkLXdlYi1rZXktMSJ9.EXAMPLE_SIGNATURE_SIMPULSEID_ADMIN_PROGRAM"
+ }
+}
diff --git a/examples/did-web/simpulseid-program-ascs-base-membership-did.json b/examples/did-web/simpulseid-program-ascs-base-membership-did.json
new file mode 100644
index 0000000..09e7d8c
--- /dev/null
+++ b/examples/did-web/simpulseid-program-ascs-base-membership-did.json
@@ -0,0 +1,42 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org"
+ ],
+ "id": "did:web:did.ascs.digital:programs:ascs-base-membership",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "alsoKnownAs": [
+ "https://did.ascs.digital/programs/ascs-base-membership"
+ ],
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:programs:ascs-base-membership#program-metadata",
+ "type": "ProgramMetadataService",
+ "serviceEndpoint": "https://did.ascs.digital/programs/ascs-base-membership"
+ }
+ ],
+ "program": {
+ "@context": "https://schema.org",
+ "@type": [
+ "schema:Program",
+ "simpulseid:BaseMembershipProgram"
+ ],
+ "@id": "https://did.ascs.digital/programs/ascs-base-membership",
+ "name": "ASCS e.V. Base Membership",
+ "description": "Base membership program of the Automotive Solution Center for Simulation e.V. (ASCS e.V.).",
+ "hostingOrganization": {
+ "@id": "did:web:did.ascs.digital:participants:ascs",
+ "@type": "Organization",
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "articlesOfAssociation": "https://media.ascs.digital/terms/ascs_articles_of_association_2021-09-17.pdf#cidv1",
+ "contributionRules": "https://media.ascs.digital/terms/ascs_contribution_rules_2020-07-08.pdf#cidv1"
+ },
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:00:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_PAYLOAD"
+ }
+}
diff --git a/examples/did-web/simpulseid-program-ascs-envited-membership-did.json b/examples/did-web/simpulseid-program-ascs-envited-membership-did.json
new file mode 100644
index 0000000..8d8391a
--- /dev/null
+++ b/examples/did-web/simpulseid-program-ascs-envited-membership-did.json
@@ -0,0 +1,48 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org"
+ ],
+ "id": "did:web:did.ascs.digital:programs:ascs-envited-membership",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "alsoKnownAs": [
+ "https://did.ascs.digital/programs/ascs-envited-membership"
+ ],
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:programs:ascs-envited-membership#program-metadata",
+ "type": "ProgramMetadataService",
+ "serviceEndpoint": "https://did.ascs.digital/programs/ascs-envited-membership"
+ }
+ ],
+ "program": {
+ "@context": "https://schema.org",
+ "@type": [
+ "schema:Program",
+ "simpulseid:EnvitedMembershipProgram"
+ ],
+ "@id": "https://did.ascs.digital/programs/ascs-envited-membership",
+ "name": "ASCS e.V. ENVITED Membership",
+ "description": "ENVITED membership program of the Automotive Solution Center for Simulation e.V. (ASCS e.V.), providing access to the ENVITED ecosystem and related services.",
+ "hostingOrganization": {
+ "@id": "did:web:did.ascs.digital:participants:ascs",
+ "@type": "Organization",
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "articlesOfAssociation": "https://media.ascs.digital/terms/ascs_articles_of_association_2021-09-17.pdf#cidv1",
+ "contributionRules": "https://media.ascs.digital/terms/ascs_contribution_rules_2020-07-08.pdf#cidv1",
+ "ecosystem": {
+ "@type": "schema:DigitalEcosystem",
+ "name": "ENVITED-X Data Space",
+ "url": "https://envited-x.net/",
+ "description": "The ENVITED-X Data Space is a collaborative platform for secure data sharing and digital asset management in the ENVITED ecosystem."
+ }
+ },
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:05:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_PAYLOAD_ENVITED"
+ }
+}
diff --git a/examples/did-web/simpulseid-program-user-did.json b/examples/did-web/simpulseid-program-user-did.json
new file mode 100644
index 0000000..f27f701
--- /dev/null
+++ b/examples/did-web/simpulseid-program-user-did.json
@@ -0,0 +1,41 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials"
+ ],
+ "id": "did:web:did.ascs.digital:programs:simpulseid-user",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:programs:simpulseid-user#program-metadata",
+ "type": "ProgramMetadataService",
+ "serviceEndpoint": {
+ "@type": [
+ "schema:CreativeWork",
+ "simpulseid:UserProgram"
+ ],
+ "@id": "https://did.ascs.digital/programs/simpulseid-user",
+ "name": "SimpulseID User Program",
+ "description": "Program definition for standard SimpulseID users in the ENVITED Ecosystem. Covers basic identity, login, and membership-related functionality for natural persons.",
+ "about": "User-level SimpulseID credentials and their usage within the ENVITED data space.",
+ "publisher": {
+ "@type": "schema:Organization",
+ "name": "Automotive Solution Center for Simulation e.V. (ASCS)",
+ "url": "https://ascs.digital/"
+ },
+ "inLanguage": "en",
+ "datePublished": "2025-08-05",
+ "termsOfService": "https://media.ascs.digital/terms/simpulse_id_terms_2025-08-05.pdf#cidv1",
+ "privacyPolicy": "https://media.ascs.digital/terms/privacy_policy_2025-08-05.pdf#cidv1"
+ }
+ }
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:00:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImFzY3MtZGlkLXdlYi1rZXktMSJ9.EXAMPLE_SIGNATURE_SIMPULSEID_USER_PROGRAM"
+ }
+}
diff --git a/examples/did-web/simpulseid-service-revocation-registry-did.json b/examples/did-web/simpulseid-service-revocation-registry-did.json
new file mode 100644
index 0000000..169231d
--- /dev/null
+++ b/examples/did-web/simpulseid-service-revocation-registry-did.json
@@ -0,0 +1,29 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.reachhaven.com/Harbour/v1/credentials"
+ ],
+ "id": "did:web:did.ascs.digital:services:revocation-registry",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#crset",
+ "type": "CRSetRevocationRegistryService",
+ "serviceEndpoint": {
+ "@type": "harbour:CRSetServiceEndpoint",
+ "endpoint": "https://gatehouse.reachhaven.com/services/harbour/crset",
+ "statusPurpose": "revocation",
+ "contractURN": "urn:blockchain:eip155:42793:contract:0x646B92C8f21e55DF67E766047E4bD7bEdF8DfA14",
+ "sourceRepository": "https://github.com/ASCS-eV/smart-contracts",
+ "implementation": "https://arxiv.org/abs/2501.17089"
+ }
+ }
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:30:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImFzY3MtZXRoZXJsaW5rLWtleS0xIn0.EXAMPLE_SIGNATURE_REVOCATION_REGISTRY"
+ }
+}
diff --git a/examples/did-web/simpulseid-service-trust-anchor-did.json b/examples/did-web/simpulseid-service-trust-anchor-did.json
new file mode 100644
index 0000000..c89428f
--- /dev/null
+++ b/examples/did-web/simpulseid-service-trust-anchor-did.json
@@ -0,0 +1,54 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1",
+ "https://schema.org"
+ ],
+ "id": "did:web:did.ascs.digital:services:trust-anchor",
+ "controller": "did:web:did.ascs.digital:participants:ascs",
+ "verificationMethod": [
+ {
+ "id": "did:web:did.ascs.digital:participants:ascs#tezos-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:participants:ascs",
+ "blockchainAccountId": "tezos:NetXnHfVqm9iesp:tz1ZBYB7Lwmoc7xbwq59mHK4GbiPhfPaEo2g"
+ },
+ {
+ "id": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:participants:ascs",
+ "blockchainAccountId": "eip155:42793:0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
+ }
+ ],
+ "assertionMethod": [
+ "did:web:did.ascs.digital:participants:ascs#tezos-key-1",
+ "did:web:did.ascs.digital:participants:ascs#etherlink-key-1"
+ ],
+ "service": [
+ {
+ "id": "did:web:did.ascs.digital:services:trust-anchor#owner",
+ "type": [
+ "TrustAnchorService",
+ "OrganizationMetadataService"
+ ],
+ "serviceEndpoint": {
+ "@type": "schema:Organization",
+ "@id": "did:web:did.ascs.digital:participants:ascs",
+ "name": "Automotive Solution Center for Simulation e.V. (ASCS)",
+ "url": "https://ascs.digital/",
+ "description": "Trust anchor and operator of the SimpulseID / ENVITED identity infrastructure at did.ascs.digital.",
+ "contactPoint": {
+ "@type": "schema:ContactPoint",
+ "contactType": "support",
+ "email": "info@ascs.digital"
+ }
+ }
+ }
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:20:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:ascs#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_PAYLOAD_TRUST_ANCHOR"
+ }
+}
diff --git a/examples/did-web/simpulseid-user-21c7c8bc-6860-490b-8ec7-219c89d93e2c-did.json b/examples/did-web/simpulseid-user-21c7c8bc-6860-490b-8ec7-219c89d93e2c-did.json
new file mode 100644
index 0000000..e50013b
--- /dev/null
+++ b/examples/did-web/simpulseid-user-21c7c8bc-6860-490b-8ec7-219c89d93e2c-did.json
@@ -0,0 +1,36 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1"
+ ],
+ "id": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "verificationMethod": [
+ {
+ "id": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#tezos-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "blockchainAccountId": "tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8"
+ },
+ {
+ "id": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#etherlink-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "blockchainAccountId": "eip155:42793:0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
+ }
+ ],
+ "authentication": [
+ "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#tezos-key-1",
+ "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#etherlink-key-1"
+ ],
+ "assertionMethod": [
+ "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#tezos-key-1",
+ "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c#etherlink-key-1"
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:05:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:bmw#etherlink-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_BMW_ADMIN"
+ }
+}
diff --git a/examples/did-web/simpulseid-user-44b982bb-ae61-4f6f-899f-a0982aaf367e-did.json b/examples/did-web/simpulseid-user-44b982bb-ae61-4f6f-899f-a0982aaf367e-did.json
new file mode 100644
index 0000000..f632930
--- /dev/null
+++ b/examples/did-web/simpulseid-user-44b982bb-ae61-4f6f-899f-a0982aaf367e-did.json
@@ -0,0 +1,28 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/did/v1"
+ ],
+ "id": "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e",
+ "controller": "did:web:did.ascs.digital:services:trust-anchor",
+ "verificationMethod": [
+ {
+ "id": "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e#tezos-key-1",
+ "type": "EcdsaSecp256k1VerificationKey2019",
+ "controller": "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e",
+ "blockchainAccountId": "tezos:NetXnHfVqm9iesp:tz1SfdVU1mor3Sgej3FmmwMH4HM1EjTzqqeE"
+ }
+ ],
+ "authentication": [
+ "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e#tezos-key-1"
+ ],
+ "assertionMethod": [
+ "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e#tezos-key-1"
+ ],
+ "proof": {
+ "type": "EcdsaSecp256k1Signature2019",
+ "created": "2025-08-06T10:10:00Z",
+ "verificationMethod": "did:web:did.ascs.digital:participants:bmw#tezos-key-1",
+ "proofPurpose": "assertionMethod",
+ "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.EXAMPLE_SIGNATURE_BMW_ADMIN"
+ }
+}
diff --git a/examples/member-credential-full.json b/examples/member-credential-full.json
deleted file mode 100644
index a763fc2..0000000
--- a/examples/member-credential-full.json
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/2018/credentials/v1",
- {
- "@version": 1.1,
- "@protected": true,
- "AscsMemberCredential": "https://schema.ascs.digital/AscsMemberCredential/v1#",
- "AscsIssuer": {
- "@id": "https://schema.ascs.digital/AscsMemberCredential/v1#AscsIssuer",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url"
- }
- },
- "AscsMember": {
- "@id": "https://schema.ascs.digital/AscsMemberCredential/v1#AscsMember",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url",
- "address": "http://schema.org/address",
- "vatID": "http://schema.org/vatID",
- "isAscsMember": "http://schema.org/Boolean",
- "isEnvitedMember": "http://schema.org/Boolean",
- "privacyPolicy": "https://schema.org/termsOfService",
- "articlesOfAssociation": "https://schema.org/termsOfService",
- "contributionRules": "https://schema.org/termsOfService"
- }
- },
- "PostalAddress": {
- "@id": "http://schema.org/PostalAddress",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "streetAddress": "http://schema.org/streetAddress",
- "postalCode": "http://schema.org/postalCode",
- "addressLocality": "http://schema.org/addressLocality",
- "addressCountry": "https://schema.org/addressCountry"
- }
- }
- }
- ],
- "type": [
- "VerifiableCredential",
- "AscsMemberCredential"
- ],
- "issuanceDate": "2023-11-22T17:14:33Z",
- "expirationDate": "2102-09-15T17:14:33Z",
- "id": "urn:uuid:576fbefb-35e8-4b71-bb1a-53d1803c86de",
- "issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1ggujjYjA7oYoaZBzTg1tYSXn3VMjcgDuv",
- "type": "AscsIssuer",
- "name": "Automotive Solution Center for Simulation e.V.",
- "url": "https://identity.ascs.digital/"
- },
- "credentialSubject": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8",
- "type": "AscsMember",
- "name": "Testcompany GmbH",
- "url": "https://test.de/",
- "address": {
- "type": "PostalAddress",
- "streetAddress": "Teststraße 1",
- "postalCode": "12345",
- "addressLocality": "Munich",
- "addressCountry": "DE"
- },
- "vatID": "DE123456789",
- "isAscsMember": true,
- "isEnvitedMember": true,
- "privacyPolicy": "https://media.ascs.digital/terms/ascs_privacy_policy_2020-07-08.pdf#cidv1",
- "articlesOfAssociation": "https://media.ascs.digital/terms/ascs_articles_of_association_2021-09-17.pdf#cidv1",
- "contributionRules": "https://media.ascs.digital/terms/ascs_contribution_rules_2020-07-08.pdf#cidv1"
- }
-}
\ No newline at end of file
diff --git a/examples/member-credential.json b/examples/member-credential.json
deleted file mode 100644
index 3e7c2a7..0000000
--- a/examples/member-credential.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/2018/credentials/v1",
- "https://schema.ascs.digital/AscsMemberCredential/v1"
- ],
- "type": [
- "VerifiableCredential",
- "AscsMemberCredential"
- ],
- "issuanceDate": "2023-11-22T17:14:33Z",
- "expirationDate": "2102-09-15T17:14:33Z",
- "id": "urn:uuid:576fbefb-35e8-4b71-bb1a-53d1803c86de",
- "issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1ggujjYjA7oYoaZBzTg1tYSXn3VMjcgDuv",
- "type": "AscsIssuer",
- "name": "Automotive Solution Center for Simulation e.V.",
- "url": "https://identity.ascs.digital/"
- },
- "credentialSubject": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8",
- "type": "AscsMember",
- "name": "Testcompany GmbH",
- "url": "https://test.de/",
- "address": {
- "type": "PostalAddress",
- "streetAddress": "Teststraße 1",
- "postalCode": "12345",
- "addressLocality": "Munich",
- "addressCountry": "DE"
- },
- "vatID": "DE123456789",
- "isAscsMember": true,
- "isEnvitedMember": true,
- "privacyPolicy": "https://media.ascs.digital/terms/ascs_privacy_policy_2020-07-08.pdf#cidv1",
- "articlesOfAssociation": "https://media.ascs.digital/terms/ascs_articles_of_association_2021-09-17.pdf#cidv1",
- "contributionRules": "https://media.ascs.digital/terms/ascs_contribution_rules_2020-07-08.pdf#cidv1"
- }
-}
\ No newline at end of file
diff --git a/examples/simpulseid-administrator-credential.json b/examples/simpulseid-administrator-credential.json
new file mode 100644
index 0000000..b9ec90e
--- /dev/null
+++ b/examples/simpulseid-administrator-credential.json
@@ -0,0 +1,61 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials#",
+ "https://schema.reachhaven.com/Harbour/v1/credentials#"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "harbour:VerifiableCredential",
+ "simpulseid:AdministratorCredential"
+ ],
+ "id": "urn:uuid:9d3a0c1b-4d4e-4f9a-9b0c-1d2e3f4a5b6d",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "type": "simpulseid:Issuer",
+ "member": "did:web:did.ascs.digital:participants:ascs"
+ },
+ "issuanceDate": "2025-08-06T10:15:22Z",
+ "expirationDate": "2030-08-05T00:00:00Z",
+ "credentialSubject": {
+ "id": "did:web:did.ascs.digital:users:21c7c8bc-6860-490b-8ec7-219c89d93e2c",
+ "type": [
+ "simpulseid:Administrator",
+ "gx:NaturalPerson",
+ "schema:Person"
+ ],
+ "memberOf": [
+ "did:web:did.ascs.digital:participants:bmw",
+ "did:web:did.ascs.digital:programs:simpulseid-administrator"
+ ],
+ "givenName": "Andreas",
+ "familyName": "Admin",
+ "email": "andreas.admin@bmw.com",
+ "address": {
+ "@type": "gx:Address",
+ "streetAddress": "Petuelring 130",
+ "postalCode": "80809",
+ "locality": "München",
+ "countryCode": "DE",
+ "region": "DE21"
+ },
+ "termsAndConditions": [
+ {
+ "@id": "ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq",
+ "@type": "gx:TermsAndConditions",
+ "gx:url": {
+ "@value": "https://media.ascs.digital/terms/administrator_privacy_policy_2025-08-05.pdf",
+ "@type": "xsd:anyURI"
+ },
+ "gx:hash": "bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq"
+ }
+ ]
+ },
+ "credentialStatus": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#f8b8a8150acbbbf936df9692ed7ca809c9a6a66b190149ce9d4e9557587829ec",
+ "type": "harbour:CRSetEntry",
+ "statusPurpose": "revocation"
+ }
+ ]
+}
diff --git a/examples/simpulseid-ascs-base-membership-credential.json b/examples/simpulseid-ascs-base-membership-credential.json
new file mode 100644
index 0000000..99918b5
--- /dev/null
+++ b/examples/simpulseid-ascs-base-membership-credential.json
@@ -0,0 +1,59 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials#",
+ "https://schema.reachhaven.com/Harbour/v1/credentials#"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "harbour:VerifiableCredential",
+ "simpulseid:AscsBaseMembershipCredential"
+ ],
+ "id": "urn:uuid:7f3f7c6a-4b4d-4e9e-8f0a-9b1b2c3d4e5f",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "type": "simpulseid:Issuer",
+ "member": "did:web:did.ascs.digital:participants:ascs"
+ },
+ "issuanceDate": "2025-08-06T10:15:22Z",
+ "expirationDate": "2030-08-05T00:00:00Z",
+ "credentialSubject": {
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "type": [
+ "simpulseid:AscsBaseMembership",
+ "schema:ProgramMembership"
+ ],
+ "memberOf": [
+ "did:web:did.ascs.digital:participants:ascs",
+ "did:web:did.ascs.digital:programs:ascs-base-membership"
+ ],
+ "programName": "ASCS e.V. Base Membership",
+ "hostingOrganization": {
+ "@id": "did:web:did.ascs.digital:participants:ascs",
+ "type": [
+ "schema:Organization",
+ "gx:LegalPerson"
+ ],
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "memberSince": "2023-01-01",
+ "termsAndConditions": [
+ {
+ "@id": "ipfs://bafybeihdwdcefgh4dqkjv67uzcmw7oj5thlvxnqxnxb4ji54m72w5foemq4",
+ "@type": "gx:TermsAndConditions",
+ "gx:url": {
+ "@value": "https://media.ascs.digital/terms/base_membership_terms_2025-08-05.pdf",
+ "@type": "xsd:anyURI"
+ },
+ "gx:hash": "bafybeihdwdcefgh4dqkjv67uzcmw7oj5thlvxnqxnxb4ji54m72w5foemq4"
+ }
+ ]
+ },
+ "credentialStatus": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#6239c5abac53d33fff4a9babaaae70f6c71ac495cface74d26ac1e3affee8c61",
+ "type": "harbour:CRSetEntry",
+ "statusPurpose": "revocation"
+ }
+ ]
+}
diff --git a/examples/simpulseid-ascs-envited-membership-credential.json b/examples/simpulseid-ascs-envited-membership-credential.json
new file mode 100644
index 0000000..dd60866
--- /dev/null
+++ b/examples/simpulseid-ascs-envited-membership-credential.json
@@ -0,0 +1,61 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials#",
+ "https://schema.reachhaven.com/Harbour/v1/credentials#"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "harbour:VerifiableCredential",
+ "simpulseid:AscsEnvitedMembershipCredential"
+ ],
+ "id": "urn:uuid:8e3a0c1b-4d4e-4f9a-9b0c-1d2e3f4a5b6c",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "type": "simpulseid:Issuer",
+ "member": "did:web:did.ascs.digital:participants:ascs"
+ },
+ "issuanceDate": "2025-08-06T10:15:22Z",
+ "expirationDate": "2030-08-05T00:00:00Z",
+ "credentialSubject": {
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "type": [
+ "simpulseid:AscsEnvitedMembership",
+ "schema:ProgramMembership"
+ ],
+ "memberOf": [
+ "did:web:did.ascs.digital:participants:ascs",
+ "did:web:did.ascs.digital:programs:ascs-base-membership",
+ "did:web:did.ascs.digital:programs:ascs-envited-membership"
+ ],
+ "programName": "ASCS e.V. ENVITED Membership",
+ "hostingOrganization": {
+ "@id": "did:web:did.ascs.digital:participants:ascs",
+ "type": [
+ "schema:Organization",
+ "gx:LegalPerson"
+ ],
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "memberSince": "2023-01-01",
+ "baseMembershipCredential": "urn:uuid:7f3f7c6a-4b4d-4e9e-8f0a-9b1b2c3d4e5f",
+ "termsAndConditions": [
+ {
+ "@id": "ipfs://bafybeifx7yeb55armcsxwwitkymga5xf53dxiarykms3ygqic7jc6he43m",
+ "@type": "gx:TermsAndConditions",
+ "gx:url": {
+ "@value": "https://media.ascs.digital/terms/envited_membership_terms_2025-08-05.pdf",
+ "@type": "xsd:anyURI"
+ },
+ "gx:hash": "bafybeifx7yeb55armcsxwwitkymga5xf53dxiarykms3ygqic7jc6he43m"
+ }
+ ]
+ },
+ "credentialStatus": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#b8ca800e6cf1807ed35c682ca7c84f07df55ad53a20784fe0ee896f279a6a047",
+ "type": "harbour:CRSetEntry",
+ "statusPurpose": "revocation"
+ }
+ ]
+}
diff --git a/examples/simpulseid-participant-credential.json b/examples/simpulseid-participant-credential.json
new file mode 100644
index 0000000..39160ab
--- /dev/null
+++ b/examples/simpulseid-participant-credential.json
@@ -0,0 +1,72 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials#",
+ "https://schema.reachhaven.com/Harbour/v1/credentials#"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "harbour:VerifiableCredential",
+ "simpulseid:ParticipantCredential"
+ ],
+ "id": "urn:uuid:576fbefb-35e8-4b71-bb1a-53d1803c86de",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "type": "simpulseid:Issuer",
+ "member": "did:web:did.ascs.digital:participants:ascs"
+ },
+ "issuanceDate": "2025-08-06T10:15:22Z",
+ "expirationDate": "2030-08-05T00:00:00Z",
+ "credentialSubject": {
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "type": [
+ "simpulseid:Participant",
+ "gx:LegalPerson",
+ "schema:Organization"
+ ],
+ "legalName": "Bayerische Motoren Werke Aktiengesellschaft",
+ "legalForm": "AG",
+ "registrationNumber": {
+ "@type": "gx:VatID",
+ "countryCode": "DE",
+ "vatID": "DE129273398"
+ },
+ "duns": "313995269",
+ "email": "imprint@bmw.com",
+ "website": "https://www.bmwgroup.com/",
+ "legalAddress": {
+ "@type": "gx:Address",
+ "streetAddress": "Petuelring 130",
+ "postalCode": "80809",
+ "locality": "München",
+ "countryCode": "DE",
+ "region": "DE21"
+ },
+ "headquartersAddress": {
+ "@type": "gx:Address",
+ "streetAddress": "Petuelring 130",
+ "postalCode": "80809",
+ "locality": "München",
+ "countryCode": "DE",
+ "region": "DE21"
+ },
+ "termsAndConditions": [
+ {
+ "@id": "ipfs://bafybeigdyj2p5rxbqzqx3g2m5qw4ftheq7l3z5v7j7nw2q7q5q5zq7q5q4",
+ "@type": "gx:TermsAndConditions",
+ "gx:url": {
+ "@value": "https://media.ascs.digital/terms/simpulse_id_terms_2025-08-05.pdf",
+ "@type": "xsd:anyURI"
+ },
+ "gx:hash": "bafybeigdyj2p5rxbqzqx3g2m5qw4ftheq7l3z5v7j7nw2q7q5q5zq7q5q4"
+ }
+ ]
+ },
+ "credentialStatus": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#608101d3a8430e61f60dcf1be0f42ab3ceb52b6abffb9f75b6f36c80362fc25a",
+ "type": "harbour:CRSetEntry",
+ "statusPurpose": "revocation"
+ }
+ ]
+}
diff --git a/examples/simpulseid-user-credential.json b/examples/simpulseid-user-credential.json
new file mode 100644
index 0000000..3a11ab4
--- /dev/null
+++ b/examples/simpulseid-user-credential.json
@@ -0,0 +1,53 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/credentials/v2",
+ "https://schema.ascs.digital/SimpulseId/v1/credentials#",
+ "https://schema.reachhaven.com/Harbour/v1/credentials#"
+ ],
+ "type": [
+ "VerifiableCredential",
+ "harbour:VerifiableCredential",
+ "simpulseid:UserCredential"
+ ],
+ "id": "urn:uuid:6a0e7e84-2e88-4b9a-977b-9e92a6d87a0f",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "type": "simpulseid:Participant",
+ "member": "did:web:did.ascs.digital:participants:bmw"
+ },
+ "issuanceDate": "2025-08-06T10:15:22Z",
+ "expirationDate": "2030-08-05T00:00:00Z",
+ "credentialSubject": {
+ "id": "did:web:did.ascs.digital:users:44b982bb-ae61-4f6f-899f-a0982aaf367e",
+ "type": [
+ "simpulseid:User",
+ "gx:NaturalPerson",
+ "schema:Person"
+ ],
+ "memberOf": [
+ "did:web:did.ascs.digital:participants:bmw",
+ "did:web:did.ascs.digital:programs:simpulseid-user"
+ ],
+ "givenName": "Max",
+ "familyName": "Mustermann",
+ "email": "max.mustermann@bmw.com",
+ "termsAndConditions": [
+ {
+ "@id": "ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq",
+ "@type": "gx:TermsAndConditions",
+ "gx:url": {
+ "@value": "https://media.ascs.digital/terms/privacy_policy_2025-08-05.pdf",
+ "@type": "xsd:anyURI"
+ },
+ "gx:hash": "bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq"
+ }
+ ]
+ },
+ "credentialStatus": [
+ {
+ "id": "did:web:did.ascs.digital:services:revocation-registry#9396f1d42a2a5eaa93a1a3211e4b0db85c8185d533b835984cd98d24ecba6440",
+ "type": "harbour:CRSetEntry",
+ "statusPurpose": "revocation"
+ }
+ ]
+}
diff --git a/examples/user-credential-full.json b/examples/user-credential-full.json
deleted file mode 100644
index 574d2e4..0000000
--- a/examples/user-credential-full.json
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/2018/credentials/v1",
- {
- "@version": 1.1,
- "@protected": true,
- "AscsUserCredential": "https://schema.ascs.digital/AscsUserCredential/v1#",
- "AscsIssuer": {
- "@id": "https://schema.ascs.digital/AscsUserCredential/v1#AscsIssuer",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "url": "https://schema.org/url"
- }
- },
- "AscsUser": {
- "@id": "https://schema.ascs.digital/AscsUserCredential/v1#AscsUser",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "name": "https://schema.org/name",
- "email": "https://schema.org/email",
- "address": "http://schema.org/address",
- "isAscsMember": "http://schema.org/Boolean",
- "isEnvitedMember": "http://schema.org/Boolean",
- "privacyPolicy": "https://schema.org/termsOfService"
- }
- },
- "PostalAddress": {
- "@id": "http://schema.org/PostalAddress",
- "@context": {
- "@version": 1.1,
- "@protected": true,
- "streetAddress": "http://schema.org/streetAddress",
- "postalCode": "http://schema.org/postalCode",
- "addressLocality": "http://schema.org/addressLocality",
- "addressCountry": "https://schema.org/addressCountry"
- }
- }
- }
- ],
- "type": [
- "VerifiableCredential",
- "AscsUserCredential"
- ],
- "issuanceDate": "2023-11-22T17:14:33Z",
- "expirationDate": "2102-09-15T17:14:33Z",
- "id": "urn:uuid:cf1f329d-9c4c-458e-ba0a-a762a296b79c",
- "issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8",
- "type": "AscsIssuer",
- "name": "Testcompany GmbH",
- "url": "https://test.de/"
- },
- "credentialSubject": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1SfdVU1mor3Sgej3FmmwMH4HM1EjTzqqeE",
- "type": "AscsUser",
- "name": "User",
- "email": "mailto:user@test.de",
- "address": {
- "type": "PostalAddress",
- "streetAddress": "Teststraße 1",
- "postalCode": "12345",
- "addressLocality": "Munich",
- "addressCountry": "DE"
- },
- "isAscsMember": true,
- "isEnvitedMember": true,
- "privacyPolicy": "https://media.ascs.digital/terms/ascs_privacy_policy_2020-07-08.pdf#cidv1"
- }
-}
\ No newline at end of file
diff --git a/examples/user-credential.json b/examples/user-credential.json
deleted file mode 100644
index dfbbc09..0000000
--- a/examples/user-credential.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "@context": [
- "https://www.w3.org/2018/credentials/v1",
- "https://schema.ascs.digital/AscsUserCredential/v1"
- ],
- "type": [
- "VerifiableCredential",
- "AscsUserCredential"
- ],
- "issuanceDate": "2023-11-22T17:14:33Z",
- "expirationDate": "2102-09-15T17:14:33Z",
- "id": "urn:uuid:cf1f329d-9c4c-458e-ba0a-a762a296b79c",
- "issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8",
- "type": "AscsIssuer",
- "name": "Testcompany GmbH",
- "url": "https://test.de/"
- },
- "credentialSubject": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1SfdVU1mor3Sgej3FmmwMH4HM1EjTzqqeE",
- "type": "AscsUser",
- "name": "User",
- "email": "mailto:user@test.de",
- "address": {
- "type": "PostalAddress",
- "streetAddress": "Teststraße 1",
- "postalCode": "12345",
- "addressLocality": "Munich",
- "addressCountry": "DE"
- },
- "isAscsMember": true,
- "isEnvitedMember": true,
- "privacyPolicy": "https://media.ascs.digital/terms/ascs_privacy_policy_2020-07-08.pdf#cidv1"
- }
-}
\ No newline at end of file
diff --git a/generated/README_contexts.md b/generated/README_contexts.md
new file mode 100644
index 0000000..1651684
--- /dev/null
+++ b/generated/README_contexts.md
@@ -0,0 +1,151 @@
+# JSON-LD Contexts for SimpulseID Credentials
+
+This folder contains the JSON-LD context documents used by SimpulseID
+credentials in the ENVITED Ecosystem. These contexts define how JSON properties,
+classes, and identifiers in credentials are expanded into stable IRIs and how
+they map to the SimpulseID ontology, Gaia-X definitions, schema.org and vCard.
+
+All contexts in this folder are intended to be hosted under:
+
+```txt
+
+```
+
+with the following MIME type:
+
+```txt
+Content-Type: application/ld+json
+```
+
+Hosting contexts in this way ensures:
+
+- OIDC4VP clients can dereference the contexts reliably
+- SSI wallets can resolve schemas consistently
+- JSON-LD processors interpret IRIs deterministically
+
+---
+
+## Included Contexts
+
+### `SimpulseIdCredentials.json`
+
+The main JSON-LD context.
+It defines all SimpulseID-specific classes and properties:
+
+- Participant (`simpulseid:Participant`)
+- ASCS Base Membership (`simpulseid:AscsBaseMembership`)
+- ASCS ENVITED Membership (`simpulseid:AscsEnvitedMembership`)
+- Administrator (`simpulseid:Administrator`)
+- User (`simpulseid:User`)
+
+It maps JSON fields to:
+
+- SimpulseID ontology terms
+- Gaia-X identity primitives (`gx:LegalPerson`, `gx:Address`, `gx:VatID`, etc.)
+- vCard properties for address modelling (`street-address`, `locality`, `region`)
+- Legal form vocabulary entries
+- Terms & conditions references (`simpulseid:termsAndConditions`)
+
+The context uses `@protected: true` to guarantee a stable schema.
+
+---
+
+### `HarbourCredentials.json`
+
+Context for revocation metadata following the Harbour Status model.
+
+Defines:
+
+- `harbour:CRSetEntry`
+- `statusPurpose` (typed as `xsd:string`)
+- `harbour:VerifiableCredential`
+
+Each SimpulseID credential uses this context in `credentialStatus`.
+
+---
+
+### `legalForm-v1.jsonld`
+
+A SKOS vocabulary for legal forms, containing entries such as:
+
+- AG
+- GmbH
+- LLC
+- CIC
+- BenCom
+- etc.
+
+Each entry is a `skos:Concept` inside the `simpulseid:LegalForm` concept scheme.
+
+Credentials reference these IRIs like:
+
+```txt
+
+```
+
+---
+
+## Why Gaia-X Terms Are Used (`gx:*`)
+
+The Gaia-X Trust Framework provides well-defined, audited semantic identifiers
+for legal entities, natural persons, addresses, registration numbers and
+terms & conditions.
+
+SimpulseID reuses these Gaia-X IRIs because:
+
+1. **Strong interoperability**
+ Credentials can be reused across Gaia-X–aligned ecosystems and data spaces.
+
+2. **Regulatory alignment**
+ Gaia-X definitions follow European governance requirements.
+
+3. **Semantic completeness**
+ Classes such as `gx:LegalPerson`, `gx:NaturalPerson`, `gx:Address`,
+ `gx:VatID` exactly match ENVITED membership needs.
+
+4. **RDF correctness**
+ JSON-LD expansion produces a clean RDF graph aligned with the Gaia-X
+ Credential Format.
+
+5. **Reusability in EVES**
+ The ENVITED Ecosystem Specifications intentionally align with Gaia-X, so
+ reusing these IRIs avoids duplicating definitions.
+
+---
+
+## How These Contexts Work Together
+
+- `SimpulseIdCredentials.json`
+ → Defines SimpulseID credential structure
+
+- `HarbourCredentials.json`
+ → Adds revocation support fully compatible with VC Data Model v2
+
+- `legalForm-v1.jsonld`
+ → Provides the vocabulary for legal form codes
+
+- Gaia-X IRIs
+ → Provide standardized identity semantics
+
+Together, they allow wallets, OIDC bridges, and verifiers to interpret
+SimpulseID credentials correctly.
+
+---
+
+## Relation to Ontologies
+
+These contexts directly reference terms defined in:
+
+```txt
+/ontologies/SimpulseIdOntology.ttl
+```
+
+and the legal form code list.
+
+The ontology defines **semantics**,
+the contexts define **how JSON maps to those semantics**.
+
+---
+
+These context documents form the foundation for all credentials issued or
+verified by **identity.ascs.digital** and the broader ENVITED Ecosystem.
diff --git a/generated/README_ontologies.md b/generated/README_ontologies.md
new file mode 100644
index 0000000..3326167
--- /dev/null
+++ b/generated/README_ontologies.md
@@ -0,0 +1,66 @@
+# SimpulseID Ontologies
+
+This folder contains the RDF/OWL ontologies that define the formal semantics
+for all classes and properties used in SimpulseID credentials. These ontologies
+provide the canonical IRIs that are referenced by the JSON-LD contexts in
+`../contexts` and interpreted by verifiers, wallets, and backend services.
+
+## Purpose
+
+The ontology defines:
+
+- The **SimpulseID credential model** (Participant, Memberships, User, Admin)
+- The **relationships** between these classes
+- Alignment with:
+ - **Gaia‑X Trust Framework**
+ - **schema.org**
+ - **vCard**
+ - **SKOS vocabularies** (e.g., legal form code list)
+
+By using shared IRIs and clear semantics, SimpulseID ensures interoperability
+across the ENVITED Ecosystem and other data spaces.
+
+## Files
+
+### `SimpulseIdOntology.ttl`
+
+Defines:
+
+- Classes:
+
+ - `simpulseid:Participant`
+ - `simpulseid:AscsBaseMembership`
+ - `simpulseid:AscsEnvitedMembership`
+ - `simpulseid:Administrator`
+ - `simpulseid:User`
+ - Program classes for Base and ENVITED memberships
+
+- Properties:
+ - `simpulseid:legalForm`
+ - `simpulseid:termsAndConditions`
+ - `simpulseid:baseMembership`
+ - Address fields using Gaia‑X and vCard IRIs
+ - Organizational membership relations (`schema:memberOf`)
+
+### Legal Form Vocabulary
+
+The ontology references the SKOS vocabulary defined in:
+
+```txt
+../contexts/legalForm-v1.jsonld
+```
+
+This vocabulary provides IRIs for legal forms (AG, GmbH, LLC, CIC, etc.).
+
+## Why Ontologies Matter
+
+- JSON-LD contexts define _mapping_
+- Ontologies define _meaning_
+- Together, they create a robust, machine‑interpretable credential model
+
+These ontologies are essential for:
+
+- Trust interoperability
+- Schema validation
+- EVES compliance
+- Gaia‑X compatibility
diff --git a/linkml/core.yaml b/linkml/core.yaml
new file mode 100644
index 0000000..96f7c80
--- /dev/null
+++ b/linkml/core.yaml
@@ -0,0 +1,30 @@
+id: https://schema.ascs.digital/Core/linkml/v1#Core
+name: core
+description: >
+ Shared LinkML core definitions to avoid URI conflicts across imported schemas.
+ This schema defines common slots once (e.g., id/type) with stable URIs.
+ JSON-LD keyword aliasing (id -> @id, type -> @type) is applied in the
+ generation script as a post-processing step.
+
+prefixes:
+ linkml: https://w3id.org/linkml/
+ xsd: http://www.w3.org/2001/XMLSchema#
+
+default_prefix: linkml
+default_range: string
+
+imports:
+ - linkml:types
+
+slots:
+ id:
+ description: Stable identifier slot (post-processed to JSON-LD @id in context output).
+ slot_uri: linkml:id
+ required: true
+ range: uri
+
+ type:
+ description: Stable type slot (post-processed to JSON-LD @type in context output).
+ slot_uri: linkml:type
+ multivalued: true
+ range: uri
diff --git a/linkml/harbour.yaml b/linkml/harbour.yaml
new file mode 100644
index 0000000..e6ac635
--- /dev/null
+++ b/linkml/harbour.yaml
@@ -0,0 +1,78 @@
+id: https://schema.reachhaven.com/Harbour/linkml/v1#Harbour
+name: harbour
+description: >
+ LinkML schema for Harbour credentials vocabulary, aligned with the
+ HarbourCredentials JSON-LD context.
+
+prefixes:
+ linkml: https://w3id.org/linkml/
+ harbour: https://schema.reachhaven.com/Harbour/v1/credentials#
+ xsd: http://www.w3.org/2001/XMLSchema#
+ vcs: https://www.w3.org/ns/credentials/status#
+
+default_prefix: harbour
+default_range: string
+
+imports:
+ - linkml:types
+ - ./core
+
+slots:
+ status_purpose:
+ description: >
+ Status purpose as defined by VC Status (e.g., "revocation").
+ slot_uri: vcs:statusPurpose
+ range: string
+ required: false
+
+ endpoint:
+ description: Service endpoint IRI.
+ slot_uri: harbour:endpoint
+ range: uri
+ required: false
+
+ contract_urn:
+ description: Contract identifier (URN/IRI) for the revocation registry implementation.
+ slot_uri: harbour:contractURN
+ range: uri
+ required: false
+
+ source_repository:
+ description: Source repository IRI (e.g., Git repository URL) for the implementation.
+ slot_uri: harbour:sourceRepository
+ range: uri
+ required: false
+
+ implementation:
+ description: Implementation identifier IRI (e.g., software package or artifact reference).
+ slot_uri: harbour:implementation
+ range: uri
+ required: false
+
+classes:
+ HarbourVerifiableCredential:
+ description: >
+ Marker class used in Harbour contexts to identify a Verifiable Credential
+ using the Harbour vocabulary.
+ class_uri: harbour:VerifiableCredential
+
+ CRSetEntry:
+ description: >
+ Credential status list entry (typically used in vc:credentialStatus),
+ aligned with harbour:CRSetEntry.
+ class_uri: harbour:CRSetEntry
+ slots:
+ - id
+ - type
+ - status_purpose
+
+ CRSetServiceEndpoint:
+ description: >
+ Service endpoint descriptor for a credential revocation set service.
+ class_uri: harbour:CRSetServiceEndpoint
+ slots:
+ - endpoint
+ - status_purpose
+ - contract_urn
+ - source_repository
+ - implementation
diff --git a/linkml/simpulseid.yaml b/linkml/simpulseid.yaml
new file mode 100644
index 0000000..a637b58
--- /dev/null
+++ b/linkml/simpulseid.yaml
@@ -0,0 +1,529 @@
+id: https://schema.ascs.digital/SimpulseId/linkml/v1#SimpulseId
+name: simpulseid
+description: >
+ LinkML schema for SimpulseID credentials, aligned with the SimpulseIdOntology,
+ SimpulseIdCredentials JSON-LD context, and Gaia-X 24.06 LinkML models.
+ This schema is intended as the single source of truth to generate JSON-LD
+ contexts, SHACL shapes, and OWL ontologies for SimpulseID credential types.
+
+prefixes:
+ linkml: https://w3id.org/linkml/
+ simpulseid: https://schema.ascs.digital/SimpulseId/v1/credentials#
+ harbour: https://schema.reachhaven.com/Harbour/v1/credentials#
+ vcs: https://www.w3.org/ns/credentials/status#
+ gx: https://w3id.org/gaia-x/development#
+ schema: http://schema.org/
+ vc: https://www.w3.org/2018/credentials#
+ vcard: http://www.w3.org/2006/vcard/ns#
+ xsd: http://www.w3.org/2001/XMLSchema#
+ skos: http://www.w3.org/2004/02/skos/core#
+ lf: https://schema.ascs.digital/SimpulseId/v1/legalForm#
+
+default_prefix: simpulseid
+default_range: string
+
+imports:
+ - linkml:types
+ - ./core
+ # Single entry point for Gaia-X: pulls in Address, LegalPerson, LegalDocument,
+ # Issuer, Participant, TermsAndConditions, etc. via gaia-x.yaml.
+ - ../service-characteristics/linkml/gaia-x
+ - ./harbour
+
+slots:
+ # NOTE:
+ # id and type are intentionally NOT defined here.
+ # They must be provided by ./core to avoid merge conflicts.
+
+ issuer:
+ description: >
+ Issuer of the Verifiable Credential. This slot uses the VC vocabulary
+ predicate vc:issuer and points to a SimpulseID-specific Issuer class.
+ That Issuer class is modelled as a subclass of the imported Gaia-X Issuer
+ definition to preserve Gaia-X semantics while allowing SimpulseID typing
+ (simpulseid:Issuer) in the credential payload.
+ slot_uri: vc:issuer
+ range: SimpulseIdIssuer
+ required: true
+ aliases: [issuer]
+
+ issuance_date:
+ description: >
+ Date-time at which the credential was issued.
+ slot_uri: vc:issuanceDate
+ range: datetime
+ required: true
+ aliases: [issuanceDate]
+
+ expiration_date:
+ description: >
+ Date-time at which the credential expires, if any.
+ slot_uri: vc:expirationDate
+ range: datetime
+ required: false
+ aliases: [expirationDate]
+
+ credential_subject:
+ description: >
+ Subject of the Verifiable Credential.
+ slot_uri: vc:credentialSubject
+ range: CredentialSubject
+ required: true
+ aliases: [credentialSubject]
+
+ credential_status:
+ description: >
+ Status entry or entries associated with the Verifiable Credential
+ (e.g. Harbour CRSet entries).
+ slot_uri: vc:credentialStatus
+ range: CredentialStatusEntry
+ multivalued: true
+ required: false
+ aliases: [credentialStatus]
+
+ # Common person-related slots (schema.org)
+
+ given_name:
+ description: Given name of a natural person.
+ slot_uri: schema:givenName
+ range: string
+ aliases: [givenName]
+
+ family_name:
+ description: Family name of a natural person.
+ slot_uri: schema:familyName
+ range: string
+ aliases: [familyName]
+
+ email:
+ description: Email address of a person or organization.
+ slot_uri: schema:email
+ range: string
+ aliases: [email]
+
+ # Membership / program slots (schema.org)
+
+ member_of:
+ description: >
+ Membership relation pointing from a person or membership to a participant
+ or program (DID or IRI).
+ slot_uri: schema:memberOf
+ multivalued: true
+ range: uri
+ aliases: [memberOf]
+
+ program_name:
+ description: Human-readable name of the program (e.g. ASCS Base Membership).
+ slot_uri: schema:programName
+ range: string
+ aliases: [programName]
+
+ hosting_organization:
+ description: >
+ Organization hosting the membership program (e.g. ASCS e.V. as
+ hosting organization of ENVITED).
+ slot_uri: schema:hostingOrganization
+ range: SimpulseidParticipant
+ aliases: [hostingOrganization]
+
+ member_since:
+ description: >
+ Date on which the membership became effective.
+ slot_uri: schema:memberSince
+ range: date
+ aliases: [memberSince]
+
+ # Address (Gaia-X aligned) – pretty keys via aliases
+
+ address:
+ description: >
+ Address of a natural person. This slot is aligned with Gaia-X by using
+ gx:address as predicate and a SimpulseID Address class that subclasses
+ the imported Gaia-X Address definition. Individual address fields use
+ vCard predicates and Gaia-X predicates, while JSON keys remain wallet-
+ friendly (streetAddress, postalCode, locality, countryCode, region).
+ slot_uri: gx:address
+ range: SimpulseIdAddress
+ required: false
+ aliases: [address]
+
+ street_address:
+ description: >
+ Street address, including street name and house number. Mapped to
+ vcard:street-address while preserving the JSON key streetAddress.
+ slot_uri: vcard:street-address
+ range: string
+ aliases: [streetAddress]
+
+ postal_code:
+ description: >
+ Postal code / ZIP code. Mapped to vcard:postal-code while preserving
+ the JSON key postalCode.
+ slot_uri: vcard:postal-code
+ range: string
+ aliases: [postalCode]
+
+ locality:
+ description: >
+ Locality / city. Mapped to vcard:locality.
+ slot_uri: vcard:locality
+ range: string
+ aliases: [locality]
+
+ country_code:
+ description: >
+ ISO 3166-1 alpha-2 country code as required by Gaia-X (gx:countryCode).
+ Preserves the JSON key countryCode.
+ slot_uri: gx:countryCode
+ range: string
+ required: true
+ aliases: [countryCode]
+
+ region:
+ description: >
+ Region code, typically NUTS2 (e.g. DE21 for Oberbayern) as used in Gaia-X
+ (gx:region). Preserves the JSON key region.
+ slot_uri: gx:region
+ range: string
+ required: false
+ aliases: [region]
+
+ # Organization / participant related slots (Gaia-X-aligned)
+
+ legal_name:
+ description: >
+ Full legal name of the organization (e.g. Bayerische Motoren Werke
+ Aktiengesellschaft). Uses the Gaia-X legalName property.
+ slot_uri: gx:legalName
+ range: string
+ aliases: [legalName]
+
+ legal_form:
+ description: >
+ Legal form of a legal person using the Gaia-X property gx:legalForm.
+ Values are IRIs from the SimpulseID legal form vocabulary (lf:*),
+ modelled directly in this LinkML schema (no standalone JSON-LD file).
+ JSON key preserved as legalForm.
+ slot_uri: gx:legalForm
+ range: SimpulseIdLegalForm
+ required: false
+ aliases: [legalForm]
+
+ legal_address:
+ description: >
+ Legal address of the organization, as required by the Gaia-X Trust
+ Framework (gx:legalAddress).
+ slot_uri: gx:legalAddress
+ range: SimpulseIdAddress
+ required: true
+ aliases: [legalAddress]
+
+ headquarters_address:
+ description: >
+ Headquarters address of the organization, optional according to the
+ Gaia-X Trust Framework (gx:headquartersAddress).
+ slot_uri: gx:headquartersAddress
+ range: SimpulseIdAddress
+ required: false
+ aliases: [headquartersAddress]
+
+ # Terms and Conditions / agreements (Gaia-X LegalDocument)
+
+ terms_and_conditions:
+ description: >
+ References to legal documents representing Terms and Conditions records.
+ Implemented using Gaia-X LegalDocument as range and gx:termsAndConditions
+ as the property IRI. JSON key preserved as termsAndConditions.
+ slot_uri: gx:termsAndConditions
+ range: LegalDocument
+ multivalued: true
+ aliases: [termsAndConditions]
+
+ # Base membership credential cross-reference
+
+ base_membership_credential:
+ description: >
+ Reference from an ENVITED membership subject to its underlying base
+ membership credential (URN of the credential).
+ slot_uri: simpulseid:baseMembershipCredential
+ range: uri
+ aliases: [baseMembershipCredential]
+
+enums:
+ SimpulseIdLegalForm:
+ description: >
+ SimpulseID legal form vocabulary modelled as a controlled code list.
+ Each value is expressed as an IRI in the lf: namespace. This replaces the
+ previously standalone JSON-LD vocabulary file while keeping stable,
+ dereferenceable identifiers for legal forms.
+ permissible_values:
+ LLC:
+ description: Limited Liability Company
+ meaning: lf:LLC
+ Corporation:
+ description: Corporation
+ meaning: lf:Corporation
+ LimitedPartnership:
+ description: Limited Partnership
+ meaning: lf:LimitedPartnership
+ NonprofitCorporation:
+ description: Nonprofit Corporation
+ meaning: lf:NonprofitCorporation
+ GmbH:
+ description: Gesellschaft mit beschränkter Haftung / Limited liability company (GmbH)
+ meaning: lf:GmbH
+ AG:
+ description: Aktiengesellschaft / Stock corporation (AG)
+ meaning: lf:AG
+ Einzelunternehmen:
+ description: Einzelunternehmen / Sole proprietorship
+ meaning: lf:Einzelunternehmen
+ GbR:
+ description: Gesellschaft bürgerlichen Rechts / Civil-law partnership (GbR)
+ meaning: lf:GbR
+ OHG:
+ description: Offene Handelsgesellschaft / General partnership (OHG)
+ meaning: lf:OHG
+ KG:
+ description: Kommanditgesellschaft / Limited partnership (KG)
+ meaning: lf:KG
+ UG:
+ description: Unternehmergesellschaft (haftungsbeschränkt) / Entrepreneurial company (UG)
+ meaning: lf:UG
+ SoleTrader:
+ description: Sole Trader
+ meaning: lf:SoleTrader
+ UnincorporatedAssociation:
+ description: Unincorporated Association
+ meaning: lf:UnincorporatedAssociation
+ Partnership:
+ description: Partnership
+ meaning: lf:Partnership
+ Trust:
+ description: Trust
+ meaning: lf:Trust
+ LimitedCompany:
+ description: Limited Company
+ meaning: lf:LimitedCompany
+ LLP:
+ description: Limited Liability Partnership
+ meaning: lf:LLP
+ CIC:
+ description: Community Interest Company (CIC)
+ meaning: lf:CIC
+ CIO:
+ description: Charitable Incorporated Organisation (CIO)
+ meaning: lf:CIO
+ CooperativeSociety:
+ description: Co-operative Society
+ meaning: lf:CooperativeSociety
+ BenCom:
+ description: Community Benefit Society (BenCom)
+ meaning: lf:BenCom
+ other:
+ description: Other / unspecified legal form
+ meaning: lf:other
+
+classes:
+ #############################################
+ # Option A: Gaia-X reuse + SimpulseID subclasses
+ #############################################
+
+ SimpulseIdIssuer:
+ description: >
+ SimpulseID issuer class used in VC instances (simpulseid:Issuer).
+ This class is a subclass of the imported Gaia-X Issuer definition,
+ enabling alignment with Gaia-X semantics while allowing SimpulseID-specific
+ typing in credentials. In JSON, the issuer object can therefore use
+ "type": "simpulseid:Issuer".
+ is_a: Issuer
+ class_uri: simpulseid:Issuer
+
+ SimpulseIdAddress:
+ description: >
+ Address class for SimpulseID credentials. It subclasses the imported
+ Gaia-X Address definition and uses gx:Address as RDF class. Address
+ fields are mapped to Gaia-X/vCard predicates through slot_uri, while the
+ JSON keys remain wallet-friendly through LinkML aliases.
+ is_a: Address
+ class_uri: gx:Address
+ slots:
+ - street_address
+ - postal_code
+ - locality
+ - country_code
+ - region
+
+ #############################################
+ # Core abstractions
+ #############################################
+
+ CredentialSubject:
+ description: >
+ Abstract base class for all SimpulseID credential subject entities
+ (participants, memberships, users, administrators).
+ abstract: true
+ class_uri: schema:Thing
+ slots:
+ - id
+ - type
+ - terms_and_conditions
+
+ VerifiableCredential:
+ description: >
+ Base class for SimpulseID Verifiable Credentials.
+ class_uri: vc:VerifiableCredential
+ slots:
+ - id
+ - type
+ - issuer
+ - issuance_date
+ - expiration_date
+ - credential_subject
+ - credential_status
+
+ CredentialStatusEntry:
+ description: >
+ Status entry describing revocation state, typically a Harbour
+ CRSetEntry.
+ class_uri: schema:Thing
+ slots:
+ - id
+ - type
+ # Harbour-specific properties stay in Harbour’s own context/ontology.
+
+ #############################################
+ # Participant / person classes
+ #############################################
+
+ SimpulseidParticipant:
+ description: >
+ SimpulseID Participant entity representing a legal person taking part
+ in SimpulseID programs. It specializes the Gaia-X LegalPerson and adds
+ SimpulseID-specific properties such as gx:legalName, gx:legalForm and
+ gx:termsAndConditions.
+ is_a: LegalPerson
+ mixins:
+ - CredentialSubject
+ class_uri: simpulseid:Participant
+ slots:
+ - legal_name
+ - legal_form
+ - legal_address
+ - headquarters_address
+ - email
+ - terms_and_conditions
+ # Note: registrationNumber comes from Gaia-X LegalPerson and remains
+ # the identifier for this class according to Gaia-X.
+
+ User:
+ description: >
+ SimpulseID User entity, representing a natural person acting in the
+ ENVITED Ecosystem.
+ is_a: CredentialSubject
+ class_uri: simpulseid:User
+ slots:
+ - given_name
+ - family_name
+ - email
+ - member_of
+ - address
+
+ Administrator:
+ description: >
+ SimpulseID Administrator entity, representing a natural person with
+ elevated rights in the ENVITED Ecosystem.
+ is_a: CredentialSubject
+ class_uri: simpulseid:Administrator
+ slots:
+ - given_name
+ - family_name
+ - email
+ - member_of
+ - address
+
+ AscsBaseMembership:
+ description: >
+ ASCS Base Membership entity, representing the base membership of a
+ participant in ASCS e.V.
+ is_a: CredentialSubject
+ class_uri: simpulseid:AscsBaseMembership
+ slots:
+ - program_name
+ - hosting_organization
+ - member_of
+ - member_since
+
+ AscsEnvitedMembership:
+ description: >
+ ASCS ENVITED Membership entity, representing membership of a participant
+ in the ENVITED program, requiring an underlying base membership credential.
+ is_a: CredentialSubject
+ class_uri: simpulseid:AscsEnvitedMembership
+ slots:
+ - program_name
+ - hosting_organization
+ - member_of
+ - member_since
+ - base_membership_credential
+
+ #############################################
+ # Credential classes
+ #############################################
+
+ ParticipantCredential:
+ description: >
+ SimpulseID Participant Credential. Verifiable Credential asserting that
+ the subject is a SimpulseID Participant (a Gaia-X LegalPerson in the
+ context of the ENVITED Ecosystem).
+ is_a: VerifiableCredential
+ class_uri: simpulseid:ParticipantCredential
+ slot_usage:
+ credential_subject:
+ range: SimpulseidParticipant
+ required: true
+
+ AscsBaseMembershipCredential:
+ description: >
+ SimpulseID ASCS Base Membership Credential. Verifiable Credential asserting
+ base membership of a participant in ASCS e.V.
+ is_a: VerifiableCredential
+ class_uri: simpulseid:AscsBaseMembershipCredential
+ slot_usage:
+ credential_subject:
+ range: AscsBaseMembership
+ required: true
+
+ AscsEnvitedMembershipCredential:
+ description: >
+ SimpulseID ASCS ENVITED Membership Credential. Verifiable Credential
+ asserting ENVITED membership status, referencing an underlying base
+ membership credential.
+ is_a: VerifiableCredential
+ class_uri: simpulseid:AscsEnvitedMembershipCredential
+ slot_usage:
+ credential_subject:
+ range: AscsEnvitedMembership
+ required: true
+
+ AdministratorCredential:
+ description: >
+ SimpulseID Administrator Credential. Verifiable Credential asserting that
+ the subject is an administrator.
+ is_a: VerifiableCredential
+ class_uri: simpulseid:AdministratorCredential
+ slot_usage:
+ credential_subject:
+ range: Administrator
+ required: true
+
+ UserCredential:
+ description: >
+ SimpulseID User Credential. Verifiable Credential asserting that the
+ subject is a SimpulseID User.
+ is_a: VerifiableCredential
+ class_uri: simpulseid:UserCredential
+ slot_usage:
+ credential_subject:
+ range: User
+ required: true
diff --git a/manifests/README.md b/manifests/README.md
new file mode 100644
index 0000000..a7645f8
--- /dev/null
+++ b/manifests/README.md
@@ -0,0 +1,58 @@
+# Wallet Rendering Manifests for SimpulseID Credentials
+
+This folder contains **wallet rendering manifests** for each credential type.
+These files follow the **Decentralized Identity Foundation (DIF) Wallet Rendering**
+specification and define how SSI wallets (such as Altme) should display the
+credential to end users.
+
+## Purpose
+
+Manifests control:
+
+- Title and subtitle displayed on the credential card
+- Key fields shown on the card (e.g., name, organization, membership type)
+- How credentials appear in credential lists and detail views
+- Icons, colors, and layout options (if supported by the wallet)
+
+All manifest files correspond 1:1 to credential types found in:
+
+```txt
+../examples/
+```
+
+and are intended for use by wallets integrated with:
+
+****
+
+## Files
+
+### `SimpulseIdParticipantCredentialManifest.json`
+
+Defines card rendering for Participant Credentials (gx:LegalPerson).
+
+### `SimpulseIdAscsBaseMembershipCredentialManifest.json`
+
+Defines rendering for ASCS Base Membership credentials.
+
+### `SimpulseIdAscsEnvitedMembershipCredentialManifest.json`
+
+Rendering for ENVITED Program Membership credentials.
+
+### `SimpulseIdAdministratorCredentialManifest.json`
+
+Rendering of administrator credentials issued by ASCS.
+
+### `SimpulseIdUserCredentialManifest.json`
+
+Rendering of user credentials issued by participant administrators.
+
+## Usage
+
+Wallets use these manifests to visually render credentials when they are:
+
+- Added to the wallet
+- Displayed in a card list
+- Displayed in detail view
+- Offered for presentation via OIDC4VP
+
+They do **not** affect cryptographic validity—only **UX rendering**.
diff --git a/manifests/SimpulseIdAdministratorCredentialManifest.json b/manifests/SimpulseIdAdministratorCredentialManifest.json
new file mode 100644
index 0000000..97a1628
--- /dev/null
+++ b/manifests/SimpulseIdAdministratorCredentialManifest.json
@@ -0,0 +1,181 @@
+{
+ "id": "SimpulseIdAdministratorManifest",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "output_descriptors": [
+ {
+ "id": "https://schema.ascs.digital/SimpulseId/v1/credentials#AdministratorManifest",
+ "schema": "https://schema.ascs.digital/SimpulseId/v1/credentials#Administrator",
+ "styles": {
+ "background": {
+ "color": "#60ac24"
+ },
+ "text": {
+ "color": "#ffffff"
+ }
+ },
+ "display": {
+ "title": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "BMW Administrator Credential"
+ },
+ "subtitle": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Automotive Solution Center for Simulation e.V."
+ },
+ "description": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "This credential certifies the administrator's role at BMW, granting specific permissions and responsibilities."
+ },
+ "properties": [
+ {
+ "path": [
+ "$.credentialSubject.givenName",
+ "$.credentialSubject.familyName"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Full Name"
+ },
+ {
+ "path": [
+ "$.credentialSubject.email"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Email Address"
+ },
+ {
+ "path": [
+ "$.credentialSubject.memberOf"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Organization"
+ },
+ {
+ "path": [
+ "$.credentialSubject.address.streetAddress"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Street Address"
+ },
+ {
+ "path": [
+ "$.credentialSubject.address.postalCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Postal Code"
+ },
+ {
+ "path": [
+ "$.credentialSubject.address.addressLocality"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "City"
+ },
+ {
+ "path": [
+ "$.credentialSubject.address.countrySubdivisionCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "State"
+ },
+ {
+ "path": [
+ "$.credentialSubject.address.country"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Country"
+ },
+ {
+ "path": [
+ "$.credentialSubject.termsAndConditions[0].@id"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "fallback": "Unknown",
+ "label": "Terms & Conditions"
+ },
+ {
+ "path": [
+ "$.issuanceDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Issued On"
+ },
+ {
+ "path": [
+ "$.expirationDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Expires On"
+ }
+ ]
+ }
+ }
+ ],
+ "presentation_definition": {
+ "input_descriptors": [
+ {
+ "constraints": {
+ "fields": [
+ {
+ "filter": {
+ "pattern": "TezosAssociatedAddress",
+ "type": "string"
+ },
+ "path": [
+ "$.type"
+ ]
+ }
+ ]
+ },
+ "id": "f2a7402b-f649-11ed-834e-0a1628958560",
+ "purpose": "Select a Tezos address for verification"
+ }
+ ]
+ }
+}
diff --git a/manifests/AscsMemberCredentialManifest.json b/manifests/SimpulseIdAscsBaseMembershipCredentialManifest.json
similarity index 63%
rename from manifests/AscsMemberCredentialManifest.json
rename to manifests/SimpulseIdAscsBaseMembershipCredentialManifest.json
index b9156e7..1d263a8 100644
--- a/manifests/AscsMemberCredentialManifest.json
+++ b/manifests/SimpulseIdAscsBaseMembershipCredentialManifest.json
@@ -1,16 +1,16 @@
{
- "id": "AscsMemberCredentialManifest",
+ "id": "SimpulseIdAscsBaseMembershipManifest",
"issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1ggujjYjA7oYoaZBzTg1tYSXn3VMjcgDuv",
+ "id": "did:web:did.ascs.digital:participants:ascs",
"name": "Automotive Solution Center for Simulation e.V."
},
"output_descriptors": [
{
- "id": "https://schema.ascs.digital/AscsMemberCredential/v1#Manifest",
- "schema": "AscsMemberCredential",
+ "id": "https://schema.ascs.digital/SimpulseId/v1/credentials#AscsBaseMembershipManifest",
+ "schema": "https://schema.ascs.digital/SimpulseId/v1/credentials#AscsBaseMembership",
"styles": {
"background": {
- "color": "#60ac24"
+ "color": "#0066cc"
},
"text": {
"color": "#ffffff"
@@ -22,7 +22,7 @@
"schema": {
"type": "string"
},
- "fallback": "asc(s Member Credential"
+ "fallback": "ASCS Base Membership"
},
"subtitle": {
"path": [],
@@ -36,103 +36,102 @@
"schema": {
"type": "string"
},
- "fallback": "A certificate that attests the organizations membership in the asc(s and optionally the ENVITED research cluster confering the mandate to perform a number of actions on behalf of that organisation."
+ "fallback": "This credential certifies the base membership in ASCS e.V., granting access to core services and benefits."
},
"properties": [
{
"path": [
- "$.credentialSubject.name"
+ "$.credentialSubject.programName"
],
"schema": {
- "type": "text"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "Organization name"
+ "label": "Membership Program"
},
{
"path": [
- "$.credentialSubject.address.addressCountry"
+ "$.credentialSubject.hostingOrganization.name"
],
"schema": {
- "type": "text"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "Country"
+ "label": "Hosting Organization"
},
{
"path": [
- "$.credentialSubject.isAscsMember"
+ "$.credentialSubject.member"
],
"schema": {
- "type": "boolean"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "asc(s membership"
+ "label": "Member"
},
{
"path": [
- "$.credentialSubject.isEnvitedMember"
+ "$.credentialSubject.memberOf[0]"
],
"schema": {
- "type": "boolean"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "ENVITED membership"
+ "label": "Member Of (Organization)"
},
{
"path": [
- "$.credentialSubject.privacyPolicy"
+ "$.credentialSubject.memberOf[1]"
],
"schema": {
- "type": "string",
- "format": "uri"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "Privacy policy"
+ "label": "Member Of (Program)"
},
{
"path": [
- "$.credentialSubject.articlesOfAssociation"
+ "$.credentialSubject.memberSince"
],
"schema": {
"type": "string",
- "format": "uri"
+ "format": "date"
},
"fallback": "Unknown",
- "label": "Articles of association"
+ "label": "Member Since"
},
{
"path": [
- "$.credentialSubject.contributionRules"
+ "$.credentialSubject.termsAndConditions[0].@id"
],
"schema": {
"type": "string",
"format": "uri"
},
"fallback": "Unknown",
- "label": "Contribution rules"
+ "label": "Terms & Conditions"
},
{
"path": [
"$.issuanceDate"
],
"schema": {
- "type": "text",
+ "type": "string",
"format": "date"
},
"fallback": "Unknown",
- "label": "Issue date"
+ "label": "Issued On"
},
{
"path": [
"$.expirationDate"
],
"schema": {
- "type": "text",
+ "type": "string",
"format": "date"
},
"fallback": "Unknown",
- "label": "Expiration date"
+ "label": "Expires On"
}
]
}
@@ -155,8 +154,8 @@
]
},
"id": "f2a7402b-f649-11ed-834e-0a1628958560",
- "purpose": "Select a Tezos address"
+ "purpose": "Select a Tezos address for verification"
}
]
}
-}
\ No newline at end of file
+}
diff --git a/manifests/SimpulseIdAscsEnvitedMembershipCredentialManifest.json b/manifests/SimpulseIdAscsEnvitedMembershipCredentialManifest.json
new file mode 100644
index 0000000..18b91dc
--- /dev/null
+++ b/manifests/SimpulseIdAscsEnvitedMembershipCredentialManifest.json
@@ -0,0 +1,181 @@
+{
+ "id": "SimpulseIdAscsEnvitedMembershipManifest",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "output_descriptors": [
+ {
+ "id": "https://schema.ascs.digital/SimpulseId/v1/credentials#AscsEnvitedMembershipManifest",
+ "schema": "https://schema.ascs.digital/SimpulseId/v1/credentials#AscsEnvitedMembership",
+ "styles": {
+ "background": {
+ "color": "#008080"
+ },
+ "text": {
+ "color": "#ffffff"
+ }
+ },
+ "display": {
+ "title": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "ASCS ENVITED Membership"
+ },
+ "subtitle": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Automotive Solution Center for Simulation e.V."
+ },
+ "description": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "This credential certifies the ENVITED membership in ASCS e.V., granting access to advanced services and collaboration tools."
+ },
+ "properties": [
+ {
+ "path": [
+ "$.credentialSubject.programName"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Membership Program"
+ },
+ {
+ "path": [
+ "$.credentialSubject.hostingOrganization.name"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Hosting Organization"
+ },
+ {
+ "path": [
+ "$.credentialSubject.member"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Member"
+ },
+ {
+ "path": [
+ "$.credentialSubject.memberOf[0]"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Member Of (Organization)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.memberOf[1]"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Member Of (Base Program)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.memberOf[2]"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Member Of (ENVITED Program)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.memberSince"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Member Since"
+ },
+ {
+ "path": [
+ "$.credentialSubject.baseMembership"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Base Membership ID"
+ },
+ {
+ "path": [
+ "$.credentialSubject.termsAndConditions[0].@id"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "fallback": "Unknown",
+ "label": "Terms & Conditions"
+ },
+ {
+ "path": [
+ "$.issuanceDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Issued On"
+ },
+ {
+ "path": [
+ "$.expirationDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Expires On"
+ }
+ ]
+ }
+ }
+ ],
+ "presentation_definition": {
+ "input_descriptors": [
+ {
+ "constraints": {
+ "fields": [
+ {
+ "filter": {
+ "pattern": "TezosAssociatedAddress",
+ "type": "string"
+ },
+ "path": [
+ "$.type"
+ ]
+ }
+ ]
+ },
+ "id": "f2a7402b-f649-11ed-834e-0a1628958560",
+ "purpose": "Select a Tezos address for verification"
+ }
+ ]
+ }
+}
diff --git a/manifests/SimpulseIdParticipantCredentialManifest.json b/manifests/SimpulseIdParticipantCredentialManifest.json
new file mode 100644
index 0000000..882c966
--- /dev/null
+++ b/manifests/SimpulseIdParticipantCredentialManifest.json
@@ -0,0 +1,261 @@
+{
+ "id": "SimpulseIdParticipantManifest",
+ "issuer": {
+ "id": "did:web:did.ascs.digital:participants:ascs",
+ "name": "Automotive Solution Center for Simulation e.V."
+ },
+ "output_descriptors": [
+ {
+ "id": "https://schema.ascs.digital/SimpulseId/v1/credentials#ParticipantManifest",
+ "schema": "https://schema.ascs.digital/SimpulseId/v1/credentials#Participant",
+ "styles": {
+ "background": {
+ "color": "#003366"
+ },
+ "text": {
+ "color": "#ffffff"
+ }
+ },
+ "display": {
+ "title": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Company Participant Credential"
+ },
+ "subtitle": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Automotive Solution Center for Simulation e.V."
+ },
+ "description": {
+ "path": [],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "This credential certifies the company's participation in the ASCS ecosystem, enabling access to collaborative services and resources."
+ },
+ "properties": [
+ {
+ "path": [
+ "$.credentialSubject.legalName"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Company Name"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalForm"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Form"
+ },
+ {
+ "path": [
+ "$.credentialSubject.registrationNumber.vatID"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "VAT ID"
+ },
+ {
+ "path": [
+ "$.credentialSubject.duns"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "DUNS Number"
+ },
+ {
+ "path": [
+ "$.credentialSubject.email"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Email"
+ },
+ {
+ "path": [
+ "$.credentialSubject.website"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "fallback": "Unknown",
+ "label": "Website"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalAddress.streetAddress"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Address (Street)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalAddress.postalCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Address (Postal Code)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalAddress.addressLocality"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Address (City)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalAddress.countrySubdivisionCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Address (State)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.legalAddress.country"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Legal Address (Country)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.headquartersAddress.streetAddress"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Headquarters (Street)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.headquartersAddress.postalCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Headquarters (Postal Code)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.headquartersAddress.addressLocality"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Headquarters (City)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.headquartersAddress.countrySubdivisionCode"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Headquarters (State)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.headquartersAddress.country"
+ ],
+ "schema": {
+ "type": "string"
+ },
+ "fallback": "Unknown",
+ "label": "Headquarters (Country)"
+ },
+ {
+ "path": [
+ "$.credentialSubject.termsAndConditions[0].@id"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "uri"
+ },
+ "fallback": "Unknown",
+ "label": "Terms & Conditions"
+ },
+ {
+ "path": [
+ "$.issuanceDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Issued On"
+ },
+ {
+ "path": [
+ "$.expirationDate"
+ ],
+ "schema": {
+ "type": "string",
+ "format": "date"
+ },
+ "fallback": "Unknown",
+ "label": "Expires On"
+ }
+ ]
+ }
+ }
+ ],
+ "presentation_definition": {
+ "input_descriptors": [
+ {
+ "constraints": {
+ "fields": [
+ {
+ "filter": {
+ "pattern": "TezosAssociatedAddress",
+ "type": "string"
+ },
+ "path": [
+ "$.type"
+ ]
+ }
+ ]
+ },
+ "id": "f2a7402b-f649-11ed-834e-0a1628958560",
+ "purpose": "Select a Tezos address for verification"
+ }
+ ]
+ }
+}
diff --git a/manifests/AscsUserCredentialManifest.json b/manifests/SimpulseIdUserCredentialManifest.json
similarity index 55%
rename from manifests/AscsUserCredentialManifest.json
rename to manifests/SimpulseIdUserCredentialManifest.json
index dc80ccc..bf56b8d 100644
--- a/manifests/AscsUserCredentialManifest.json
+++ b/manifests/SimpulseIdUserCredentialManifest.json
@@ -1,13 +1,13 @@
{
- "id": "AscsUserCredentialManifest",
+ "id": "SimpulseIdUserManifest",
"issuer": {
- "id": "did:pkh:tezos:NetXnHfVqm9iesp:tz1bpeJArd7apJyTUryfXH1SD6w8GL6Gwhj8",
- "name": "Testcompany GmbH"
+ "id": "did:web:did.ascs.digital:participants:bmw",
+ "name": "Bayerische Motoren Werke Aktiengesellschaft"
},
"output_descriptors": [
{
- "id": "https://schema.ascs.digital/AscsUserCredential/v1#Manifest",
- "schema": "AscsUserCredential",
+ "id": "https://schema.ascs.digital/SimpulseId/v1/credentials#UserManifest",
+ "schema": "https://schema.ascs.digital/SimpulseId/v1/credentials#User",
"styles": {
"background": {
"color": "#7891bb"
@@ -22,105 +22,86 @@
"schema": {
"type": "string"
},
- "fallback": "asc(s User Credential"
+ "fallback": "BMW User Credential"
},
"subtitle": {
"path": [],
"schema": {
"type": "string"
},
- "fallback": "Automotive Solution Center for Simulation e.V."
+ "fallback": "Bayerische Motoren Werke AG"
},
"description": {
"path": [],
"schema": {
"type": "string"
},
- "fallback": "A certificate that attests the users affiliation with an organization holding a membership in the asc(s and optionally the ENVITED research cluster confering the mandate to access services within the ecosystem."
+ "fallback": "This credential certifies the user's affiliation with BMW, granting access to ecosystem services."
},
"properties": [
{
"path": [
- "$.credentialSubject.name"
+ "$.credentialSubject.givenName",
+ "$.credentialSubject.familyName"
],
"schema": {
- "type": "text"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "User name"
- },
- {
- "path": [
- "$.credentialSubject.address.addressCountry"
- ],
- "schema": {
- "type": "text"
- },
- "fallback": "Unknown",
- "label": "Country"
+ "label": "Full Name"
},
{
"path": [
"$.credentialSubject.email"
],
"schema": {
- "type": "text"
- },
- "fallback": "Unknown",
- "label": "E-Mail"
- },
- {
- "path": [
- "$.credentialSubject.isAscsMember"
- ],
- "schema": {
- "type": "boolean"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "asc(s membership"
+ "label": "Email Address"
},
{
"path": [
- "$.credentialSubject.isEnvitedMember"
+ "$.credentialSubject.memberOf"
],
"schema": {
- "type": "boolean"
+ "type": "string"
},
"fallback": "Unknown",
- "label": "ENVITED membership"
+ "label": "Organization"
},
{
"path": [
- "$.credentialSubject.privacyPolicy"
+ "$.credentialSubject.termsAndConditions[0].@id"
],
"schema": {
"type": "string",
"format": "uri"
},
"fallback": "Unknown",
- "label": "Privacy policy"
+ "label": "Terms & Conditions"
},
{
"path": [
"$.issuanceDate"
],
"schema": {
- "type": "text",
+ "type": "string",
"format": "date"
},
"fallback": "Unknown",
- "label": "Issue date"
+ "label": "Issued On"
},
{
"path": [
"$.expirationDate"
],
"schema": {
- "type": "text",
+ "type": "string",
"format": "date"
},
"fallback": "Unknown",
- "label": "Expiration date"
+ "label": "Expires On"
}
]
}
@@ -143,8 +124,8 @@
]
},
"id": "f2a7402b-f649-11ed-834e-0a1628958560",
- "purpose": "Select a Tezos address"
+ "purpose": "Select a Tezos address for verification"
}
]
}
-}
\ No newline at end of file
+}
diff --git a/ontology-management-base b/ontology-management-base
new file mode 160000
index 0000000..6d957bd
--- /dev/null
+++ b/ontology-management-base
@@ -0,0 +1 @@
+Subproject commit 6d957bd0b98bc094c2eb835682b9ae44af064a01
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e8d8ea9
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,16 @@
+# Core LinkML libraries (generators, runtime, datamodel)
+linkml==1.9.6
+linkml-runtime==1.9.5
+
+# RDF & SHACL stack needed by LinkML and your existing scripts
+rdflib==7.5.0
+pyshacl==0.30.1
+
+# JSON-LD parsing and framing
+pyld==2.0.4
+
+# YAML loader for LinkML schema parsing
+PyYAML==6.0.3
+
+# General utilities used in your scripts
+click==8.1.8
diff --git a/service-characteristics b/service-characteristics
new file mode 160000
index 0000000..702940d
--- /dev/null
+++ b/service-characteristics
@@ -0,0 +1 @@
+Subproject commit 702940d9b20b24d89057394dfd333c06d5c9a73a
diff --git a/src/README.md b/src/README.md
new file mode 100644
index 0000000..6b7884d
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,53 @@
+# Generated artefacts
+
+This folder contains downstream artefacts generated from LinkML schemas:
+
+- JSON-LD context (`*_context.jsonld`)
+- SHACL shapes (`*_shacl.ttl`)
+- OWL ontology (`*_ontology.ttl`)
+
+Each schema is generated into its own subfolder:
+
+- `generated/simpulseid/`
+- `generated/harbour/`
+- `generated/gx/`
+
+## 1) Generate
+
+From repository root:
+
+```bash
+python3 src/generate_from_linkml.py \
+ --model linkml/simpulseid.yaml \
+ --model linkml/harbour.yaml \
+ --model service-characteristics/linkml/gaia-x.yaml \
+ --out-root generated
+```
+
+## 2) Validate examples against generated SHACL + schema (recommended)
+
+Examples are validated using the `ontology-management-base` validator.
+Point `--root` to `generated/` so it can resolve:
+
+- generated contexts
+- generated SHACL files
+- generated ontologies
+
+Example:
+
+```bash
+python3 ontology-management-base/src/check_jsonld_against_shacl_schema.py \
+ examples/simpulseid-administrator-credential.json \
+ --root generated/
+```
+
+## Notes on `id` / `@id`
+
+In JSON-LD, the node identifier is the keyword `@id`. Many JSON-LD contexts (including VC contexts) map a compact term like `id` to `@id`, but the underlying mechanism is JSON-LD itself.
+
+For LinkML, the robust modelling pattern is to define a shared slot once (e.g., in a small `core.yaml`) with:
+
+- `slot_uri: "@id"` for the `id` slot
+- `slot_uri: "@type"` for the `type` slot
+
+and import that shared definition into all schemas that need it. This prevents “conflicting URIs for item: id” during import merges.
diff --git a/src/generate_from_linkml.py b/src/generate_from_linkml.py
new file mode 100644
index 0000000..26c0a79
--- /dev/null
+++ b/src/generate_from_linkml.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python3
+"""
+Generate downstream artefacts (JSON-LD context, SHACL shapes, OWL ontology)
+from one or more LinkML schemas.
+
+Examples:
+ python3 src/generate_from_linkml.py --model linkml/simpulseid.yaml
+ python3 src/generate_from_linkml.py --model linkml/simpulseid.yaml --model linkml/harbour.yaml
+"""
+
+import argparse
+import os
+from pathlib import Path
+from typing import Dict, List, Optional
+from urllib.parse import urlparse
+
+from linkml.generators.jsonldcontextgen import ContextGenerator
+from linkml.generators.owlgen import OwlSchemaGenerator
+from linkml.generators.shaclgen import ShaclGenerator as _BaseShaclGenerator
+from linkml_runtime.utils.schemaview import SchemaView
+import json
+
+def patch_jsonld_keywords(context_json: str) -> str:
+ """
+ LinkML cannot use '@id'/'@type' as slot_uri (loader rejects it).
+ We therefore patch the generated context to alias:
+ - id -> @id
+ - type -> @type
+ """
+ doc = json.loads(context_json)
+ ctx = doc.get("@context")
+ if isinstance(ctx, dict):
+ ctx["id"] = "@id"
+ ctx["type"] = "@type"
+ return json.dumps(doc, indent=2, ensure_ascii=False) + "\n"
+
+
+def debug(msg: str) -> None:
+ print(f"[DEBUG] {msg}")
+
+
+def ensure_dir(path: Path) -> None:
+ path.mkdir(parents=True, exist_ok=True)
+
+
+def find_repo_root(start: Path) -> Path:
+ current = start
+ while current != current.parent:
+ if (current / ".git").is_dir() or (current / "service-characteristics").is_dir():
+ return current
+ current = current.parent
+ return start.parent
+
+
+def build_import_map(repo_root: Path) -> Dict[str, str]:
+ gaiax_linkml_dir = repo_root / "service-characteristics" / "linkml"
+ import_map: Dict[str, str] = {}
+
+ if not gaiax_linkml_dir.is_dir():
+ debug(f"Gaia-X linkml dir not found at {gaiax_linkml_dir}")
+ return import_map
+
+ for yaml_file in gaiax_linkml_dir.glob("*.yaml"):
+ import_map[yaml_file.stem] = str(yaml_file.with_suffix("").resolve())
+
+ debug(f"Built import_map with {len(import_map)} entries from {gaiax_linkml_dir}")
+ return import_map
+
+
+def iri_to_model_name(iri: str) -> str:
+ path = urlparse(iri).path
+ parts = [p for p in path.split("/") if p]
+ return (parts[0].lower() if parts else "unknown")
+
+
+class FixedShaclGenerator(_BaseShaclGenerator):
+ """Ensure SchemaView is built with the same importmap/base_dir as the loader."""
+
+ def __post_init__(self) -> None:
+ from linkml.utils.generator import Generator as BaseGenerator
+
+ BaseGenerator.__post_init__(self)
+ self.schemaview = SchemaView(self.schema, importmap=self.importmap or {}, base_dir=self.base_dir)
+ self.generate_header()
+
+
+def set_linkml_model_path(repo_root: Path) -> None:
+ gaiax_linkml_dir = repo_root / "service-characteristics" / "linkml"
+ local_linkml_dir = repo_root / "linkml"
+
+ search_paths: List[str] = []
+ if gaiax_linkml_dir.is_dir():
+ search_paths.append(str(gaiax_linkml_dir))
+ if local_linkml_dir.is_dir():
+ search_paths.append(str(local_linkml_dir))
+
+ existing_env = os.environ.get("LINKML_MODEL_PATH")
+ if existing_env:
+ search_paths.append(existing_env)
+
+ if search_paths:
+ os.environ["LINKML_MODEL_PATH"] = os.pathsep.join(search_paths)
+ debug(f"LINKML_MODEL_PATH set to: {os.environ['LINKML_MODEL_PATH']}")
+
+
+def schema_id_for(model_path: Path, import_map: Dict[str, str], base_dir: str) -> Optional[str]:
+ sv = SchemaView(str(model_path), importmap=import_map, base_dir=base_dir)
+ return getattr(sv.schema, "id", None)
+
+
+def generate_one(model_path: Path, out_root: Path, import_map: Dict[str, str]) -> None:
+ base_dir = str(model_path.parent)
+
+ sid = schema_id_for(model_path, import_map, base_dir)
+ model_name = iri_to_model_name(sid) if sid else model_path.stem.lower()
+
+ out_dir = out_root / model_name
+ ensure_dir(out_dir)
+
+ out_context = out_dir / f"{model_name}_context.jsonld"
+ out_shacl = out_dir / f"{model_name}_shacl.ttl"
+ out_owl = out_dir / f"{model_name}_ontology.ttl"
+
+ debug(f"Model: {model_path}")
+ debug(f"schema_id={sid!r} -> model_name={model_name!r}")
+ debug(f"Outputs: {out_dir}")
+
+ old_cwd = Path.cwd()
+ os.chdir(model_path.parent)
+ try:
+ print(f"Using LinkML model: {model_path}")
+
+ print(f"Generating JSON-LD context -> {out_context}")
+ ctx_gen = ContextGenerator(str(model_path), importmap=import_map, base_dir=base_dir)
+ out_context.write_text(patch_jsonld_keywords(ctx_gen.serialize()), encoding="utf-8")
+
+ print(f"Generating SHACL shapes -> {out_shacl}")
+ shacl_gen = FixedShaclGenerator(str(model_path), importmap=import_map, base_dir=base_dir)
+ out_shacl.write_text(shacl_gen.serialize(), encoding="utf-8")
+
+ print(f"Generating OWL ontology -> {out_owl}")
+ owl_gen = OwlSchemaGenerator(str(model_path), importmap=import_map, base_dir=base_dir)
+ out_owl.write_text(owl_gen.serialize(), encoding="utf-8")
+
+ print(f"Done: {model_name}")
+ finally:
+ os.chdir(old_cwd)
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description="Generate JSON-LD context, SHACL shapes and OWL ontology from one or more LinkML models."
+ )
+ parser.add_argument(
+ "--model",
+ action="append",
+ required=True,
+ help="Path to a LinkML YAML schema. Repeat --model for multiple schemas.",
+ )
+ parser.add_argument(
+ "--out-root",
+ default="generated",
+ help="Root output folder (default: generated). Each schema is generated into generated//",
+ )
+
+ args = parser.parse_args()
+
+ models = [Path(m).resolve() for m in args.model]
+ for mp in models:
+ if not mp.exists():
+ raise SystemExit(f"LinkML model not found: {mp}")
+
+ repo_root = find_repo_root(models[0].parent)
+ debug(f"repo_root: {repo_root} (exists={repo_root.exists()}, type={'dir' if repo_root.is_dir() else 'missing'})")
+
+ import_map = build_import_map(repo_root)
+ set_linkml_model_path(repo_root)
+
+ out_root = Path(args.out_root).resolve()
+ ensure_dir(out_root)
+
+ for mp in models:
+ generate_one(mp, out_root, import_map)
+
+
+if __name__ == "__main__":
+ main()