hachure 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/assurance.md +192 -0
- package/package.json +9 -3
- package/verification-endpoint.md +152 -0
package/README.md
CHANGED
|
@@ -226,6 +226,20 @@ validates TrustBundle input against these schemas via `validateTrustBundle()`.
|
|
|
226
226
|
|
|
227
227
|
---
|
|
228
228
|
|
|
229
|
+
## Profiles
|
|
230
|
+
|
|
231
|
+
The core specification covers record shapes and status semantics. Profiles are
|
|
232
|
+
optional, independently adoptable conventions for interop and transport. Adopting
|
|
233
|
+
a profile requires no changes to core record shapes or the status function.
|
|
234
|
+
|
|
235
|
+
| Profile | File | What it covers |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| in-toto interop | [interop-in-toto.md](interop-in-toto.md) | Wrapping a TrustBundle as a signed in-toto Statement v1 / DSSE envelope. |
|
|
238
|
+
| Verification endpoint | [verification-endpoint.md](verification-endpoint.md) | Producer-served HTTP endpoint for receivers to fetch post-export event deltas. |
|
|
239
|
+
| Assurance | [assurance.md](assurance.md) | Signing as a dial: L0/L1/L2 assurance levels, identity presentation, consumer policy, and human signing ceremony. |
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
229
243
|
## Out of scope: future extension profiles
|
|
230
244
|
|
|
231
245
|
The following producer domains are explicitly out of scope for this core specification.
|
package/assurance.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Assurance — Extension Profile
|
|
2
|
+
|
|
3
|
+
**Profile type:** OPTIONAL extension
|
|
4
|
+
**Status:** draft
|
|
5
|
+
**Namespace:** `hachure.org/v1`
|
|
6
|
+
**Depends on:** core record shapes, [interop-in-toto.md](interop-in-toto.md), [verification-endpoint.md](verification-endpoint.md)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Principle: signing is a dial, not a gate
|
|
11
|
+
|
|
12
|
+
Unsigned records are valid core records. Forever. This profile defines how
|
|
13
|
+
consumers express and verify *higher* assurance, and how policies weigh the
|
|
14
|
+
levels against one another. It is never a prerequisite for producing or
|
|
15
|
+
consuming a TrustBundle.
|
|
16
|
+
|
|
17
|
+
The assurance model exists because some environments want non-repudiation, audit
|
|
18
|
+
trails that survive producer outages, or cryptographic evidence that a specific
|
|
19
|
+
human exercised a specific authority. Signing is the mechanism that provides
|
|
20
|
+
those properties — but it is layered on top of an already-valid record, not a
|
|
21
|
+
precondition for record validity. A bundle with no signatures is not a
|
|
22
|
+
degraded bundle; it is an L0 bundle.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Assurance levels
|
|
27
|
+
|
|
28
|
+
Three levels are defined. Higher levels are a strict superset of lower levels:
|
|
29
|
+
an L2 record satisfies any policy that accepts L1 or L0.
|
|
30
|
+
|
|
31
|
+
### L0 — producer-asserted (default)
|
|
32
|
+
|
|
33
|
+
The record is unsigned. Assurance derives entirely from the trustworthiness of
|
|
34
|
+
the transport channel and the producer identity declared in the bundle's
|
|
35
|
+
`source` field. All TrustBundles that do not carry a DSSE envelope are L0.
|
|
36
|
+
This is the default; no annotation or flag is required.
|
|
37
|
+
|
|
38
|
+
### L1 — identity-signed (keyless / ephemeral)
|
|
39
|
+
|
|
40
|
+
The record is wrapped in a DSSE envelope (per
|
|
41
|
+
[interop-in-toto.md](interop-in-toto.md)). The signing key is short-lived and
|
|
42
|
+
bound to an identity asserted by an OIDC provider at signing time — a CI
|
|
43
|
+
workflow identity (`sub: repo:org/repo:ref:refs/heads/main`) or a human account
|
|
44
|
+
(`sub: user@example.com`). The certificate binds the ephemeral public key to
|
|
45
|
+
that OIDC identity for the lifetime of the signing event.
|
|
46
|
+
|
|
47
|
+
An L1 signature MAY be submitted to a public transparency log (Rekor or
|
|
48
|
+
equivalent). When it is, the resulting log entry UUID SHOULD be stored in the
|
|
49
|
+
bundle's `proof` block as an `IntegrityAnchor` of kind `transparency_log`.
|
|
50
|
+
Transparency-log inclusion is encouraged but not required for L1 conformance.
|
|
51
|
+
|
|
52
|
+
The OIDC issuer and subject carried in the signing certificate are the
|
|
53
|
+
authoritative identity for the signing event. Implementations that verify L1
|
|
54
|
+
signatures MUST surface a human-readable identity derived from those fields (see
|
|
55
|
+
[Identity presentation](#identity-presentation) below).
|
|
56
|
+
|
|
57
|
+
### L2 — held-key (org-controlled KMS/HSM)
|
|
58
|
+
|
|
59
|
+
The record is wrapped in a DSSE envelope and signed with a long-lived key held
|
|
60
|
+
in an org-controlled key-management system (a KMS or HSM). The key is not
|
|
61
|
+
ephemeral and is not tied to a per-operation OIDC token. Key rotation and
|
|
62
|
+
revocation are producer policy; this profile imposes no rotation schedule or
|
|
63
|
+
revocation mechanism.
|
|
64
|
+
|
|
65
|
+
L2 is appropriate for environments that cannot use public OIDC issuers or
|
|
66
|
+
public transparency logs — air-gapped deployments, highly regulated environments
|
|
67
|
+
with internal PKI requirements, or organisations that maintain their own CA.
|
|
68
|
+
|
|
69
|
+
Because L2 keys are long-lived, verifiers must obtain the producer's public key
|
|
70
|
+
through an out-of-band channel (internal PKI, a published key-distribution
|
|
71
|
+
endpoint, a previously-trusted bundle). This profile does not specify that
|
|
72
|
+
channel.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## What gets signed
|
|
77
|
+
|
|
78
|
+
Producers that adopt this profile MAY sign the following record types. Signing
|
|
79
|
+
any of them does not change the record's schema; the DSSE envelope wraps the
|
|
80
|
+
serialised record and is carried alongside it, not embedded in it.
|
|
81
|
+
|
|
82
|
+
### TrustBundles
|
|
83
|
+
|
|
84
|
+
A full TrustBundle, including release bundles, is the primary signing target.
|
|
85
|
+
Signing a bundle asserts that the named producer attests to the entire contents
|
|
86
|
+
at the moment the envelope was created. The in-toto Statement `subject` array
|
|
87
|
+
SHOULD identify the bundle's `integrityAnchor.value` so downstream verifiers can
|
|
88
|
+
correlate the envelope with a specific bundle revision.
|
|
89
|
+
|
|
90
|
+
### Attestations
|
|
91
|
+
|
|
92
|
+
A human's `ReviewOutcome` record carrying an `authorizing` block (ADR 0004) is
|
|
93
|
+
an identity-signed attestation. When the human's OIDC identity signs that
|
|
94
|
+
record at the moment the authority is exercised (see
|
|
95
|
+
[Human signing ceremony](#human-signing-ceremony)), the result is non-repudiable
|
|
96
|
+
evidence that a specific identity made a specific decision. This signed
|
|
97
|
+
attestation is the appropriate content for the `identityEvidence` field on a
|
|
98
|
+
Claim: it collapses "someone in this org approved this" into "this OIDC-verified
|
|
99
|
+
identity approved this, cryptographically."
|
|
100
|
+
|
|
101
|
+
### Verification-endpoint responses
|
|
102
|
+
|
|
103
|
+
A producer serving a verification-endpoint response (see
|
|
104
|
+
[verification-endpoint.md](verification-endpoint.md)) MAY wrap the response
|
|
105
|
+
bundle in a DSSE envelope before returning it. A signed response upgrades the
|
|
106
|
+
assurance level of that endpoint from L0 to L1 or L2 according to the key type
|
|
107
|
+
used. Receivers SHOULD apply the same identity-presentation rules to a signed
|
|
108
|
+
response as to any other signed record.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Identity presentation
|
|
113
|
+
|
|
114
|
+
Verifiers MUST surface a human-readable identity for every signed record they
|
|
115
|
+
display or log. Raw key fingerprints are not an acceptable primary display.
|
|
116
|
+
|
|
117
|
+
Derive the display identity from the DSSE envelope's signing certificate:
|
|
118
|
+
|
|
119
|
+
- For L1 (OIDC-backed): present the OIDC issuer and subject in a
|
|
120
|
+
human-readable form. Examples:
|
|
121
|
+
- CI workflow: `"signed by github.com/org/repo workflow .github/workflows/release.yml"`
|
|
122
|
+
- Human account: `"signed by alice@example.com (GitHub)"`
|
|
123
|
+
- For L2 (held key): present the key's subject DN or the KMS key alias as
|
|
124
|
+
configured by the producer. Example: `"signed by CN=kontour-release-key, O=Kontour AI"`
|
|
125
|
+
|
|
126
|
+
Displaying a fingerprint alongside the human-readable identity is permitted and
|
|
127
|
+
encouraged for debugging. It is not a substitute for the identity string as the
|
|
128
|
+
primary display element.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Consumer policy
|
|
133
|
+
|
|
134
|
+
Assurance requirements are policy, not wire format. A consumer expresses its
|
|
135
|
+
requirements through a `VerificationPolicy` that declares a minimum assurance
|
|
136
|
+
level among its `acceptanceCriteria`. Mismatches between a record's actual
|
|
137
|
+
level and the consumer's required level are **transparency gaps** — structured
|
|
138
|
+
annotations that feed the status function's inputs and surface as `proposed` or
|
|
139
|
+
`assumed` status rather than silent hard failures.
|
|
140
|
+
|
|
141
|
+
This mirrors the admissibility doctrine in ADR 0004 §4: heuristics emit issues
|
|
142
|
+
for human review; they do not silently decide. A bundle whose assurance level
|
|
143
|
+
falls below a consumer's requirement is recorded and flagged; a human or an
|
|
144
|
+
automated policy layer decides whether to accept, escalate, or re-request.
|
|
145
|
+
|
|
146
|
+
Concretely:
|
|
147
|
+
|
|
148
|
+
- An L0 bundle that satisfies all policy evidence requirements reaches
|
|
149
|
+
`verified` normally. If the consumer policy also requires L1, the consumer
|
|
150
|
+
annotates the gap; the status function sees the annotation as a transparency
|
|
151
|
+
gap and surfaces the claim at `proposed` pending a signed replacement.
|
|
152
|
+
- An L1 or L2 bundle that satisfies all policy evidence requirements and meets
|
|
153
|
+
the assurance requirement reaches `verified` without annotation.
|
|
154
|
+
- A signed record with an unverifiable or expired certificate does not silently
|
|
155
|
+
downgrade to L0. The verification failure is itself a transparency gap,
|
|
156
|
+
flagged for the attention queue.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Human signing ceremony
|
|
161
|
+
|
|
162
|
+
When a human exercises authority — authoring a policy-change attestation,
|
|
163
|
+
signing off a release bundle, or countersigning a ReviewOutcome — the signing
|
|
164
|
+
gesture MUST be interactive and co-located in time with the authorizing act.
|
|
165
|
+
|
|
166
|
+
The ceremony is an interactive OIDC browser flow: the same gesture as
|
|
167
|
+
sign-in-with-Google or a Stripe payment confirmation. The human authenticates
|
|
168
|
+
to the OIDC provider, the provider issues a short-lived certificate bound to
|
|
169
|
+
the authenticated identity, and that certificate signs the record. The entire
|
|
170
|
+
flow completes in the same session as the authorizing act; signing a record
|
|
171
|
+
retroactively from a different session is not a conforming ceremony.
|
|
172
|
+
|
|
173
|
+
Design intent: friction lands only where authority is exercised. Routine
|
|
174
|
+
read-only operations, status queries, and bundle consumption carry no signing
|
|
175
|
+
requirement. The ceremony surfaces once, at the moment of consequence.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Non-goals
|
|
180
|
+
|
|
181
|
+
- **Mandating a CA or transparency log.** This profile does not require a
|
|
182
|
+
specific certificate authority, a specific OIDC issuer, or submission to any
|
|
183
|
+
particular log. L1 signing with a private OIDC issuer and no public log is
|
|
184
|
+
valid L1.
|
|
185
|
+
- **Key custody prescriptions.** How a producer acquires, stores, rotates, or
|
|
186
|
+
revokes L2 keys is producer policy. This profile does not specify HSM vendor,
|
|
187
|
+
key-rotation schedule, or revocation-distribution mechanism.
|
|
188
|
+
- **Core-format changes.** No core record schema is altered by this profile.
|
|
189
|
+
Adopting the assurance profile requires no schema migration and no changes to
|
|
190
|
+
the status derivation function.
|
|
191
|
+
- **Signing every record.** Signing is always optional. Producers that sign
|
|
192
|
+
nothing are fully conformant with the core specification.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hachure",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Hachure
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Hachure \u2014 canonical distribution of the open trust format: normative JSON schemas, conformance test vectors, and spec constants.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|
|
7
7
|
"exports": {
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
"index.mjs",
|
|
16
16
|
"README.md",
|
|
17
17
|
"status-function.md",
|
|
18
|
-
"interop-in-toto.md"
|
|
18
|
+
"interop-in-toto.md",
|
|
19
|
+
"verification-endpoint.md",
|
|
20
|
+
"assurance.md"
|
|
19
21
|
],
|
|
20
22
|
"scripts": {
|
|
21
23
|
"test": "node --test test/index.test.mjs"
|
|
@@ -30,5 +32,9 @@
|
|
|
30
32
|
"license": "MIT",
|
|
31
33
|
"publishConfig": {
|
|
32
34
|
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/hachure-org/spec.git"
|
|
33
39
|
}
|
|
34
40
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Verification Endpoint — Extension Profile
|
|
2
|
+
|
|
3
|
+
**Profile type:** OPTIONAL extension
|
|
4
|
+
**Status:** draft
|
|
5
|
+
**Namespace:** `hachure.org/v1`
|
|
6
|
+
**Depends on:** core record shapes, [status-function.md](status-function.md), [interop-in-toto.md](interop-in-toto.md)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Problem
|
|
11
|
+
|
|
12
|
+
A TrustBundle is a point-in-time snapshot. Once exported, it carries no channel
|
|
13
|
+
back to the producer. A receiver holding a bundle from last week has no way to
|
|
14
|
+
learn that an authority trace was revoked yesterday, that a blocking evidence item
|
|
15
|
+
was added the day after export, or that a claim has since been superseded. The
|
|
16
|
+
receiver can re-run the status function as many times as it likes, but can only
|
|
17
|
+
produce the same answer from the same stale inputs.
|
|
18
|
+
|
|
19
|
+
This profile defines a lightweight channel for receivers to ask a producer: *what
|
|
20
|
+
has changed since this bundle was issued?* The response delivers fresh inputs for
|
|
21
|
+
the receiver's own status recomputation. It is testimony with a timestamp — a
|
|
22
|
+
record of what the producer asserted at the moment of response. It is never a
|
|
23
|
+
verdict the receiver is expected to obey.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Discovery
|
|
28
|
+
|
|
29
|
+
Producers supporting this profile expose a verification endpoint at a well-known
|
|
30
|
+
path on the same host that issued the bundle:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
GET https://<producer-host>/.well-known/hachure/verify?ref=<integrityRef>[&ref=...]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Multiple refs may be passed as repeated `ref` query parameters. For large sets,
|
|
37
|
+
a POST variant is also allowed:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
POST https://<producer-host>/.well-known/hachure/verify
|
|
41
|
+
Content-Type: application/json
|
|
42
|
+
|
|
43
|
+
{ "refs": ["<integrityRef>", ...] }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`integrityRef` is the integrity anchor value carried on a claim or bundle
|
|
47
|
+
(`claim.integrityRef` or a bundle-level `integrityAnchor.value`).
|
|
48
|
+
|
|
49
|
+
Producers MAY require authentication before serving a response. The response
|
|
50
|
+
semantics defined in this profile are unchanged by the presence or absence of
|
|
51
|
+
authentication; the receiver simply may not be able to reach the endpoint
|
|
52
|
+
without valid credentials.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Response shape
|
|
57
|
+
|
|
58
|
+
The response body is a TrustBundle (see `schemas/trust-bundle.schema.json`)
|
|
59
|
+
scoped to the records matching the requested refs, plus a `metadata` extension
|
|
60
|
+
block. The bundle carries:
|
|
61
|
+
|
|
62
|
+
- **`source`** — the producer identifier, matching `source` in the original bundle.
|
|
63
|
+
- **`claims`** — all claims whose `integrityRef` was among the requested refs.
|
|
64
|
+
Each claim is returned in its current form as the producer knows it.
|
|
65
|
+
- **`evidence`** and **`events`** — the delta since issuance where the producer
|
|
66
|
+
can supply it: new evidence items, new verification events, revocation events,
|
|
67
|
+
dispute events. Producers that do not track a delta MAY return the full current
|
|
68
|
+
set for the matched claims; receivers MUST NOT assume the absence of an item
|
|
69
|
+
means it was never present in the original bundle.
|
|
70
|
+
- **`authorityTrace`** — current authority traces relevant to the matched claims,
|
|
71
|
+
including any that have been revoked since the original bundle was issued.
|
|
72
|
+
- **`metadata`** — a free-form object on the bundle. This profile defines four
|
|
73
|
+
reserved keys within `metadata`:
|
|
74
|
+
|
|
75
|
+
| Key | Type | Required | Meaning |
|
|
76
|
+
|---|---|---|---|
|
|
77
|
+
| `respondedAt` | ISO 8601 string | yes | The timestamp at which the producer assembled this response. |
|
|
78
|
+
| `statusFunctionVersion` | string | yes | The status function version active at the producer at response time. |
|
|
79
|
+
| `requestedRefs` | string[] | yes | The full list of refs from the request, in order. |
|
|
80
|
+
| `unknownRefs` | string[] | yes | Refs from the request that the producer does not recognise. Must be present even if empty. |
|
|
81
|
+
|
|
82
|
+
Unknown refs are reported in `unknownRefs` honestly. A producer MUST NOT silently
|
|
83
|
+
omit a ref it does not recognise; it MUST include it in `unknownRefs` so the
|
|
84
|
+
receiver can distinguish "no changes" from "not found."
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Assurance levels
|
|
89
|
+
|
|
90
|
+
A response may be signed or unsigned. The two carry different weight.
|
|
91
|
+
|
|
92
|
+
**Signed response.** A producer that wraps the response bundle in a DSSE envelope
|
|
93
|
+
(per [interop-in-toto.md](interop-in-toto.md)) or attaches a `proof` block provides
|
|
94
|
+
independently verifiable testimony. The receiver can verify the signature using the
|
|
95
|
+
producer's public key before trusting any of the returned data. A signed response is
|
|
96
|
+
as trustworthy as the key and the in-toto statement it protects.
|
|
97
|
+
|
|
98
|
+
**Unsigned response.** A response delivered without a signature is producer-asserted
|
|
99
|
+
only. Receivers SHOULD treat an unsigned response exactly as they would treat an
|
|
100
|
+
unsigned TrustBundle received over a trusted channel: the transport provides some
|
|
101
|
+
assurance, but the content itself is not independently verifiable. Do not give an
|
|
102
|
+
unsigned response higher trust than the connection that delivered it.
|
|
103
|
+
|
|
104
|
+
Key distribution and rotation are out of scope for this profile. The same backlog
|
|
105
|
+
item that defers cryptographic signing for testimony records (ADR 0004, §Backlog)
|
|
106
|
+
applies here: until key-management infrastructure exists, signing is OPTIONAL and
|
|
107
|
+
unsigned responses are valid.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Receiver rules
|
|
112
|
+
|
|
113
|
+
1. **Re-run the status function.** Merge the response bundle's events and evidence
|
|
114
|
+
with the records in the held bundle, then call the status function over the
|
|
115
|
+
combined input at your own `now`. Do not treat any status value in the response
|
|
116
|
+
as a pre-computed verdict.
|
|
117
|
+
|
|
118
|
+
2. **Fix `now` before evaluating.** The status function is `f(claim, evidence,
|
|
119
|
+
events, policy, authorityTrace, now)`. The response supplies updated inputs; the
|
|
120
|
+
receiver controls `now`. Two receivers evaluating the same response at different
|
|
121
|
+
instants may derive different statuses — that is expected and correct.
|
|
122
|
+
|
|
123
|
+
3. **Cache by `respondedAt`; honour `max-age`.** A receiver MAY cache a response
|
|
124
|
+
keyed on the set of requested refs and the `respondedAt` timestamp. Producers MAY
|
|
125
|
+
include a standard HTTP `Cache-Control: max-age=<seconds>` header as a hint for
|
|
126
|
+
how long the response is expected to remain fresh. The hint is advisory; the
|
|
127
|
+
receiver decides its own staleness policy.
|
|
128
|
+
|
|
129
|
+
4. **Retain the response as a record.** A verification response is itself a record
|
|
130
|
+
worth keeping. It is testimony: evidence of what the producer asserted at
|
|
131
|
+
`respondedAt`. A receiver that retains responses can reconstruct the history of
|
|
132
|
+
its knowledge — when it learned of a revocation, when a dispute event appeared —
|
|
133
|
+
which is useful for audit and for re-evaluating past InquiryRecords.
|
|
134
|
+
|
|
135
|
+
5. **Treat signed and unsigned responses differently.** Apply the assurance-level
|
|
136
|
+
rules above before deciding how to weight the response in a combined evaluation.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Non-goals
|
|
141
|
+
|
|
142
|
+
- **Transport beyond HTTPS.** This profile specifies only the HTTP/HTTPS request
|
|
143
|
+
and response shape. Other transport mechanisms (gRPC, message queues, file
|
|
144
|
+
exchange) are not covered.
|
|
145
|
+
- **Push and webhooks.** This profile is pull-only. Producers notify receivers
|
|
146
|
+
only when asked. Push notification channels are a separate concern.
|
|
147
|
+
- **Transparency-log inclusion.** Including verification responses in a public
|
|
148
|
+
transparency log (Rekor or equivalent) is complementary and encouraged for
|
|
149
|
+
high-assurance scenarios, but it is not required by this profile and is not
|
|
150
|
+
specified here.
|
|
151
|
+
- **Key management.** Public-key distribution, rotation, and revocation are out
|
|
152
|
+
of scope. See the ADR 0004 backlog note above.
|