hachure 0.3.0 → 0.4.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/assurance.md +38 -0
- package/package.json +1 -1
- package/schemas/evidence.schema.json +25 -0
- package/verification-endpoint.md +64 -10
package/assurance.md
CHANGED
|
@@ -170,10 +170,48 @@ the authenticated identity, and that certificate signs the record. The entire
|
|
|
170
170
|
flow completes in the same session as the authorizing act; signing a record
|
|
171
171
|
retroactively from a different session is not a conforming ceremony.
|
|
172
172
|
|
|
173
|
+
**Recommended mechanism for highest-assurance human ceremonies:** WebAuthn /
|
|
174
|
+
passkey with user-verification (UV=1). A device-local authenticator satisfies
|
|
175
|
+
three independent assurance legs simultaneously:
|
|
176
|
+
|
|
177
|
+
- **Presence** — the passkey gesture (biometric or PIN) proves the enrolled
|
|
178
|
+
device is physically present; biometric data never leaves the device.
|
|
179
|
+
- **Identity** — the hardware-backed assertion composes with the OIDC
|
|
180
|
+
certificate: the certificate binds the ephemeral key to the OIDC subject;
|
|
181
|
+
the passkey attests the device-local identity enrolled at registration time.
|
|
182
|
+
- **Engagement** (non-normative) — oversight metrics such as session duration
|
|
183
|
+
or interaction events can accompany the record as non-normative evidence;
|
|
184
|
+
they are not part of the conformance criteria.
|
|
185
|
+
|
|
186
|
+
Because the three legs are independent, losing one (e.g., no biometric sensor
|
|
187
|
+
on the device) does not forfeit the others. An OIDC-only ceremony without a
|
|
188
|
+
passkey assertion is still a conforming L1 ceremony; the passkey upgrade is
|
|
189
|
+
RECOMMENDED where the platform supports it.
|
|
190
|
+
|
|
173
191
|
Design intent: friction lands only where authority is exercised. Routine
|
|
174
192
|
read-only operations, status queries, and bundle consumption carry no signing
|
|
175
193
|
requirement. The ceremony surfaces once, at the moment of consequence.
|
|
176
194
|
|
|
195
|
+
## Collection channels and media evidence
|
|
196
|
+
|
|
197
|
+
Any collection channel defined in the reference implementation (see ADR 0004 in
|
|
198
|
+
the reference implementation) MAY attach media evidence — for example,
|
|
199
|
+
capture-provenance imagery conforming to C2PA — as ordinary evidence entries
|
|
200
|
+
with integrity anchors. Three rules govern such attachments:
|
|
201
|
+
|
|
202
|
+
1. **Channels do not replace admissible testimony kinds.** A photo or video of
|
|
203
|
+
a signing gesture is attached evidence, not a substitute for an `exchange` or
|
|
204
|
+
`authorized-action` block. The admissible testimony kinds in ADR 0004 remain
|
|
205
|
+
the authoritative record; media is corroborating context.
|
|
206
|
+
2. **Capture provenance determines evidence grade.** Media accompanied by a
|
|
207
|
+
valid C2PA manifest (or equivalent capture-provenance credential) is treated
|
|
208
|
+
as integrity-anchored evidence at the level its anchor supports. Media
|
|
209
|
+
without capture provenance is ordinary L0 evidence: present, but carrying no
|
|
210
|
+
additional assurance weight beyond the transport channel.
|
|
211
|
+
3. **Integrity anchors are required for non-L0 media claims.** If a consumer
|
|
212
|
+
policy requires L1 or higher evidence grade for media, the media item MUST
|
|
213
|
+
carry an `IntegrityAnchor` referencing the capture-provenance credential.
|
|
214
|
+
|
|
177
215
|
---
|
|
178
216
|
|
|
179
217
|
## Non-goals
|
package/package.json
CHANGED
|
@@ -24,9 +24,34 @@
|
|
|
24
24
|
"collectedBy": { "type": "string" },
|
|
25
25
|
"integrityRef": { "type": "string" },
|
|
26
26
|
"integrityAnchor": { "$ref": "#/$defs/integrityAnchor" },
|
|
27
|
+
"passing": {
|
|
28
|
+
"type": "boolean",
|
|
29
|
+
"description": "Whether the check that produced this evidence passed. Omitted when the evidence is not the output of a pass/fail check."
|
|
30
|
+
},
|
|
31
|
+
"blocking": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"description": "Whether a non-passing result should block (e.g. trigger disputed status under a policy conflict rule)."
|
|
34
|
+
},
|
|
35
|
+
"execution": {
|
|
36
|
+
"$ref": "#/$defs/execution",
|
|
37
|
+
"description": "How the evidence was produced: the command or tool invocation, exit code, and duration — making artifacts self-describing without requiring the producer's adapter config."
|
|
38
|
+
},
|
|
27
39
|
"metadata": { "type": "object" }
|
|
28
40
|
},
|
|
29
41
|
"$defs": {
|
|
42
|
+
"execution": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"required": ["runner", "label"],
|
|
45
|
+
"properties": {
|
|
46
|
+
"runner": { "enum": ["bash", "mcp"] },
|
|
47
|
+
"label": { "type": "string" },
|
|
48
|
+
"exitCode": { "type": "integer" },
|
|
49
|
+
"isError": { "type": "boolean" },
|
|
50
|
+
"durationMs": { "type": "number" },
|
|
51
|
+
"metadata": { "type": "object" }
|
|
52
|
+
},
|
|
53
|
+
"additionalProperties": false
|
|
54
|
+
},
|
|
30
55
|
"integrityAnchor": {
|
|
31
56
|
"type": "object",
|
|
32
57
|
"required": ["id", "kind", "algorithm", "value", "sourceRef"],
|
package/verification-endpoint.md
CHANGED
|
@@ -30,7 +30,7 @@ Producers supporting this profile expose a verification endpoint at a well-known
|
|
|
30
30
|
path on the same host that issued the bundle:
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
-
GET https://<producer-host>/.well-known/hachure/verify?ref=<
|
|
33
|
+
GET https://<producer-host>/.well-known/hachure/verify?ref=<ref>[&ref=...]
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Multiple refs may be passed as repeated `ref` query parameters. For large sets,
|
|
@@ -40,17 +40,39 @@ a POST variant is also allowed:
|
|
|
40
40
|
POST https://<producer-host>/.well-known/hachure/verify
|
|
41
41
|
Content-Type: application/json
|
|
42
42
|
|
|
43
|
-
{ "refs": ["<
|
|
43
|
+
{ "refs": ["<ref>", ...] }
|
|
44
44
|
```
|
|
45
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
46
|
Producers MAY require authentication before serving a response. The response
|
|
50
47
|
semantics defined in this profile are unchanged by the presence or absence of
|
|
51
48
|
authentication; the receiver simply may not be able to reach the endpoint
|
|
52
49
|
without valid credentials.
|
|
53
50
|
|
|
51
|
+
### Ref resolution semantics
|
|
52
|
+
|
|
53
|
+
A `ref` value in the request MAY be any of the following:
|
|
54
|
+
|
|
55
|
+
- **(a) A claim `id`** — the stable identifier on a claim object (`claim.id`).
|
|
56
|
+
- **(b) A claim's current integrity ref** — the `currentIntegrityRef` string field
|
|
57
|
+
on a claim (`claim.currentIntegrityRef`, per `schemas/claim.schema.json`).
|
|
58
|
+
Note: the analogous full anchor object is `claim.currentIntegrityAnchor`; when
|
|
59
|
+
resolving by integrity value, match against `currentIntegrityRef` or
|
|
60
|
+
`currentIntegrityAnchor.value`.
|
|
61
|
+
- **(c) A bundle-level integrity anchor value** — the `.value` field of an
|
|
62
|
+
`integrityAnchor` object carried on an `authorityTrace` or `evidence` record
|
|
63
|
+
within a bundle (`schemas/trust-bundle.schema.json` `$defs/integrityAnchor`
|
|
64
|
+
→ `value`).
|
|
65
|
+
|
|
66
|
+
Producers MUST support lookup by (a) and (b). Producers MAY support lookup by (c).
|
|
67
|
+
Receivers SHOULD prefer (a) for stability; (b) and (c) are useful when only an
|
|
68
|
+
integrity value is available from a prior bundle snapshot.
|
|
69
|
+
|
|
70
|
+
**Multi-match:** a single ref value MAY match more than one claim (for example,
|
|
71
|
+
two claims that share the same `currentIntegrityRef`). When a ref matches multiple
|
|
72
|
+
claims, the response includes ALL matching claims. A ref is reported as unknown
|
|
73
|
+
(in `unknownRefs`) only when it matches nothing — zero claims, evidence records,
|
|
74
|
+
or authority traces.
|
|
75
|
+
|
|
54
76
|
---
|
|
55
77
|
|
|
56
78
|
## Response shape
|
|
@@ -60,8 +82,9 @@ scoped to the records matching the requested refs, plus a `metadata` extension
|
|
|
60
82
|
block. The bundle carries:
|
|
61
83
|
|
|
62
84
|
- **`source`** — the producer identifier, matching `source` in the original bundle.
|
|
63
|
-
- **`claims`** — all claims
|
|
64
|
-
|
|
85
|
+
- **`claims`** — all claims that matched the requested refs (by id, currentIntegrityRef,
|
|
86
|
+
or anchor value as described above). When a ref matched multiple claims, all are
|
|
87
|
+
included. Each claim is returned in its current form as the producer knows it.
|
|
65
88
|
- **`evidence`** and **`events`** — the delta since issuance where the producer
|
|
66
89
|
can supply it: new evidence items, new verification events, revocation events,
|
|
67
90
|
dispute events. Producers that do not track a delta MAY return the full current
|
|
@@ -69,20 +92,35 @@ block. The bundle carries:
|
|
|
69
92
|
means it was never present in the original bundle.
|
|
70
93
|
- **`authorityTrace`** — current authority traces relevant to the matched claims,
|
|
71
94
|
including any that have been revoked since the original bundle was issued.
|
|
72
|
-
- **`metadata`** — a free-form object on the bundle. This profile defines
|
|
95
|
+
- **`metadata`** — a free-form object on the bundle. This profile defines five
|
|
73
96
|
reserved keys within `metadata`:
|
|
74
97
|
|
|
75
98
|
| Key | Type | Required | Meaning |
|
|
76
99
|
|---|---|---|---|
|
|
77
100
|
| `respondedAt` | ISO 8601 string | yes | The timestamp at which the producer assembled this response. |
|
|
78
|
-
| `statusFunctionVersion` | string | yes | The status function version
|
|
101
|
+
| `statusFunctionVersion` | string | yes | The status function version the producer's current evaluation pipeline uses — i.e. the value the implementation exports (e.g. `statusFunctionVersion` from the reference implementation), independent of any version values stored inside served bundles. |
|
|
79
102
|
| `requestedRefs` | string[] | yes | The full list of refs from the request, in order. |
|
|
80
|
-
| `unknownRefs` | string[] | yes | Refs from the request that
|
|
103
|
+
| `unknownRefs` | string[] | yes | Refs from the request that matched nothing. Must be present even if empty. |
|
|
104
|
+
| `evaluatedAt` | `"response"` \| `"generation"` | no | When omitted or `"response"`, the producer evaluated claims dynamically at response time. `"generation"` indicates the producer cannot evaluate dynamically (e.g. static file serving) and the `statusFunctionVersion` reflects the version recorded when the bundle was originally generated. |
|
|
81
105
|
|
|
82
106
|
Unknown refs are reported in `unknownRefs` honestly. A producer MUST NOT silently
|
|
83
107
|
omit a ref it does not recognise; it MUST include it in `unknownRefs` so the
|
|
84
108
|
receiver can distinguish "no changes" from "not found."
|
|
85
109
|
|
|
110
|
+
**`statusFunctionVersion` source:** producers report the version their current
|
|
111
|
+
evaluation pipeline uses — the value their implementation exports at response time.
|
|
112
|
+
This is independent of any `statusFunctionVersion` fields stored inside the claims
|
|
113
|
+
or events within served bundles. Producers that serve static bundles without
|
|
114
|
+
dynamic evaluation MUST report the version that was active at generation time and
|
|
115
|
+
MUST set `evaluatedAt: "generation"` in metadata.
|
|
116
|
+
|
|
117
|
+
**`integrityAnchor` shape:** integrity anchor objects in responses follow the
|
|
118
|
+
`integrityAnchor` definition in `schemas/claim.schema.json` (`$defs/integrityAnchor`)
|
|
119
|
+
and `schemas/trust-bundle.schema.json` (`$defs/integrityAnchor`). Required fields
|
|
120
|
+
are `id`, `kind`, `algorithm`, `value`, and `sourceRef`. On claims the anchor is
|
|
121
|
+
carried as `currentIntegrityAnchor`; on authority-trace and evidence records it
|
|
122
|
+
is carried as `integrityAnchor`.
|
|
123
|
+
|
|
86
124
|
---
|
|
87
125
|
|
|
88
126
|
## Assurance levels
|
|
@@ -150,3 +188,19 @@ unsigned responses are valid.
|
|
|
150
188
|
specified here.
|
|
151
189
|
- **Key management.** Public-key distribution, rotation, and revocation are out
|
|
152
190
|
of scope. See the ADR 0004 backlog note above.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Changelog
|
|
195
|
+
|
|
196
|
+
**Amended after first independent implementation — hachure.org site function.**
|
|
197
|
+
Five ambiguities resolved: (1) corrected claim integrity field names to schema
|
|
198
|
+
truth (`currentIntegrityRef`, `currentIntegrityAnchor`) and noted authority-trace
|
|
199
|
+
and evidence fields (`integrityRef`, `integrityAnchor`); (2) defined ref resolution
|
|
200
|
+
semantics — producers MUST support id and currentIntegrityRef lookups, MAY support
|
|
201
|
+
anchor-value lookups; (3) clarified multi-match: a ref matching multiple claims
|
|
202
|
+
returns all of them, unknown only when nothing matches; (4) clarified
|
|
203
|
+
`statusFunctionVersion` source as the producer's current pipeline export, added
|
|
204
|
+
optional `evaluatedAt` metadata key (`"response"` | `"generation"`) for static
|
|
205
|
+
producers; (5) added normative cross-reference to `integrityAnchor` schema
|
|
206
|
+
definition in `schemas/claim.schema.json` and `schemas/trust-bundle.schema.json`.
|