TrustWeave SDK · 11 September 2026

Excellent code,
no way to ship it.

The first whole-repository pass since 2026-09-06. Every category is re-derived from the current tree rather than carried forward, and the mean lands at 8.6 / 10.

8.6 / 10Overall · six-category mean · previously 9.3 composite
3,897Tests passed · 0 failures · 0 errors · 15 documented skips
57.3%Merged line coverage · 39.8% branch

The previous 9.3 was a composite: each round from 2026-09-07 to 2026-09-10 reassessed one category and carried five forward. Nothing verified in those rounds regressed. What moves the number here is the long tail no recent round examined.

What is genuinely excellent

Findings

F1 · The tree does not pass its own build

./gradlew build fails — 232 ktlint violations across 10 files in kms:plugins:hashicorp (169 main, 63 test), 115 of them in VaultKeyManagementService.kt. This is the Vault work that closed finding R15, written and never linted. Everything else is clean: 3,897 tests pass and checkKotlinAbi passes.

F2 · main carries an unversioned copy of the reviewed code

169 uncommitted files. The same work is committed on codex/joint-remediation-20260910 and codex/configuration-data-20260910, neither merged; the tree differs from the former in two tracked files. Every score since 2026-09-07 was awarded to code reachable from no branch on main. CI on main is green as of e0a4464f — the red-since-August state no longer holds.

F3 · There is no publication path

No build file declares a publishing repository, so publishToMavenRepository is never created and publishToMavenLocal is the only thing that works. The POM has no scm block, which Central rejects outright, and its description points at docs/reference/module-maturity.md — a path that does not exist. v0.7.0 is tagged with no release and no artifact.

F4 · Coverage is bimodal

Recently reviewed modules are strong — observability 97.8%, verifiable-intent 90.0%, common 87.0%, kms-core 85.0%. The rest is not.

ModuleLinesLineBranch
credentials/credential-api4,09548.6%38.1%
did/did-core2,49158.1%33.4%
wallet/wallet-core21624.5%24.0%
did/plugins/web19121.5%29.7%
did/registrar76811.5%11.7%
credentials/credential-models-mp1,2146.8%14.3%
did plugins ion · sol · polygon · plc · cheqd · ens162–3241.2–2.5%~2%

The policy floors (56.0 line / 38.0 branch) sit just under the measurement — they record where the code is, not where it should be. Separately, of 2,363 Kotlin blocks inventoried across the docs, 9 are source-backed and executed.

F5 · 61 dependency coordinates escape the catalog, and have drifted

LibraryHardcodedCatalog
org.bitcoinj:bitcoinj-core0.16.20.17.1
org.web3j:core4.10.05.0.2 / 4.14.0
com.google.code.gson:gson2.10.12.14.0
org.slf4j:slf4j-api2.0.92.0.17
kotlinx-coroutines-test1.8.1 (5 modules)1.10.2

Dependabot raises PRs against the catalog; these modules never move — and they parse untrusted network input. The new observability module repeats the pattern, pinning OpenTelemetry 1.65.0 inline in four places.

F6 · Three shipped servers have no authentication primitive

DidRegistrarServer, VcApiServer and the status-list server ship with none. VcApiServer's own KDoc says it: "There is no API key, bearer token, or mTLS anywhere in this module." The registrar creates, updates and deactivates DIDs. A loopback default plus a note telling operators to add a proxy is guidance, not a control — and trust-registry-server already shows the right shape.

F7 · Instrumentation stops at the HTTP boundary

The observability module is excellent and wired into six hosts. Across the tree, 33 of 788 main-source files reference a logger; DID resolution, KMS, wallet and credential verification emit no structured events, metrics or correlation id. A host with a failed verification span has nothing to join it to.

F8 · Half the workflows are unpinned

ci.yml, release-evidence.yml and docs-check.yml pin every action by SHA. deploy.yml, conformance-nightly.yml and conformance-pr.yml pin none, and the last two declare no permissions block — the nightly job runs actions/github-script@v7, which creates issues, on the default token scope.

F9 · Nothing is declared production-supported

The capability catalog has 8 entries for 107 modules, none supported. The custody runbook states no profile is qualified. A consumer cannot tell which module is production code.

F10 · A presenter-reachable exception escapes the verification contract

ChainVerifier.verify translates only SQLException from the budget reservation, but the ledger also throws IllegalStateException on a stored-policy mismatch. The ledger scope is sha256 of the L2 JWT without disclosures, so one signed L2 carrying two payment mandates with different budgets reaches it. Fails hard, not open — but it breaks the result contract on presenter-controlled input. The adjacent negative-max variant is not a defect: it is caught as Malformed and fails closed.

F11 · Two documented cancellation gaps

BitstringStatusListManager lines 1211 and 1263 iterate 131,072 entries with no cooperative cancellation, in non-suspend functions that cannot reach coroutineContext. The TODOs prescribe the fix.

