Skip to content

Commit 92fc8e3

Browse files
Merge pull request #196 from taleodor/2025-10-streamline-descovery
Streamline Discovery
2 parents 1726b76 + 7559166 commit 92fc8e3

File tree

3 files changed

+330
-30
lines changed

3 files changed

+330
-30
lines changed

discovery/readme.md

Lines changed: 159 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -149,17 +149,73 @@ Example:
149149
urn:tei:uuid:cyclonedx.org:d4d9f54a-abcf-11ee-ac79-1a52914d44b1
150150
```
151151

152+
#### EAN/UPC
152153

153-
#### Other types to be defined
154+
Where the `unique-identifier` is a EAN/UPC.
154155

155-
- EAN
156-
- GS1
157-
- STD
156+
Syntax:
157+
158+
```text
159+
urn:tei:eanupc:<domain-name>:<ean/upc-number>
160+
````
161+
162+
Example:
163+
```text
164+
urn:tei:eanupc:cyclonedx.org:1234567890123
165+
```
166+
167+
#### GTIN
158168

159-
Note that if an identifier, like EAN, is used for multiple different products then this
160-
EAN code will not be unique for a given product and should not be used as an identifier.
161-
In this case, the vendor is recommended to create a separate identifier for each unique
162-
product sold by other means, like UUID or hash.
169+
Where the `unique-identifier` is a [GTIN](https://www.gs1.org/standards/id-keys/gtin).
170+
171+
Syntax:
172+
173+
```text
174+
urn:tei:gtin:<domain-name>:<gtin-number>
175+
````
176+
177+
Example:
178+
```text
179+
urn:tei:gtin:cyclonedx.org:0234567890123
180+
```
181+
182+
#### ASIN
183+
184+
Where the `unique-identifier` is a [ASIN](https://sell.amazon.com/blog/what-is-an-asin).
185+
186+
Syntax:
187+
188+
```text
189+
urn:tei:asin:<domain-name>:<asin-identifier>
190+
````
191+
192+
Example:
193+
```text
194+
urn:tei:asin:cyclonedx.org:B07FZ8S74R
195+
```
196+
197+
198+
#### UDI
199+
200+
Where the `unique-identifier` is a [UDI](https://www.gs1.org/industries/healthcare/udi).
201+
202+
Syntax:
203+
204+
```text
205+
urn:tei:udi:<domain-name>:<udi-identifier>
206+
````
207+
208+
Example:
209+
```text
210+
urn:tei:udi:cyclonedx.org:00123456789012
211+
```
212+
213+
Note that if an identifier, like EAN, is used for multiple different product releases
214+
then this EAN code will not be unique for a given product. While this case is supported
215+
by TEA, the vendor is recommended to create a separate TEI for each unique product sold,
216+
like UUID or hash. In any case, the vendor SHOULD minimize the number of distinct product
217+
releases returned per TEI. Preferable situation is to have a single product release
218+
per TEI.
163219

164220
### TEI resolution using DNS
165221

@@ -177,38 +233,112 @@ The name in the DNS name part points to a set of DNS records.
177233
A TEI with `domain-name` `tea.example.com` queries DNS for `tea.example.com`, considering `A`, `AAAA` and `CNAME` records.
178234
These point to the hosts available for the Transparency Exchange API.
179235

180-
The TEA client connects to the host using HTTPS and validates the certificate.
181-
The URI is composed of the name with the `/.well-known/tea` prefix added.
236+
The TEA client connects to the host using HTTPS and validates
237+
the certificate. The URL is composed of the host name with the `/.well-known/tea` path added.
182238

183-
This results in the base URI (without the product identifier)
184-
`https://tea.example.com/.well-known/tea/`
239+
This results in the base URL such as
240+
`https://products.example.com/.well-known/tea`
185241

242+
This response must contain json object that lists the available TEA server endpoints and supported versions.
243+
The json must conform to the [TEA Well-Known Schema](tea-well-known.schema.json).
186244

187-
## Connecting to the API
245+
Example:
246+
```json
247+
{
248+
"schemaVersion": 1,
249+
"endpoints": [
250+
{
251+
"url": "https://api.teaexample.com",
252+
"versions":
253+
[
254+
"0.1.0-beta.1",
255+
"0.2.0-beta.2",
256+
"1.0.0"
257+
],
258+
"priority": 1
259+
},
260+
{
261+
"url": "https://api2.teaexample.com/mytea",
262+
"versions":
263+
[
264+
"1.0.0"
265+
],
266+
"priority": 0.5
267+
}
268+
]
269+
}
270+
```
188271

189-
When connecting to the `.well-known/tea` URI with the unique identifier
190-
a HTTP redirect is **required**.
272+
## TODO: Port resolution
191273

192-
The server MUST redirect HTTP requests for that resource
193-
to the actual "context path" using one of the available mechanisms
194-
provided by HTTP (e.g., using a 301, 303, or 307 response). Clients
195-
MUST handle HTTP redirects on the `.well-known` URI. Servers MUST
196-
NOT locate the actual TEA service endpoint at the
197-
`.well-known` URI as per Section 1.1 of [RFC5785].
274+
N.B. This needs to be resolved before finalizing the spec.
198275

199-
### Overview: Finding the Index using DNS result
276+
Currently, the port number is not part of the TEI but it is needed to connect to the API.
277+
The current assumption is that the client connects on the default https port (443).
278+
At this time, it is recommended that experimental clients add an optional port parameter, which
279+
allows to override the default port.
200280

201-
Append the product part of the TEI to the URI found
281+
A port number cannot be added to the TEI URN spec as it breaks the location independence
282+
requirement of URN.
202283

203-
- TEI: `urn:tei:uuid:products.example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1`
204-
- DNS record: `products.example.com`
205-
- URL: `https://products.example.com/.well-known/tea/d4d9f54a-abcf-11ee-ac79-1a52914d44b1/`
206-
- HTTP 302 redirect to "https://teapot02.consumer.example.com/tea/v2/product/d4d9f54a-abcf-11ee-ac79-1a52914d44b1'
284+
Possible solutions to this issue:
285+
1. Make a convention that the port number for the ./well-known/tea is always 443. Exceptions
286+
possible via explicit client setting for non-production environments only.
287+
2. Use SRV or HTTPS DNS records to resolve the ./well-known/tea URL with the port number.
288+
289+
290+
## Connecting to the API
291+
292+
Clients must pick any one of the endpoints listed in the `.well-known/tea` json
293+
response. The client MUST pick an endpoint with the at least one version that is
294+
supported by the client is using. The client MUST prioritize endpoints with the
295+
highest matching version supported both by the client and the endpoint based on
296+
SemVer 2.0.0 specification comparison [rules](https://semver.org/#spec-item-11).
297+
If there are several endpoints like these and if the priority field is present,
298+
the client SHOULD pick the endpoint with the highest priority value (a float
299+
between 0 and 1).
300+
301+
The client must then construct the full URL to the API by appending the
302+
"/v" plus one of the versions listed in the `versions` array of the selected endpoint,
303+
plus "/discovery?tei=", plus the TEI that is url-encoded according to [RFC3986]
304+
and [RFC3986]).
305+
306+
Examples:
307+
1. For TEI `urn:tei:uuid:products.example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b`
308+
`https://api.teaexample.com/v0.2.0-beta.2/discovery?tei=urn%3Atei%3Auuid%3Aproducts.example.com%3Ad4d9f54a-abcf-11ee-ac79-1a52914d44b`
309+
2. For TEI `urn:tei:purl:products.example.com:pkg:deb/debian/[email protected]?arch=i386&distro=jessie`
310+
`https://api2.teaexample.com/mytea/v1.0.0/discovery?tei=urn%3Atei%3Apurl%3Aproducts.example.com%3Apkg%3Adeb%2Fdebian%2Fcurl%407.50.3-1%3Farch%3Di386%26distro%3Djessie`
311+
312+
The discovery endpoint is a part of the TEA OpenAPI specification.
313+
314+
If the TEI is known to the TEA server, the discovery endpoint must return at least
315+
the product release uuid, the root URL of the TEA server, the list of supported
316+
versions, plus the response may have other fields based on the current version of
317+
the TEA OpenAPI specification.
318+
319+
If the TEI is not known to the TEA server, the discovery endpoint must return a 404
320+
status code with a response describing the error.
321+
322+
If the DNS record for the discovery endpoint cannot be resolved by the client, or
323+
the discovery endpoint fails with 5xx error code, or the TLS certificate cannot be validated,
324+
the client MUST retry the discovery endpoint with the next endpoint in the list, if another
325+
endpoint is present. While doing so the client SHOULD preserve the priority order if provided
326+
(from highest to lowest priority). If no other endpoint is available, the client MUST retry
327+
the discovery endpoint with the first endpoint in the list. The client SHOULD implement an
328+
exponential backoff strategy for retries.
329+
330+
TODO: Handle Auth errors (401, 403) and corresponding messages.
331+
332+
## Notes Regarding .well-known
333+
Servers MUST NOT locate the actual TEA service endpoint at the
334+
`.well-known` URI as per Section 1.1 of [RFC5785].
335+
336+
### TLS Encryption
207337

208-
Always prefix with the https:// scheme. http (unencrypted) is not valid.
338+
The .well-known endpoint must only be available via HTTPS. Using unencrypted HTTP is not valid.
209339

210340
- TEI: `urn:tei:uuid:products.example.com:d4d9f54a-abcf-11ee-ac79-1a52914d44b1`
211-
- URL: `https://products.example.com/.well-known/tea/d4d9f54a-abcf-11ee-ac79-1a52914d44b1/`
341+
- URL: `https://products.example.com/.well-known/tea`
212342

213343
**NOTE:** The `/.well-known/tea` names space needs to be registred.
214344

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://cyclonedx.github.io/transparency-exchange-api/discovery/tea-well-known.schema.json",
4+
"title": "TEA .well-known discovery document",
5+
"description": "JSON Schema for the TEA .well-known/tea discovery payload that lists available TEA API endpoints and supported versions.",
6+
"type": "object",
7+
"additionalProperties": false,
8+
"required": ["schemaVersion", "endpoints"],
9+
"properties": {
10+
"schemaVersion": {
11+
"type": "integer",
12+
"const": 1,
13+
"description": "Schema version for the TEA .well-known discovery document. Currently always 1."
14+
},
15+
"endpoints": {
16+
"type": "array",
17+
"description": "List of available TEA service endpoints and their supported versions.",
18+
"minItems": 1,
19+
"items": { "$ref": "#/definitions/endpoint" }
20+
}
21+
},
22+
"definitions": {
23+
"endpoint": {
24+
"type": "object",
25+
"additionalProperties": false,
26+
"required": ["url", "versions"],
27+
"properties": {
28+
"url": {
29+
"type": "string",
30+
"format": "uri",
31+
"description": "Base URL of the TEA API endpoint (no trailing slash)."
32+
},
33+
"versions": {
34+
"type": "array",
35+
"description": "Supported TEA API versions for this endpoint. Use with the /v{version} prefix when constructing requests.",
36+
"minItems": 1,
37+
"items": {
38+
"type": "string",
39+
"pattern": "^\\d+\\.\\d+(?:\\.\\d+)?(?:-[0-9A-Za-z.-]+)?$",
40+
"examples": [
41+
"0.1.0-beta.1",
42+
"0.2.0-beta.2",
43+
"1.0.0"
44+
],
45+
"description": "TEA OpenAPI Spec Version identifier, conforms to SemVer 2.0 (https://semver.org/)."
46+
}
47+
},
48+
"priority": {
49+
"type": "number",
50+
"minimum": 0,
51+
"maximum": 1,
52+
"default": 1,
53+
"description": "Optional priority for this endpoint. Higher values indicate higher priority. Range: 0 to 1."
54+
}
55+
}
56+
}
57+
},
58+
"examples": [
59+
{
60+
"schemaVersion": 1,
61+
"endpoints": [
62+
{
63+
"url": "https://api.teaexample.com",
64+
"versions": ["0.1.0-beta.1", "0.2.0-beta.2", "1.0"],
65+
"priority": 1
66+
},
67+
{
68+
"url": "https://api2.teaexample.com/mytea",
69+
"versions": ["1.0.0"],
70+
"priority": 0.5
71+
}
72+
]
73+
}
74+
]
75+
}

0 commit comments

Comments
 (0)