Serve the AAS projection over content negotiation - #72
Conversation
Port traits now dispatch on the sector's catalog key rather than the Sector enum, so a plugin can be loaded for a sector this build has no variant for; the lockfile also moves wasmtime to 46.0.2 for two sandbox-state advisories.
An evidence dossier named only the node version, so it attested a compliance determination without naming the code that computed it — the regulatory logic behind a verdict lives in the core library, and the two version lines move independently.
The AAS projection has existed in the core library for several releases with no HTTP door; it is built from the verified signed payload and masked before any mapper sees it, so the new projection cannot widen what a public caller receives.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 41 |
| Duplication | 12 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
|
Pushed This PR now depends on odal-node/dpp-core#86 and cannot merge before it. That change fixes four defects that made the AAS Environment invalid against IDTA's published schema — pinned at 0.14.1, this door serves documents no AAS parser would accept. The repin needs to move to the release carrying those fixes, and the wording added to What the new commit adds:
One caveat on coverage: the cache-hit path is not driven end-to-end. Both success paths now return through a single constructor, and that constructor is unit-tested, but populating a real cache hit needs Redis and the resolver has no integration tier. The test says so rather than implying more coverage than it has.
|
Closes #69.
GET /dpp/{id}withAccept: application/aas+jsonnow returns an IDTA Asset Administration Shell Environment. This is the first time the AAS projection has been reachable over HTTP — it has existed in the core library for several releases with no consumer at all, and this repo did not even depend on the crate that holds it.Three commits, in the order they must land.
1. Repin to
dpp-core0.14.1Port traits dispatch on the sector's catalog key rather than the
Sectorenum, soPluginHostandComplianceRegistryimplementations take&strand call sites passSector::catalog_key(). Taking the enum meant a plugin could only ever be loaded for a sector this build already had a variant for.The lockfile also moves
wasmtime46.0.1 → 46.0.2, clearing RUSTSEC-2026-0222 and RUSTSEC-2026-0223 — low-severity advisories on the Wasm sandbox's internal state handling. Unrelated to the repin; the advisory database updated.Also fixes
.cargo/config.toml.example, which never gaineddpp-vcordpp-aasafter they were split out upstream. Anyone using the local-core override was silently getting those two from the registry and everything else from the working tree.2. Record the core version in the evidence dossier
A dossier named only the node version, so it attested a compliance determination without naming the code that computed it. The regulatory logic, schemas and disclosure policy behind a verdict live in the core library, and the two version lines move independently.
coreVersionis also reported on/api/v1/infoand/health.Breaking: the manifest uses
deny_unknown_fields, so this is a format change rather than an optional addition. No dossier exists outside tests, so format"1"is defined to include it rather than carrying an optional field permanently.3. The AAS door
Built from the verified signed public payload, never the live row — the same discipline the JSON-LD door uses, so body and signature agree by construction. An Environment assembled from current database state would drift from the view the operator actually signed.
Field selection is not made in this repo. The door calls
dpp_aas::build_aas_environment, which filters the passport through the disclosure seam before any mapper sees it. A projection that picked its own field list would eventually disagree with the canonical one, and the direction it disagrees in is the direction that leaks.Tests
406for a media type this route cannot produce.*/*,application/jsonand an absentAcceptstill reach the JSON-LD default.502.Two judgement calls
The
406is deliberately narrow. Only a header naming something genuinely unproducible gets it. An absent, empty,*/*,application/*,application/jsonorapplication/ld+jsonheader all still reach the JSON-LD default — RFC 9110 §12.5.1, and also what curl and most HTTP clients send. A broader reading would have broken every existing consumer of this route.A passport with no GTIN returns
406. Unsold-goods reports and untyped sectors carry none — they do not identify a trade item — so no AAS asset identity exists for them. That is more honest than an Environment with an inventedglobalAssetId.Scoped out
AAS reads are counted as the
jsonscan variant. Telling them apart from JSON-LD reads needs a migration, since thevariantcolumn isCHECK-constrained, and is only worth doing if the distinction is ever needed.Verification
just checkgreen against the published 0.14.1 crates, with no local-core override present: 591 tests.