You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ROADMAP.md
+11-8Lines changed: 11 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,7 +61,8 @@ Read from the TS and Python SDK changelogs plus the AdCP 3.1 beta release notes.
61
61
-**Open error-code decoding.** As SDK forward-compatibility practice, receivers should not fail closed on unknown `error.code`; classify from `recovery` and default conservatively when absent. Java generated enums need an unknown-value strategy, not a hard enum parse failure. → [`codegen`](#track-2--l0-types--codegen) + [`transport`](#track-3--l0-transport-mcp--a2a).
62
62
-**Advisory `errors[]` on success payloads.**`STALE_RESPONSE`, canonical-format projection warnings, pixel-tracker downgrade/upgrade warnings, and similar advisories ride in payload `errors[]` while transport/task success remains success. Java callers and validators must not promote advisory payload errors to thrown failures. → [`transport`](#track-3--l0-transport-mcp--a2a) + [`testing`](#track-9--testing--conformance).
63
63
-**Universal request `idempotency_key`.** 3.1 read tools accept every-request envelope fields and the compliance suite probes this. Java request builders and MCP wrapper validation must tolerate and emit envelope fields on every task request, not only write calls. → [`codegen`](#track-2--l0-types--codegen) + [`transport`](#track-3--l0-transport-mcp--a2a) + [`async-l3`](#track-6--l3-idempotency-async-tasks-webhooks).
64
-
-**Webhook token round-trip and endpoint proof-of-control.**`McpWebhookPayload.token` is typed; durable account-level webhook configs require proof-of-control semantics and stable `subscriber_id` replace/upsert behavior. → [`signing`](#track-4--l1-signing) + [`async-l3`](#track-6--l3-idempotency-async-tasks-webhooks) + [`multitenant`](#track-5--l2-account-store-registry-multi-tenant).
64
+
-**Webhook token round-trip.**`McpWebhookPayload.token` is typed and must echo through webhook dispatch/receipt paths. → [`signing`](#track-4--l1-signing) + [`async-l3`](#track-6--l3-idempotency-async-tasks-webhooks).
@@ -71,11 +72,13 @@ Read from the TS and Python SDK changelogs plus the AdCP 3.1 beta release notes.
71
72
-**Canonical creative formats.**`format_options[]`, `format_option_refs`, `format_option_id`, `v1_format_ref`, named canonical format helpers, v1↔v2 projection, pixel-tracker advisory downgrades, and cache-backed canonical registries. The beta.2 `capability_ids` write path was removed before beta.5; Java should model the beta.5 `format_option_*` names from the start. → [`codegen`](#track-2--l0-types--codegen) + [`transport`](#track-3--l0-transport-mcp--a2a).
72
73
-**Public placement catalogs.**`adagents.json` can publish placement catalogs and publisher-scoped `placement_refs`; seller-private routing stays out of public placement schemas. → [`multitenant`](#track-5--l2-account-store-registry-multi-tenant).
-**Delivery and billing finality.**`reach_window`, `viewability.viewed_seconds`, windowed pull recovery, row-level delivery finality, `report_usage` finality, and `BILLING_OUT_OF_BAND`. → [`codegen`](#track-2--l0-types--codegen) + [`testing`](#track-9--testing--conformance).
75
+
-**Delivery and billing finality.**`reach_window`, `viewability.viewed_seconds`, windowed pull recovery, row-level delivery finality, `report_usage` finality, and `BILLING_OUT_OF_BAND` as an error-code surface. → [`codegen`](#track-2--l0-types--codegen) + [`testing`](#track-9--testing--conformance).
75
76
-**Action discovery.**`allowed_actions[]`, `available_actions[]`, finer media-buy action enum values, `ACTION_NOT_ALLOWED`, and helper-level request decomposition in TS/Python. Java should expose typed helpers around `update_media_buy` mutations instead of forcing every adopter to re-parse action intent. → [`lifecycle`](#track-7--l3-lifecycle--transitions) + [`transport`](#track-3--l0-transport-mcp--a2a).
76
77
77
78
**Cross-SDK helper surface to match**
78
79
80
+
TS/Python helper names are references, not Java naming requirements. Java idioms win: `*Request` builders, records/sealed types, instance or namespaced helpers where clearer than free functions, and `@Nullable` rather than `Optional` on public model fields.
81
+
79
82
-**TS `@adcp/sdk@8.1` helper additions.** Root exports now include canonical creative format helpers, format projection/write-side helpers, `ensureGetProductsCacheScope()` / `validateGetProductsCacheScope()`, `parseWholesaleFeedWebhookNotification()` / `normalizeWholesaleFeedWebhookNotification()`, signal discovery helpers, `decomposeUpdateMediaBuy()` / `assertUpdateMediaBuyAllowed()`, per-tool type slices, SSRF-safe networking helpers, typed server `*Payload` aliases, and 3.1 compliance/cache selection in the runner. Java equivalents belong in the main `adcp`, `adcp-server`, and `adcp-testing` artifacts rather than new artifacts.
80
83
-**Python `adcp@6.x` helper additions.** Python now has version-routed validation, 2.5/3.0/3.1 beta schema caches, canonical-format projection, webhook proof-of-control helpers, wholesale feed sender, request-scoped capabilities hooks, unknown-field policy and hook composition, media-buy version handling/update actions, externally managed webhook signing capabilities, and permissive property resolution. Java server APIs should mirror the capability/hook seams even if implementation names differ.
81
84
@@ -196,7 +199,7 @@ Each track entry has:
196
199
197
200
| Milestone | Target | Release gate |
198
201
|---|---|---|
199
-
| v0.1 alpha | M+3 |L0 surface compiles against the D23 target bundle (`3.1.0-beta.5`, or 3.1 GA if cut before the codegen PR), wire-version negotiation works for stable and prerelease tokens, multi-bundle validators can serve 3.0 and 3.1 traffic, SSRF/auth discovery baseline lands, storyboards green against reference mock-server in CI.Local Gradle artifacts only (per D6 — first Maven Central publish at v0.3). |
202
+
| v0.1 alpha | M+3 | D23 target bundle compiles (`3.1.0-beta.5`, or 3.1 GA if cut before the codegen PR).<br>Wire-version negotiation works for stable and prerelease tokens.<br>Multi-bundle validators can serve 3.0 and 3.1 traffic.<br>SSRF/auth discovery baseline lands.<br>Storyboards green against reference mock-server in CI.<br>Local Gradle artifacts only (per D6 — first Maven Central publish at v0.3). |
@@ -289,7 +292,7 @@ The RFC's M+12 target is the realistic line. Pre-committing M+9 and slipping is
289
292
**Scope:**
290
293
291
294
- Hand-rolled RFC 9421 canonicalizer (it's small and spec-tight; `org.tomitribe:http-signatures` is the wrong spec). Verifier test harness mirrors the TS one.
292
-
-`SigningProvider`SPI via `META-INF/services/`. API shape takes explicit `SigningContext` rather than a single `AdcpUse`; receivers enforce purpose at JWK `adcp_use`.
295
+
-`SigningProvider`+ `VerificationKeyResolver` SPIs via `META-INF/services/`. Signing takes explicit `SigningContext` rather than a single `AdcpUse`; verification starts from inbound `kid` and only then maps to tenant/principal context. Receivers enforce purpose at JWK `adcp_use`.
293
296
- Tenant-aware key selection at the signing boundary (D22). The API cannot model one global key per `adcp_use`: multi-tenant operators need one JWKS endpoint with distinct `kid` values per publisher tenant under the same `adcp_use`. The v0.2 signing surface freezes `SigningContext` in [`specs/signing-context.md`](specs/signing-context.md); v0.3 connects it to `AccountStore` tenant resolution.
294
297
- In-process provider via JCA Ed25519 / ECDSA. **No Bouncy Castle in core** — JDK 21 has Ed25519 natively.
295
298
- AWS KMS provider via `software.amazon.awssdk:kms`. Lazy-init.
@@ -336,7 +339,7 @@ The RFC's M+12 target is the realistic line. Pre-committing M+9 and slipping is
9.**MIT-licensed dependency position.** D9 picked the MIT-licensed `io.modelcontextprotocol.sdk`. License is compatible with Apache 2.0 downstream use, but the foundation may want an explicit position on accepting MIT deps in officially supported SDKs.
569
572
10.**Funding model shape.** RFC framing (contributed engineer at 50%+ for ~12 months + named maintainer + 2–3 design partners) is the right ask; whether it's pooled member funding, single-anchor-org contribution, or foundation grant is open.
570
-
11.**Design partner outreach.** Anchor candidates by audience segment: one publisher running Spring Boot, one SSP, one broadcaster middleware team, and one EU ad-server vendor on Spring Boot 3.x / OAuth 2.1 / multi-tenant signing shape. ADvendio is a concrete reviewer candidate in that last segment, but has not committed engineering time or an LOI; still need 2–3 committed design partners before scaling.
573
+
11.**Design partner outreach.** Anchor candidates by audience segment: one publisher running Spring Boot, one SSP, one broadcaster middleware team, and one EU ad-server vendor on Spring Boot 3.x / OAuth 2.1 / multi-tenant signing shape. Concrete company names belong in a private outreach tracker until they commit engineering time or an LOI; still need 2–3 committed design partners before scaling.
571
574
12.**WG vote timing.** Recommendation: hold the vote at v0.1 alpha milestone (concrete working code) rather than now (abstract commitment).
The generated JSON adapter maps recognized wire values to `Known` and unrecognized wire values to `Unknown`. Serialization preserves `rawValue()` exactly.
32
32
33
+
## Jackson binding
34
+
35
+
Open enum wrappers do not use Jackson `@JsonTypeInfo`; they serialize as the flat protocol string. The generator emits a custom `JsonDeserializer<T>` for each open vocabulary that maps the incoming string to `Known` or `Unknown`, plus a matching `JsonSerializer<T>` that writes `rawValue()`.
36
+
37
+
This is separate from polymorphic envelope handling in Track 2. Envelope types may use discriminator-based Jackson handling; open vocabularies must not, because the wire value is a scalar string.
38
+
33
39
## Generator rules
34
40
35
41
- Open vocabularies generate a sealed wrapper with `Known` and `Unknown`.
36
42
- The nested known-value type may be a Java enum when the known value set is useful for switch exhaustiveness.
37
43
- Unknown raw values are never rewritten, lowercased, uppercased, or mapped to a generic `UNKNOWN` sentinel that loses the original string.
44
+
- Each open vocabulary emits Jackson serializer/deserializer bindings that preserve the flat scalar wire shape.
38
45
- Closed vocabularies may generate plain Java enums.
39
46
- The schema post-processor owns the open/closed classification; contributors must not infer it from value count.
Inbound verification starts from the signed request, especially the `kid` header. The resolver maps the inbound key id to a verification key and any resolved tenant/principal metadata; the verifier then checks the signature and `adcp_use` purpose.
36
+
37
+
```java
38
+
publicinterfaceVerificationKeyResolver {
39
+
VerificationKeyresolve(VerificationInputinput);
40
+
}
41
+
42
+
public record VerificationInput(
43
+
AdcpUse expectedUse,
44
+
String kid,
45
+
SignedInput input) {
33
46
}
34
47
```
35
48
@@ -41,8 +54,9 @@ There is no release API shaped as `SigningProvider.forUse(AdcpUse)`. If a protot
41
54
-`tenant` is nullable for single-tenant deployments and caller-side signing where no publisher account has been resolved yet.
42
55
-`principal` is nullable and carries the resolved account/principal when available.
43
56
- Providers may use `tenant`, `principal`, or both to select `kid`; they must not ignore `use`.
44
-
- Verification still enforces the key purpose at JWK `adcp_use`; tenant context only narrows which key is expected or acceptable.
57
+
- Verification starts from inbound `kid`; tenant context is derived after key lookup and never assumed before signature verification.
58
+
- Verification still enforces the key purpose at JWK `adcp_use`.
45
59
46
60
## Milestone contract
47
61
48
-
v0.2 freezes the `SigningContext` type and SPI method signatures. v0.3 wires `AccountStore` / `adagents.json` principal resolution into the context passed to webhook and signed-request providers.
62
+
v0.2 freezes the `SigningContext`, `SigningProvider`, and `VerificationKeyResolver` shapes. v0.3 wires `AccountStore` / `adagents.json` principal resolution into the context passed to webhook and signed-request providers.
0 commit comments