Skip to content

v0.3.0

Latest

Choose a tag to compare

@github-actions github-actions released this 29 May 14:43
220508b

[0.3.0] - 2026-05-29

This release closes the failures reported by the
did:webvh interop test suite
against the v0.2.0 line (see issue #2).

Added

  • Negative interop test vectors vendored from the upstream
    did:webvh test suite under
    didwebvh-core/src/test/resources/interop/
    (basic-create/python, basic-update/ts, full java-eecc log
    set, pre-rotation-consume/{rust,java-eecc},
    witness-update/rust, witness-threshold/rust, and
    negative-cross-did-witness-replay/ts), each exercised by a
    dedicated JUnit test under didwebvh-core/.../interop/.
  • Implicit #files and #whois services in resolved DID
    Documents
    (spec §3.8 and §3.9): the resolver now emits a
    relativeRef #files service and a
    LinkedVerifiablePresentation #whois service unless the
    controller has already declared services with the same id. The
    shared logic lives in didweb.ImplicitServices and is also
    reused by DidWebPublisher.

Fixed

  • Cross-DID witness-proof replay (spec §3.7.5, lines 884-889):
    when the witness parameter is set to {} while witnesses were
    active, the transition entry MUST itself be witnessed by the
    prior witnesses. WitnessValidator was merging the empty config
    in first and skipping the entry as inactive, which let an
    attacker disable witnessing and replay a stale (or cross-DID)
    proof for an earlier entry. The validator now tracks the prior
    config and, on a witness-off transition, requires approval from
    the prior witnesses.
  • witness: {} round-trip across implementations: Python and
    TS serialise an empty "witness": {} object in parameters when
    no witnesses are configured. Gson was instantiating
    WitnessConfig via Unsafe.allocateInstance, bypassing the
    constructor and leaving witnesses null — every call to
    isActive() / getWitnesses() then NPE'd on the first
    Python/TS log entry. Java was also re-serialising the empty
    config as {"threshold":0,"witnesses":[]} instead of {},
    producing a different JCS canonical form for SCID, entry-hash
    and proof computation. Added a no-arg constructor (so Gson uses
    Constructor.newInstance) and a WitnessConfigTypeAdapter that
    round-trips the empty-object form.
  • Pre-rotation entries authorized against the wrong key set
    (spec §3.7.5): when the previous entry committed a
    nextKeyHashes, the active updateKeys for the current entry are
    the current entry's own updateKeys, not the previous entry's.
    LogChainValidator was unconditionally using the previous
    entry, failing every pre-rotation-consume log from rust and
    java-eecc. DeactivateDidOperation made the same mistake when
    emitting its intermediate pre-rotation-consuming entry; it now
    signs that entry with nextRotationSigner. Regenerated
    pre-rotation-log.jsonl under the corrected rules.
  • Witness-proof pruning and bare-multikey witness ids (spec
    §3.7.8): a witness proof at versionId V implicitly approves all
    prior log entries, and the DID Controller SHOULD prune
    did-witness.json to retain only the latest proof per witness.
    WitnessValidator required an exact-versionId proof per entry
    and failed with "missing witness proof" against the Rust pruned
    files. It also compared witness ids as did:key:<multikey>
    against the Rust implementation's bare-multikey form, yielding 0
    authorized proofs. The validator now pre-verifies all proofs
    once, counts distinct authorized witnesses per entry, and
    matches witness ids by multikey portion to accept both
    did:key:z6Mk… and bare z6Mk… forms.
  • Pre-rotation and portable-SCID negative-test gaps closed for
    negative-pre-rotation-omit-updatekeys and
    negative-portable-scid-swap.
  • Release auth: auto-detect and decode base64-encoded
    user:pass OSSRH_TOKEN values so Sonatype publishing succeeds
    with either token form.

Changed

  • CI: GitHub Actions upgraded to versions compatible with
    Node.js 24, and Node.js 24 is forced in both the CI and release
    workflows to silence the deprecation warning emitted by older
    actions on the GHA runners.
  • Release notes: the GitHub Release body is now generated
    directly from the matching ## [VERSION] section of this
    CHANGELOG (with an appended Maven Central coordinate), and the
    release attaches only the self-contained didwebvh-wizard.jar
    uber-jar — library modules are consumed from Maven Central.
  • Test coverage: raised didwebvh-core from ~77% to ~82% on
    the Codecov metric (line coverage 93%) by covering real branches
    in LogChainValidator, LogProcessor, DidResolver,
    MigrateDidOperation, CreateDidOperation, DidWebVhUrl, and
    the file fetcher — malformed versionId/versionTime, future
    versionTime rejection, witness threshold bounds, method-version
    downgrade, query-param parsing, PROACTIVE / WHEN_REQUIRED witness
    fetch branches, migrate guards (null/empty inputs, deactivated,
    newPath, alsoKnownAs dedup), controller-list array vs string
    forms, and URL port / IPv6 / empty-domain rejection.

Artifacts

Maven Central (recommended for library users):

<dependency>
  <groupId>io.github.decentralized-identity</groupId>
  <artifactId>didwebvh-java</artifactId>
  <version>0.3.0</version>
</dependency>

The aggregate didwebvh-java artifact transitively pulls in didwebvh-core and didwebvh-signing-local. Depend on didwebvh-core directly if you plan to supply your own Signer implementation.

<!-- Core only (BYO Signer): -->
<dependency>
  <groupId>io.github.decentralized-identity</groupId>
  <artifactId>didwebvh-core</artifactId>
  <version>0.3.0</version>
</dependency>

Browse all modules: https://central.sonatype.com/namespace/io.github.decentralized-identity

CLI wizard uber-jar is attached to this release below (not published to Maven Central).

Full changelog: https://github.com/decentralized-identity/didwebvh-java/blob/v0.3.0/CHANGELOG.md