F12 · The validation gates read the wrong directory on Windows

check-test-evidence.py and check-junit-contract.py default to the in-repo build/, which on this project's documented Windows layout is a stale 2026-09-06 snapshot. Run with their defaults they report 40 evidence failures and 8 invalid JUnit methods; pointed at the real build root both exit 0 with zero failures. This caught me mid-review — the 8 looked like the known non-void @Test trap until I confirmed all six named OID4VP tests do appear in the current JUnit XML.

F13 · 550 broad catches, 21 with a comment for a body

Every security path I read fails closed correctly, but the surface has not been audited, and a swallowed CancellationException is exactly the class of defect these rounds keep finding one at a time. A balanced-brace scan finds zero genuinely empty catch bodies — an earlier line-counting grep in this review reported 12, which was wrong — and 21 whose body is only a comment. Four of those sat in suspend functions and swallowed cancellation. The wider surface is 187 broad catches inside suspend functions that neither rethrow nor mention cancellation; most convert to a sealed failure and are fine.

Scores

Category2026-09-10NowWhy
Security and access control9.08.8F6, F8, F9, F10
Observability and diagnosability9.69.0F7 — the 9.6 was scored against the six HTTP hosts, not the library
Reliability and scale9.59.2F11, and no deployment-scale evidence
Configuration and data9.58.8F5
Deployment and release8.57.0F1, F2, F3, F12
Testing and documentation9.58.5F4

Equal-weight mean: 51.3 ÷ 6 = 8.55, rounded to 8.6.

Getting above 9.5

Full acceptance criteria in tasks.json. Fifteen tasks; the projected mean on completion is 9.52.

Week 1 — stop the bleeding

Weeks 2–3 — make it shippable

Weeks 2–6 — the big one

Weeks 4–5, then ongoing

Two items do not compress no matter how fast the code goes: Sonatype namespace verification (T03) and real custody or hardware qualification (T09). Start them first even though they finish last.

Evidence and machine-readable assessment

Tree: e0a4464f plus 169 uncommitted files · full build 13m38s, 2188 actionable tasks · checkKotlinAbi passed · all seven Python validation gates executed.

Remediation, same day

Nine of fifteen tasks closed with local evidence. Four remain open as multi-week work, and two need an action only the repository owner can take. Full record in remediation.json.

FindingStateWhat changed
F1 · build failsClosedktlintFormat cleared all 232 violations in kms:plugins:hashicorp. The module baseline is untouched, so nothing was grandfathered.
F2 · unversioned treePartlyThe tree is committed. Merging the codex/* branches and pushing rewrites shared history and publishes the work, so it is left to the owner.
F3 · no publication pathClosed in codeMaven repository declared in the root build and the BOM, scm and issueManagement in every POM, the dead documentation URL corrected, and a reviewer-gated publish job on v* tags. Sonatype namespace verification remains an external step — see the runbook.
F4 · coverageOpenTwo to three weeks of test writing; not attempted.
F5 · catalog driftClosedAll 61 literals moved into the catalog across 34 build files. web3j, gson, slf4j and coroutines-test converged; bitcoinj stays on 0.16.2 through an explicit bitcoinj-legacy alias because 0.17 is a breaking API change — recorded rather than hidden.
F6 · no server authenticationClosedNew HostAuthentication: constant-time bearer tokens, host-supplied authorizers, an explicit frontedByProxy declaration, per-caller rate limiting. The three servers refuse mutations with 503 until a host says which applies. Breaking; in the changelog.
F7 · library instrumentationOpenOne week; not attempted.
F8 · unpinned workflowsClosedAll 14 references SHA-pinned, both missing permissions blocks added, and the nightly job's issues: write moved to a job that runs no repository code.
F9 · nothing supportedPartlyA ratchet: every module must declare a maturity or be recorded as unassessed, and the unassessed count may only fall. Classifying the 102 recorded modules is an owner decision.
F10 · escaping exceptionClosedLedger IllegalStateException and IllegalArgumentException become an invalid result, with a regression driving both through a refusing data source.
F11 · cancellation gapsClosedBoth loops are suspend and probe every 8192 bits. A test proves a cancelled revocation issues fewer statements than a completed one, so the decode really did abort.
F12 · wrong build rootClosedscripts/build_root.py resolves the root the way the build does and refuses one holding no results, instead of reporting phantom gaps.
F13 · broad catchesPartly; count correctedZero genuinely empty bodies, not 12. Four of the 21 comment-only bodies sat in suspend functions and swallowed cancellation; all four now rethrow. 187 remain to triage.

Five new gates keep the closed findings closed: check-workflow-pinning, check-dependency-catalog, check-publication, check-capability-coverage, and the shared build_root resolver. All are wired into CI and the release workflow, and each ships with unit tests.