WebVH end-to-end harness
April 15, 2026 · View on GitHub
This directory contains the Traction WebVH E2E harness entrypoint and phase registry.
Current runtime behavior:
- working CLI (
run.py) - profile/phase registry (
phases/smoke.pyliveness,phases/webvh.pyWebVH configure/create,phases/connect.pyOOB + DID Exchange,phases/setup.pyAnonCreds schema/cred-def,phases/indy.pyIndy endorser + public DID on BCovrin test, issue/verify/revoke) - environment + token wiring
- smoke phase (
GET /status/live,GET /tenant/walletfor issuer and holder) - issuer wallet upgrade, WebVH configure,
webvh-create, AnonCreds schema + cred-def with revocation, DIDComm connection using publicdid:webvh, issue-credential-2.0, present-proof-2.0, revocation, second proof expecting failure
Current scope
Implemented
smokephase callsGET /status/liveand authenticatedGET /tenant/wallet(issuer + holder)upgrade-anoncreds-wallet:GET /tenant/walletforsettings.wallet.nameand type (ACA-PyGET /settingsomitswallet.name), optionalPOST /anoncreds/wallet/upgrade, poll untilaskar-anoncredsconfigure-webvh-plugin:GET /tenant/server/status/config(controller defaults only), optionalWEBVH_WITNESS_INVITATIONor fetch/api/invitationson the WebVH server,POST /did/webvh/configuration(INFO logs the sanitized request body; full responses and other HTTP bodies only withrun.py -v/ debug logging). Merges storedparameter_optionsfromGET /did/webvh/configuration; setswitness_thresholdonly whenWEBVH_WITNESS_THRESHOLDis positive, and drops any mergedwitness_thresholdwhen it is not (avoids echoing an old stored value)webvh-create:POST /did/webvh/createwithoptions(namespace,identifierfor the path segment,didcomm: true, optionalwitness_thresholdwhen env is positive, optionalserver_urlfrom stored config or context). Default identifier is 8 random[a-z0-9]characters (envWEBVH_CREATE_ALIAS/WEBVH_CREATE_IDENTIFIER). Sendsapply_policy: trueby default (merge with WebVH server identifier policy; matches ACA-Py). SetWEBVH_CREATE_APPLY_POLICY=falseto skip policy merge. Setsctx.webvh_last_created_didwhen the response includes adid:webvhidpublish-schema-webvh/publish-cred-def-webvh:POST /anoncreds/schemathenPOST /anoncreds/credential-definitionwithsupport_revocation: trueandrevocation_registry_size(default 4 inconstants.py). Idempotent when the same schema/cred-def already exists for the WebVH issuer DID. Schema/cred-def responses are debug-only (-v); INFO logs HTTP status lines and published idsoob-didexchange-webvh-didcomm: issuerPOST /out-of-band/create-invitationwithuse_didset to the wallet’sdid:webvh(noPOST /wallet/did/public— that is Indy public-DID/endorser, not this flow) and DID Exchange 1.1; holderPOST /out-of-band/receive-invitation(auto_accept); polls issuer-side OOB record / connection list until the exchange is active or completedissue-webvh:POST /issue-credential-2.0/send-offer(anoncreds filter,auto_issue); holderPOST …/send-request; polls until issuer exchange is doneverify-webvh/verify-webvh-post-revoke:POST /present-proof-2.0/send-requestwith anoncreds non-revocation interval, holderPOST …/send-presentation; first round expects verified; afterrevoke-webvh, second round expects not verified (or abandoned)revoke-webvh:POST /anoncreds/revocation/revokewithrev_reg_id/cred_rev_idwhen present (elsecred_ex_id);publish/notifyfromconstants.py(defaults: publish on, holder notify off)- context loading from
.envand shell env - required issuer/holder token validation at startup
- profile execution and end-of-run summary (indented
run+webvhsections:traction_url; after create, fulldid:webvh:…and BCVH-style explorer links{server_url}/api/explorer/dids?scid=…and{server_url}/api/explorer/resources?scid=…when a DID is present — e.g. resources for an SCID) --witness: addsendorsement: trueto the WebVH configure POST (endorser-style flow)- Indy (BCovrin test) — profile
indy-bcovrin-e2e(see below;indy-bcovrin-setupis an alias):smoke(pollsGET /tenant/walletthrough 503 upgrade),upgrade-anoncreds-wallet(issuer), ledger + endorser + public DID +publish-schema-indy/publish-cred-def-indy(same anoncreds revocation options as WebVH; unqualified IndyissuerId/schemaIdfor resolver compatibility), thenoob-didexchange-indy-didcomm: OOB + DID Exchange 1.1 withuse_public_did: true(wallet ledger public DID; do not pass a shortuse_did— invalidservicesand 422 on receive), distinct OOB/holder aliases from the WebVH path (constants.py), thenissue-indy/verify-indy/revoke-indy/verify-indy-post-revoke— sameanoncredsfilters and proof shape as the WebVH phases, usingctx.indy_cred_def_id.
Prerequisites
- Python 3.10+
- Poetry 1.8+
- Traction tenant proxy reachable (default BC Gov sandbox URL; override with
TRACTION_TENANT_PROXY_BASE)
Setup
cd scripts/webvh-e2e
poetry install
cp .env.example .env
Run commands from this directory (scripts/webvh-e2e) so python-dotenv picks up ./.env (it does not override variables already set in your shell).
Environment variables
The checked-in .env.example comments optional WebVH create settings; other optional variables below work when set in .env or the shell.
Tuning (schema/cred-def, preview attributes, polling intervals, revoke flags, wallet-upgrade wait): edit constants.py — not environment variables. E2E_SMOKE_WALLET_READY_* / E2E_SMOKE_WALLET_POST_READY_SETTLE_SEC control smoke polling through GET /tenant/wallet 503s and optional settle after both wallets are OK (the settle is skipped when issuer and holder are already askar-anoncreds). Indy E2E builds a fresh cred-def tag each run (E2E_INDY_CRED_DEF_TAG_PREFIX + random hex) so publish-cred-def-indy always creates a new definition and does not hit duplicate-tag 400 from a prior run.
Logging: At INFO, TractionClient logs the full JSON body of each POST except POST /did/webvh/configuration (that one is sanitized). Issue and proof requests can include attribute values—treat default logs as potentially sensitive in shared CI or support channels.
Required:
TRACTION_TENANT_PROXY_BASE(default:https://traction-sandbox-tenant-proxy.apps.silver.devops.gov.bc.ca; usehttp://localhost:8032for a local stack)TRACTION_ISSUER_TENANT_TOKENTRACTION_HOLDER_TENANT_TOKEN
Optional (WebVH):
WEBVH_WITNESS_INVITATION— fullwitness_invitationstring forPOST /did/webvh/configuration(skips unauthenticated fetch from the WebVH server)WEBVH_CREATE_NAMESPACE(defaulttraction-e2e) —POST /did/webvh/createoptions.namespaceWEBVH_CREATE_ALIAS— fixedoptions.identifier(default: random 8-char value when unset)WEBVH_CREATE_IDENTIFIER— same asWEBVH_CREATE_ALIAS(fixedoptions.identifier)WEBVH_WITNESS_THRESHOLD(default0, omitted from requests) — when set to a positive integer, addsoptions.witness_thresholdon create andparameter_options.witness_thresholdon configureWEBVH_CREATE_APPLY_POLICY— set to0/false/no/offto sendapply_policy: false(omit server policy merge; default in harness is on /true)
Optional (Indy / BCovrin test — profile indy-bcovrin-e2e):
E2E_INDY_WRITE_LEDGER_ID— ledger id forPUT /ledger/…/set-write-ledger(defaultbcovrin-testinconstants.pyif unset)E2E_INDY_REGISTER_NYM_ALIAS— optional alias forPOST /ledger/register-nym(default: tenanttenant_name/wallet_idfromGET /tenant, elsewebvh-e2e-indy)
Issuer tenant requirements for Indy: the Innkeeper tenant must be allowed to connect to endorsers and create a public DID on the target ledger (same as the Tenant UI “Issuance” prerequisites). Otherwise POST /tenant/endorser-connection returns 400 (“not configured as an issuer”).
Profiles
all(default): same phases asnew-issuer-webvh(WebVH end-to-end only)new-issuer-webvh: WebVH path fromsmokethroughverify-webvh-post-revokeindy-bcovrin-e2e: Full Indy path on BCovrin test — smoke (wallet readiness + optional settle inconstants.py), issuerupgrade-anoncreds-wallet, ledger, endorser, public DID, anoncreds schema/cred-def, DIDComm over Indy public DID, issue / verify / revoke / verify-after-revoke (holder token required).indy-bcovrin-setupis the same phases (legacy name).
Usage
From scripts/webvh-e2e:
poetry run python3 run.py
poetry run python3 run.py --profile new-issuer-webvh
poetry run python3 run.py --profile all -v
poetry run python3 run.py --profile new-issuer-webvh --witness
poetry run python3 run.py --profile indy-bcovrin-e2e