Verifiably-Go โ Full-Reality Implementation Plan
This plan replaces every simulated/mock path in the verifiably-go UI with live
calls against the DPG stack in docker/stack/docker-compose.yml:
- walt.id Community Stack v0.18.2 โ issuer-api (
:7002), verifier-api
(:7003), wallet-api (:7001). - Inji Certify v0.14.0 โ primary Auth-Code instance (via certify-nginx
:8091,
tokens signed by eSignet) and Pre-Auth instance (:8094, tokens signed by
its own JWKS). - Inji Web Wallet v0.16.0 โ injiweb-ui (
:3004), mimoto (:8099), eSignet
(:3005). - Inji Verify v0.16.0 โ inji-verify-service (
:8082), inji-verify-ui (:3001). - WSO2IS v7.0.0 (
:9443) and Keycloak latest (:8180) as OIDC IDPs. - LibreTranslate (
:5000) for en-GB / fr-FR / es-ES UI translation.
Guarantees this plan makes explicit
G1. No simulation remains. Every current stub โ scan, upload, paste,
example-offer cycling, holder presentation, bulk issuance preview, PDF
issuance, auth โ resolves to a live call. The word "simulate" and the
flakyOutcome() helper both leave the production codepaths.
G2. Two Inji Certify cards. The catalog exposes
inji_certify_authcode and inji_certify_preauth as separate DPG entries.
Downstream screens (schema, mode, issue form, result) reflect each one's
actual capabilities, not a shared abstraction.
G3. Hard agnosticism line. CI rule:
grep -rE 'waltid|inji_|keycloak|wso2is|mimoto|esignet' internal/handlers templates vctypes backend cmd
must return zero matches. Vendor names live only in internal/adapters/*,
internal/auth/*, and backends.json.
Full "simulate โ real" inventory
| Current stub | Lives at | Replacement |
|---|---|---|
flakyOutcome() random 75/25 split |
mock/adapter.go:276 |
Deleted. All VerificationResult comes from a real verifier call. |
SimulateResponse โ mock FetchPresentationResult |
verifier.go:55 |
Handler renamed to FetchResponse; adapter polls real verifier session until terminal (walt.id /openid4vc/session/{state}, inji-verify /vp-result/{transactionId}). |
VerifyDirect method=scan |
verifier.go:72 |
Front-end adds getUserMedia + jsQR. Decoded QR text POSTs as CredentialData. |
VerifyDirect method=upload |
verifier.go:72 |
Multipart upload accepted. Server-side QR extraction via gozxing or pixelpass-compatible decoder. |
SimulatePresent |
handlers.go + holder_present.html |
New adapter method PresentCredential(ctx, credID, requestURI) drives the real OID4VP response path. |
ListExampleOffers 3 hardcoded fixtures |
mock/data.go:181 |
Replaced with BootstrapOffers(ctx) โ adapter issues a canned credential against its live backend at startup. |
PrefillSubjectFields mock values |
mock/data.go:132 |
walt.id โ empty; Inji Auth-Code โ MOSIP Identity Plugin; Inji Pre-Auth โ CSV data-provider. |
ListWalletCredentials seed |
mock/data.go:226 |
walt.id โ GET /wallet/{id}/credentials; Inji Web โ Mimoto session-scoped list. Walletbag JSON persistence on top. |
IssueBulk hardcoded 247/2 |
mock/adapter.go:152 |
Adapter iterates real CSV rows and aggregates real per-row outcomes. |
IssueAsPDF walt.id |
mock/adapter.go:138 |
ErrNotSupported (UI hides via DPG.DirectPDF=false). |
IssueAsPDF Inji Certify Auth-Code |
โ | Real call via Claim-169 QR/pixelpass path. |
CompleteAuth stub |
handlers.go:162 |
Real OIDC callback against whichever provider the user picked. |
| Inji Web "redirect only" | previous plan | Real: OAuth-style handshake with Mimoto; token stored on session; credentials readable via GET /v1/mimoto/wallet-credentials. |
| Inji Verify cross-device | previous plan | Real: POST /vc-submission, poll /vp-result/{id}. No browser-tab hand-off. |
| Top-bar language selector | not implemented | LibreTranslate, offline-cached via pre-extracted locales/{fr,es}.json. |
Two Inji Certify cards โ downstream capability redesign
Card A โ Inji Certify ยท Authorization Code (via eSignet)
- Tag:
Auth-Code ยท via eSignet - Tagline: "The holder logs into eSignet, which issues an OIDC access token
that Inji Certify accepts as a resource server." - Capabilities:
- Flow: holder is redirected to eSignet for interactive login (mock-identity UIN).
- Data: claims populate from MOSIP Identity Plugin via UIN lookup.
- Wallet: compatible with Inji Web Wallet; also any OID4VCI wallet supporting Auth-Code.
- Token: Bearer is eSignet-signed; Inji Certify validates via JWKS.
- Limitation: requires eSignet running; JWKS endpoint reachable.
Card B โ Inji Certify ยท Pre-Authorized Code
- Tag:
Pre-Auth ยท operator-driven - Tagline: "The operator stages claims directly on the certify instance; the
wallet exchanges a pre-authorized code with certify's own token endpoint โ
no user login." - Capabilities:
- Flow: operator POSTs claims to
/pre-authorized-data; offer URI carries pre-auth code. - Data: operator-entered or CSV row via Pre-Auth data-provider plugin.
- Wallet: paste-based in-process wallets, walt.id wallet (pre-auth), PDF destination. Not compatible with Inji Web Wallet.
- Token: certify-signed by this isolated instance's own JWKS.
- Limitation: no user consent screen; demo scenarios only.
- Flow: operator POSTs claims to
Downstream screen branching
- Schema picker โ live per-DPG
GET /v1/certify/credential-configuration.
The UI renders whatever each instance reports (no shared schema list). - Mode picker โ branches on
dpg.Capabilities:- Card A enables
wallet(redirect flow),inji_web. Disablespdfunless MOSIP Identity Plugin + pixelpass are configured. - Card B enables
wallet (paste),pdf. Disablesinji_web.
- Card A enables
- Issue form โ source picker branches:
- Card A: Manual entry, MOSIP Identity Plugin (UIN lookup).
- Card B: Manual entry, CSV row (farmer_identity_data.csv).
- Result panel โ shows the actual downstream endpoint/mechanism:
- Card A: eSignet authorization URL + expected JWKS source.
- Card B: pre-auth code inside offer URI + certify token endpoint.
All branchings are driven by dpg.Capabilities keys (flow.auth_code,
flow.pre_auth, token.source, wallet.compatible_with). No
if vendor == โฆ anywhere in handlers.
Architecture changes
vctypes.DPGgainsCapabilities []Capability{Title, Body, Kind}.- Two Inji Certify adapters, one client โ
Client{baseURL, flow, authMode, jwksURL}parameterised twice by the registry. - New adapter method
PresentCredential(ctx, credID, requestURI). - New adapter method
BootstrapOffers(ctx)โ live example offers at startup. IssueBulkRequest.RowCount intโRows []map[string]string. Real CSV.- Front-end
static/scanner.js(jsQR), server-side PDF QR extractor. - Walletbag JSON persistence (ported from ui-demo commit 9e9c169).
- Inji Web linking flow:
GET /holder/link/injiweb+ callback. - Inji Verify polling lives inside the injiverify adapter โ UI contract unchanged.
Packages
internal/
adapters/
registry/ # dispatcher; reads backends.json
waltid/ # issuer + verifier + wallet HTTP client
injicertify/ # parameterised twice (authcode + preauth)
injiweb/ # mimoto + esignet client + linking flow
injiverify/ # vc-verification + vc-submission + vp-result
libretranslate/ # translation client
auth/
keycloak/ # OIDC PKCE
wso2is/ # OIDC PKCE
session.go
store/
walletbag/ # JSON persistence
schemas/ # custom-schema persistence
httpx/ # shared transport: auth, retries, timeouts, errors
config/
backends.json
Milestones (simulation-free)
- Scaffolding + CI agnosticism rule. Registry,
httpx, env toggle, grep rule in CI. - walt.id end-to-end. All three roles. Bootstrap offers work. Walletbag populated from live wallet-api.
- Inji Certify โ two cards. Catalog entries, capability-driven downstream screens, both flows real end-to-end.
- Inji Verify.
vc-verification+vc-submission/vp-result, INJIVER-1131 guard, real polling. - Inji Web account linking. OAuth handshake; credentials readable; holder can present.
- Scan + upload on verifier. Camera path + PDF QR extraction; adapter paste/scan/upload paths live.
- Holder presentation (
PresentCredential). New adapter method; real OID4VP response. - Bulk issuance real CSV path.
- Auth (Keycloak + WSO2IS). Real OIDC login, token injection, refresh.
- i18n (LibreTranslate). Extractor, locale files, selector in top bar.
- Compose service + live e2e. Dockerfile, service entry, full test matrix.
Definition of done
grep -RE 'simulate|mock|Flaky|Example(Offer|Credential)s' cmd internal/handlers templatesreturns zero matches in production paths.- Agnosticism grep rule passes.
- Two Inji Certify cards render distinct capability lists; their mode-picker and issue-form options differ.
- Every handler path that previously called a mock function now has an integration test hitting a real container.
- Walletbag survives
docker compose down && up. - Scan, upload, paste, and present exchange real data end-to-end.
- Language selector drives real LibreTranslate translations.