Skip to content

Commit e747a93

Browse files
leifjclaude
andauthored
docs(issuers): fix issuer, operations, registry and reference docs against vc v0.7.23 (#79)
* docs(reference): note build-time generation and PDP requirement on reference index Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(issuers): fix deploy composes, endpoints, transform->derivations, SAML/OIDC examples Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(issuers,reference): PDP wording, issuer stack deployment fixes Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(operations): admin API auth, docker image list and tags Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(registry): registry-cli flags and registry roles Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(reference): token status lists, standards endpoints and formats, API page Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(operations): link admin_host known issue Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
1 parent 55a70cf commit e747a93

16 files changed

Lines changed: 796 additions & 545 deletions

‎docs/sirosid/issuers/api-integration.md‎

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -426,19 +426,19 @@ apigw:
426426
427427
### Credential Offer Format
428428
429-
The deep link contains a credential offer with pre-authorized code grant:
429+
The offer carries a pre-authorized code grant. `credential_configuration_ids` holds the credential **scope** (here `diploma`), and the offer is valid for 5 minutes. The `tx_code` object is present only when `enable_pin` is on:
430430
431431
```json
432432
{
433433
"credential_issuer": "https://issuer.example.org",
434-
"credential_configuration_ids": ["urn:eudi:diploma:1"],
434+
"credential_configuration_ids": ["diploma"],
435435
"grants": {
436436
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
437437
"pre-authorized_code": "oaKazRN8I0IbtZ...",
438438
"tx_code": {
439439
"input_mode": "numeric",
440440
"length": 6,
441-
"description": "Enter the PIN sent to your email"
441+
"description": "Enter the PIN provided by the issuer"
442442
}
443443
}
444444
}
@@ -449,21 +449,9 @@ The deep link contains a credential offer with pre-authorized code grant:
449449
450450
## Revocation
451451
452-
Credential revocation is managed via [Token Status Lists](/sirosid/reference/token-status-lists). When a credential needs to be revoked, delete the underlying document and the issuer updates the status list entry:
452+
Credential status is published as [Token Status Lists](/sirosid/reference/token-status-lists) by the registry service. Deleting a document through `DELETE /api/v1/datastore` removes the stored document so no further credentials can be issued from it, but it does **not** change the status of credentials that were already issued: apigw never calls the registry to update a status.
453453
454-
```bash
455-
DELETE /api/v1/datastore
456-
Content-Type: application/json
457-
Authorization: Bearer <your-jwt-token>
458-
459-
{
460-
"authentic_source": "hr.example.org",
461-
"scope": "diploma",
462-
"document_id": "diploma-2025-001234"
463-
}
464-
```
465-
466-
Verifiers checking the Token Status List will see the credential as revoked.
454+
To revoke an issued credential, update its status entry in the registry, either through the registry admin GUI (`registry.admin_gui`, `POST /admin/status`) or by calling the registry's `TokenStatusListUpdateStatus` gRPC method directly. Verifiers checking the Token Status List then see the credential as revoked.
467455
468456
---
469457
@@ -478,7 +466,11 @@ service IssuerService {
478466
rpc MakeSDJWT (MakeSDJWTRequest) returns (MakeSDJWTReply) {}
479467
rpc MakeMDoc (MakeMDocRequest) returns (MakeMDocReply) {}
480468
rpc MakeVC20 (MakeVC20Request) returns (MakeVC20Reply) {}
469+
rpc MakeJWP (MakeJWPRequest) returns (MakeJWPReply) {}
481470
rpc JWKS (Empty) returns (JwksReply) {}
471+
rpc SignMetadata (SignMetadataRequest) returns (SignMetadataReply) {}
472+
rpc GetIACAs (Empty) returns (GetIACAsReply) {}
473+
rpc Status (v1.status.StatusRequest) returns (v1.status.StatusReply) {}
482474
}
483475
```
484476
@@ -499,22 +491,25 @@ message MakeSDJWTRequest {
499491
```protobuf
500492
message MakeMDocRequest {
501493
string scope = 1; // Credential scope
502-
string doc_type = 2; // e.g., "org.iso.18013.5.1.mDL"
494+
reserved 2; // was: string doc_type; the doctype now comes from mddl
503495
bytes document_data = 3; // JSON encoded mDL data
504496
bytes device_public_key = 4; // CBOR encoded COSE_Key
505497
string device_key_format = 5; // "cose", "jwk", or "x509"
498+
bytes mddl = 6; // Raw MDDL (mso_mdoc) schema JSON bytes
506499
}
507500
```
508501
509502
### Connection
510503
504+
The generated Go stubs live under `internal/` in the [vc repository](https://github.com/SUNET/vc) and cannot be imported from other modules; generate your own client from `proto/v1-issuer.proto`. The gRPC server listens on `issuer.grpc_server.addr` (default `:8090`).
505+
511506
```go
512507
import (
513508
"google.golang.org/grpc"
514-
pb "vc/internal/gen/issuer/apiv1_issuer"
509+
pb "example.org/yourmodule/gen/issuer/apiv1_issuer" // generated from proto/v1-issuer.proto
515510
)
516511
517-
conn, err := grpc.Dial("issuer.example.org:9090", grpc.WithTransportCredentials(creds))
512+
conn, err := grpc.Dial("issuer.example.org:8090", grpc.WithTransportCredentials(creds))
518513
client := pb.NewIssuerServiceClient(conn)
519514
520515
reply, err := client.MakeSDJWT(ctx, &pb.MakeSDJWTRequest{
@@ -604,6 +599,9 @@ apigw:
604599
enable: true
605600
issuer_url: "https://auth.example.com"
606601
audience: "vc-issuer"
602+
# client_id and redirect_uri are required whenever oidc.enable is true
603+
client_id: "vc-apigw"
604+
redirect_uri: "https://issuer.example.org/ui/callback"
607605
```
608606
609607
When SPOCP rules are configured, each request is evaluated as a **six-part s-expression** (all six parts are mandatory and must appear in this exact order):
@@ -714,7 +712,7 @@ a string.
714712
3. **mTLS for gRPC**: Use mutual TLS for the internal Issuer gRPC service (configurable via `grpc_server.tls`)
715713
4. **Input Validation**: The issuer validates all document data against VCTM schemas
716714
5. **Audit Logging**: All API operations are logged for compliance (configurable webhook destinations)
717-
6. **Rate Limiting**: Implement rate limiting at the reverse proxy level to prevent abuse
715+
6. **Rate Limiting**: apigw has built-in per-IP rate limiting (`apigw.rate_limit`, including `datastore_requests_per_minute`); add reverse-proxy limits on top if needed
718716
719717
---
720718

‎docs/sirosid/issuers/concepts.md‎

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Compatible wallets include:
1515
- **SIROS ID Credential Manager** (based on [wwWallet](/opensource#wwwallet-project)) – used in examples throughout this documentation
1616
- **EUDI Reference Wallet** – the EU Digital Identity reference implementation
1717
- **Native mobile wallets** – iOS and Android applications with OID4VCI support
18-
- **Third-party wallets** – any wallet implementing OID4VCI and supported formats (SD-JWT VC, mDL, JWT VC)
18+
- **Third-party wallets** – any wallet implementing OID4VCI and supported formats (SD-JWT VC, mDL/mdoc, W3C VC 2.0)
1919

2020
:::tip Multi-Wallet Support
2121
A single issuer deployment can issue credentials to multiple different wallet implementations. The OID4VCI protocol ensures consistent behavior across all compliant wallets.
@@ -116,7 +116,8 @@ The SIROS ID Issuer supports multiple credential formats to meet different use c
116116
|--------|----------|----------|---------------------|
117117
| **SD-JWT VC** | [IETF SD-JWT VC](https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/) | EU Digital Identity, general use | ✅ Yes |
118118
| **mDL/mDoc** | [ISO 18013-5](https://www.iso.org/standard/69084.html) | Mobile driving licenses | ✅ Yes |
119-
| **JWT VC** | [W3C VC Data Model](https://www.w3.org/TR/vc-data-model/) | Legacy systems | ❌ No |
119+
| **W3C VC 2.0** (`ldp_vc`) | [W3C VC Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) with Data Integrity proofs | Linked-data ecosystems | Depends on cryptosuite |
120+
| **JWP** (blind BBS) | [IETF JSON Web Proof](https://datatracker.ietf.org/doc/draft-ietf-jose-json-web-proof/) | Unlinkable presentations | ✅ Yes |
120121

121122
:::tip Recommended Format
122123
**SD-JWT VC** is the recommended format for new deployments. It provides selective disclosure (users can share only necessary claims) and is the format specified by the EU Digital Identity Wallet Architecture Reference Framework (ARF).
@@ -134,7 +135,7 @@ A **credential type** defines the schema and semantics of a credential. Each typ
134135
```mermaid
135136
graph LR
136137
subgraph "Credential Type Definition (VCTM)"
137-
VCT["VCT Identifier<br/>urn:eudi:pid:arf-1.8:1"]
138+
VCT["VCT Identifier<br/>urn:eudi:pid:1"]
138139
Claims["Claim Schema<br/>given_name, family_name, ..."]
139140
Display["Display Rules<br/>Labels, logos, templates"]
140141
end
@@ -155,9 +156,9 @@ Each credential type is defined by a **VCTM file** that specifies:
155156

156157
```json
157158
{
158-
"vct": "urn:eudi:pid:arf-1.8:1",
159+
"vct": "urn:eudi:pid:1",
159160
"name": "Person Identification Data",
160-
"description": "EU Person Identification Data credential (ARF 1.8)",
161+
"description": "EU Person Identification Data credential",
161162
"display": [
162163
{
163164
"lang": "en-US",
@@ -178,24 +179,23 @@ Each credential type is defined by a **VCTM file** that specifies:
178179
}
179180
```
180181

181-
#### Built-in Credential Types
182+
#### Shipped Credential Types
182183

183-
SIROS ID includes pre-configured types based on EU standards:
184+
The [vc repository `metadata/` directory](https://github.com/SUNET/vc/tree/main/metadata) ships type metadata for common types, which you reference from `common.credential_metadata`:
184185

185-
| Type | VCT | Description |
186-
|------|-----|-------------|
187-
| **PID (ARF 1.5)** | `urn:eudi:pid:arf-1.5:1` | Person Identification Data (ARF 1.5) |
188-
| **PID (ARF 1.8)** | `urn:eudi:pid:arf-1.8:1` | Person Identification Data (ARF 1.8+) |
189-
| **EHIC** | `urn:eudi:ehic:1` | European Health Insurance Card |
190-
| **PDA1** | `urn:eudi:pda1:1` | Portable Document A1 |
191-
| **Diploma** | `urn:eudi:diploma:1` | Educational credentials |
192-
| **ELM** | `urn:eudi:elm:1` | European Learning Model |
193-
| **Microcredential** | `urn:eudi:micro_credential:1` | Short learning achievements |
194-
| **OpenBadge** | `urn:eudi:openbadge_complete:1` | Open Badges 3.0 |
186+
| Type | VCT / doctype | File |
187+
|------|---------------|------|
188+
| **PID** | `urn:eudi:pid:1` | `vctm_pid.json` |
189+
| **EHIC** | `urn:eudi:ehic:1` | `vctm_ehic.json` |
190+
| **PDA1** | `urn:eudi:pda1:1` | `vctm_pda1.json` |
191+
| **Diploma** | `urn:eudi:diploma:1` | `vctm_diploma.json` |
192+
| **ELM** | `urn:eudi:elm:1` | `vctm_elm.json` |
193+
| **Microcredential** | `urn:eudi:micro_credential:1` | `vctm_microcredential.json` |
194+
| **eduID** | `urn:credential:eduid:1` | `vctm_eduid.json` |
195+
| **PID (mdoc)** | `eu.europa.ec.eudi.pid.1` | `pid_mdoc.mdoc.json` |
196+
| **mDL (mdoc)** | `org.iso.18013.5.1.mDL` | `mdl.mdoc.json` |
195197

196-
:::note ARF Version Selection
197-
SIROS ID supports both ARF 1.5 and ARF 1.8 PID schemas. Which one a scope uses is determined by the VCTM it points at in `common.credential_metadata`. The generic VCT `urn:eudi:pid:1` is accepted for compatibility but maps to a configured ARF version.
198-
:::
198+
Which schema a scope uses is determined by the VCTM (or MDDL) file it points at in `common.credential_metadata`.
199199

200200
### Building the Claim Set
201201

@@ -208,7 +208,8 @@ configuration:
208208
from and which auth provider identifies the user.
209209
3. `apigw.auth_providers.<provider>.attribute_mapping` normalises the
210210
provider's own attribute names to canonical claim names, with optional
211-
transforms and defaults.
211+
defaults. Mapping is a rename-and-presence step only; value
212+
transformations are `derivations` on the scope (see below).
212213

213214
APIGW then validates the resulting claim set against the VCTM schema before
214215
sending it to the issuer for signing.
@@ -217,7 +218,7 @@ sending it to the issuer for signing.
217218
common:
218219
credential_metadata:
219220
pid:
220-
vctm_file_path: "/metadata/vctm_pid_arf_1_8.json"
221+
vctm_file_path: "/metadata/vctm_pid.json"
221222
format: "dc+sd-jwt"
222223

223224
apigw:
@@ -234,20 +235,28 @@ apigw:
234235
required: true
235236
"urn:oid:0.9.2342.19200300.100.1.3":
236237
claim: "email_address"
237-
transform: "lowercase"
238238

239239
data_sources:
240240
# The SAML assertion's claims ARE the credential data
241241
assertion:
242242
scopes:
243243
pid:
244244
auth_provider: saml
245+
# Value transformations are derivations on the scope
246+
derivations:
247+
- lowercase:
248+
input: email_address
245249
```
246250
247-
Supported `transform` values are `lowercase`, `uppercase`, `trim`,
248-
`country_alpha2`, `country_alpha3` and `yyyymmdd_to_iso`. `default:` supplies a
249-
value when the attribute is absent, and `as_array: true` wraps a scalar in a
250-
single-element array.
251+
`default:` supplies a value when the attribute is absent, and `as_array: true`
252+
wraps a scalar in a single-element array. Available derivation primitives are
253+
`age_over_thresholds`, `lowercase`, `uppercase`, `trim`, `country_alpha2`,
254+
`country_alpha3`, `yyyymmdd_to_iso`, `swamid_highest_assurance_level` and
255+
`random`. Derivations are supported on `datastore`, `assertion`, `external_api`
256+
and `presentation` scopes; each takes an `input` claim name and, where
257+
applicable, an `output` (default: in place). See the
258+
[VC Configuration Reference](/sirosid/reference/vc-configuration) for each
259+
primitive's parameters.
251260

252261
:::note Removed configuration
253262
Earlier releases had a top-level `credential_constructor` section. It no longer
@@ -309,32 +318,15 @@ flowchart TB
309318
| **SAML SP** | Service Provider for SAML federations | SAML 2.0 |
310319
| **OIDC RP** | Relying Party for OIDC providers | OpenID Connect |
311320
| **Session Manager** | OAuth2 session and state management | OAuth 2.0 |
312-
| **Issuer API** | Core credential operations | gRPC + REST |
321+
| **Issuer API** | Core credential operations (called by apigw; the REST datastore API is served by apigw) | gRPC |
313322
| **Credential Constructor** | Builds credentials from claims | Internal |
314323
| **Signing Service** | Cryptographic signing (SW or HSM) | JWS, COSE |
315324
| **Status Lists** | Revocation status tracking | Token Status List |
316325
| **Audit Log** | Compliance and monitoring | Internal |
317326

318327
### Service Architecture
319328

320-
The issuer can run as a single process or as separate microservices:
321-
322-
<div className="row">
323-
<div className="col col--6">
324-
325-
**Single Process Mode**
326-
327-
```mermaid
328-
flowchart TB
329-
Combined[apigw + issuer + registry]
330-
```
331-
332-
All components in one binary—simplest deployment for development and small-scale production.
333-
334-
</div>
335-
<div className="col col--6">
336-
337-
**Microservices Mode**
329+
The issuer runs as three separate services (`apigw`, `issuer` and `registry`, each its own binary and container image) that talk gRPC to each other and share a MongoDB:
338330

339331
```mermaid
340332
flowchart TB
@@ -343,13 +335,11 @@ flowchart TB
343335
Registry[Registry Service]
344336
345337
APIGW -->|gRPC| Issuer
338+
APIGW -->|gRPC| Registry
346339
Issuer -->|gRPC| Registry
347340
```
348341

349-
Separate services for independent scaling and high availability.
350-
351-
</div>
352-
</div>
342+
All three can run on one host (for example with Docker Compose, see [Deployment](./deployment)) or be scaled independently for high availability.
353343

354344
## Deployment Models
355345

@@ -465,12 +455,12 @@ flowchart LR
465455

466456
### Model 4: Standalone Issuer
467457

468-
Minimal deployment for testing or air-gapped environments.
458+
Minimal single-host deployment for testing or air-gapped environments: the same three services and MongoDB, run together on one machine.
469459

470460
```mermaid
471461
flowchart LR
472462
subgraph "Single Server"
473-
All[Issuer + Registry<br/>Embedded MongoDB]
463+
All[apigw + issuer + registry<br/>+ MongoDB]
474464
end
475465
476466
TestWallet[Test Wallet]
@@ -479,7 +469,7 @@ flowchart LR
479469

480470
| Aspect | Details |
481471
|--------|---------|
482-
| **Setup** | Minutes – single Docker container |
472+
| **Setup** | Minutes – one Docker Compose file |
483473
| **Maintenance** | Minimal |
484474
| **Data location** | Local |
485475
| **Customization** | Development/testing |

0 commit comments

Comments
 (0)