The problem
Sealing is provider-agnostic in the port and provider-locked in the composition
root. A self-hoster gets one specific QTSP or a ghost, and nothing in the design
requires that.
The port is already neutral. dpp_domain::ports::seal::SealPort says nothing
about any vendor. SealRequest, SealedEnvelope and SealFormat are
provider-neutral, and SealFormat already carries Cades, Xades, Pades and
Jades.
The wiring is not. QtspSealAdapter has exactly two states — the eID Easy
backend, or GhostSeal. dpp-node/src/main.rs selects between them by matching
on EideasyConfig::from_env(). There is no selector and no second backend.
So the constraint is roughly 200 lines of composition-root wiring, not an
architectural commitment.
Why this matters
A qualified certificate is issued to a legal person after identity
verification under eIDAS Art. 24(1). A self-hoster therefore cannot ride anyone
else's certificate — they must be their own subscriber. That makes "self-host
the software, then go contract with one specific vendor before you can publish a
compliant passport" the actual onboarding story, which is not a self-host story.
It is also worse for operators who already hold a relationship with a national
QTSP: they would be asked to re-procure through an aggregator that resells the
same underlying providers.
And it undercuts the positioning where it is strongest. The product is
operator-controlled infrastructure with no vendor lock-in; a hardcoded trust
provider is the one dependency that carries legal weight, and therefore the one
a compliance reviewer will notice first.
Shape
Cloud Signature Consortium (CSC) is the right interoperability target for a
second backend, rather than a third bespoke adapter.
- CSC API v2.2 defines the endpoints this needs:
/credentials/list,
/credentials/info for capability discovery, /signatures/sign/hash,
/signatures/timestamp, and OAuth2 token issuance.
- Critically, it defines service-level authorisation for electronic seals —
unattended signing with no per-signature activation step. That is the mode a
passport-sealing node needs; the attended flows are designed for human
signatures.
- It covers CAdES, XAdES, PAdES and JAdES, and distinguishes returning a raw
signature from returning a full AdES envelope.
Sketch:
- Core — no change. The port is already right.
dpp-seal — a provider selector plus a CSC backend alongside the existing
one.
- Engine — near-zero.
main.rs selects a backend instead of matching one
config type; the sealing_live guard and the trust tier are unchanged.
What is not known
Per-vendor detail the specification cannot answer, and no public page states for
any candidate:
- which CSC version each QTSP actually serves;
- whether their service-authorisation mode is enabled for seals rather than
only for attended signatures;
- their per-seal commercial terms.
Each of these needs a sandbox account per vendor to establish.
One thing to not carry forward
The csc/ module deleted alongside the eID Easy work is not a head start.
It modelled CSC v1.0, with a JAdES default this design would not use, against a
specification now several minor versions on. Reviving it means rewriting it —
the deletion stands.
Scope
This issue is the design and its cost, not a commitment to build it. It should
not start before the qualified-seal path is proven end-to-end against at least
one real provider, since a second backend written before the first one has ever
completed a live seal is a second untested thing rather than a hedge.
The problem
Sealing is provider-agnostic in the port and provider-locked in the composition
root. A self-hoster gets one specific QTSP or a ghost, and nothing in the design
requires that.
The port is already neutral.
dpp_domain::ports::seal::SealPortsays nothingabout any vendor.
SealRequest,SealedEnvelopeandSealFormatareprovider-neutral, and
SealFormatalready carriesCades,Xades,PadesandJades.The wiring is not.
QtspSealAdapterhas exactly two states — the eID Easybackend, or
GhostSeal.dpp-node/src/main.rsselects between them by matchingon
EideasyConfig::from_env(). There is no selector and no second backend.So the constraint is roughly 200 lines of composition-root wiring, not an
architectural commitment.
Why this matters
A qualified certificate is issued to a legal person after identity
verification under eIDAS Art. 24(1). A self-hoster therefore cannot ride anyone
else's certificate — they must be their own subscriber. That makes "self-host
the software, then go contract with one specific vendor before you can publish a
compliant passport" the actual onboarding story, which is not a self-host story.
It is also worse for operators who already hold a relationship with a national
QTSP: they would be asked to re-procure through an aggregator that resells the
same underlying providers.
And it undercuts the positioning where it is strongest. The product is
operator-controlled infrastructure with no vendor lock-in; a hardcoded trust
provider is the one dependency that carries legal weight, and therefore the one
a compliance reviewer will notice first.
Shape
Cloud Signature Consortium (CSC) is the right interoperability target for a
second backend, rather than a third bespoke adapter.
/credentials/list,/credentials/infofor capability discovery,/signatures/sign/hash,/signatures/timestamp, and OAuth2 token issuance.unattended signing with no per-signature activation step. That is the mode a
passport-sealing node needs; the attended flows are designed for human
signatures.
signature from returning a full AdES envelope.
Sketch:
dpp-seal— a provider selector plus a CSC backend alongside the existingone.
main.rsselects a backend instead of matching oneconfig type; the
sealing_liveguard and the trust tier are unchanged.What is not known
Per-vendor detail the specification cannot answer, and no public page states for
any candidate:
only for attended signatures;
Each of these needs a sandbox account per vendor to establish.
One thing to not carry forward
The
csc/module deleted alongside the eID Easy work is not a head start.It modelled CSC v1.0, with a JAdES default this design would not use, against a
specification now several minor versions on. Reviving it means rewriting it —
the deletion stands.
Scope
This issue is the design and its cost, not a commitment to build it. It should
not start before the qualified-seal path is proven end-to-end against at least
one real provider, since a second backend written before the first one has ever
completed a live seal is a second untested thing rather than a hedge.