hachure 0.1.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 +267 -0
- package/conformance/README.md +31 -0
- package/conformance/sf-authority-resolved.json +106 -0
- package/conformance/sf-disputed-blocking.json +78 -0
- package/conformance/sf-reference-bundle-snapshot.json +332 -0
- package/conformance/sf-stale-duration.json +76 -0
- package/conformance/sf-verified-commit.json +68 -0
- package/index.mjs +61 -0
- package/interop-in-toto.md +133 -0
- package/package.json +34 -0
- package/schemas/claim.schema.json +82 -0
- package/schemas/derivation-rule.schema.json +57 -0
- package/schemas/evidence.schema.json +49 -0
- package/schemas/inquiry-record.schema.json +76 -0
- package/schemas/trust-bundle.schema.json +180 -0
- package/schemas/verification-event.schema.json +28 -0
- package/schemas/verification-policy.schema.json +65 -0
- package/status-function.md +225 -0
package/README.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Hachure — an open trust format
|
|
2
|
+
|
|
3
|
+
**Namespace:** `hachure.org/v1`
|
|
4
|
+
**Reference implementation:** `@kontourai/surface`
|
|
5
|
+
**Status:** pre-1.0, hard versioning, no compatibility promises yet
|
|
6
|
+
**Originally developed by:** [Kontour AI](https://kontour.ai)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm i -D hachure
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The package ships the normative JSON schemas, conformance test vectors, and the
|
|
17
|
+
`STATUS_FUNCTION_VERSION` constant that ties implementations to a specific
|
|
18
|
+
algorithm revision.
|
|
19
|
+
|
|
20
|
+
**Claiming conformance:** run the test vectors from `testVectors` against your
|
|
21
|
+
implementation. For each vector, call your status-derivation function with
|
|
22
|
+
`vector.input` and `vector.now`, then assert that the derived status for every
|
|
23
|
+
claim ID matches `vector.expect.statusByClaimId`. Passing all vectors for a given
|
|
24
|
+
`STATUS_FUNCTION_VERSION` is the bar for a conforming implementation.
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { testVectors, STATUS_FUNCTION_VERSION } from 'hachure';
|
|
28
|
+
|
|
29
|
+
for (const { name, vector } of testVectors) {
|
|
30
|
+
const results = deriveStatuses(vector.input, new Date(vector.now));
|
|
31
|
+
for (const [claimId, expected] of Object.entries(vector.expect.statusByClaimId)) {
|
|
32
|
+
assert.equal(results[claimId], expected, `${name} / ${claimId}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## What this is
|
|
41
|
+
|
|
42
|
+
Hachure is an open format for portable trust state. It defines how claims about
|
|
43
|
+
real-world subjects — and the evidence, policies, verification events, authority
|
|
44
|
+
records, and derivation rules behind them — are represented so they can cross
|
|
45
|
+
product and vendor boundaries without the receiver needing access to the
|
|
46
|
+
producer's internals.
|
|
47
|
+
|
|
48
|
+
Hachures are the short strokes on hand-drawn maps that show the shape and
|
|
49
|
+
steepness of terrain. This format does the same for trust: it shows the contours
|
|
50
|
+
of what is supported, what is stale, what is disputed, and what is simply
|
|
51
|
+
asserted.
|
|
52
|
+
|
|
53
|
+
The format is deliberately not named after any company or product.
|
|
54
|
+
`@kontourai/surface` is its reference implementation. Producers outside the
|
|
55
|
+
Kontour suite can emit and consume these records without adopting a vendor name
|
|
56
|
+
into their wire format.
|
|
57
|
+
|
|
58
|
+
**Governance intent:** Hachure is currently developed by Kontour AI, which holds
|
|
59
|
+
the name to protect it. We intend to move the specification to neutral
|
|
60
|
+
governance as adoption warrants.
|
|
61
|
+
|
|
62
|
+
The Kontour products build on top: Survey emits Trust Bundles, Veritas authors claims
|
|
63
|
+
through it, Flow consumes Surface-shaped evidence at gates, and Console operates across
|
|
64
|
+
all of them. Each product stands alone; the format requires none of them.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Namespace and versioning
|
|
69
|
+
|
|
70
|
+
All core trust-format records use `apiVersion: hachure.org/v1` in the Kontour
|
|
71
|
+
Resource Shape envelope. Product-specific records use product-scoped namespaces
|
|
72
|
+
(`surface.kontour.ai/v1alpha1`, `survey.kontour.ai/v1alpha1`, etc.).
|
|
73
|
+
|
|
74
|
+
Pre-1.0: the format uses hard breaking changes rather than compatibility aliases.
|
|
75
|
+
No forward or backward compatibility guarantees are made across versions. Version
|
|
76
|
+
bumps are reflected in `schemaVersion` (an integer field in TrustBundle, currently
|
|
77
|
+
`3`) and in `STATUS_FUNCTION_VERSION` (a string exported by the reference
|
|
78
|
+
implementation, currently `"1"`).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Scope: core record shapes
|
|
83
|
+
|
|
84
|
+
This specification covers the following record types. Each is a first-class concept
|
|
85
|
+
in the format; none requires a specific producer or product to instantiate.
|
|
86
|
+
|
|
87
|
+
### TrustBundle
|
|
88
|
+
|
|
89
|
+
The central wire record. A portable, point-in-time package of trust state from a
|
|
90
|
+
single producer: claims, evidence, policies, verification events, and optional identity
|
|
91
|
+
links, claim groups, and authority traces.
|
|
92
|
+
|
|
93
|
+
Plain-language definition (ADR 0002):
|
|
94
|
+
|
|
95
|
+
> A Trust Bundle is a portable, point-in-time package of trust state from a single
|
|
96
|
+
> producer — claims, the evidence and verification events behind them, and the policies
|
|
97
|
+
> the producer played by — packed so it can cross a product boundary without the
|
|
98
|
+
> receiver needing access to the producer's internals.
|
|
99
|
+
|
|
100
|
+
The `source` field identifies the producer. Bundles from multiple producers can be
|
|
101
|
+
merged; conflicts surface as `disputed` status (never last-write-wins).
|
|
102
|
+
|
|
103
|
+
An optional `identityLinks` array declares co-referent subjects — real-world entities
|
|
104
|
+
known under more than one identifier. Each link carries a stable optional `id`, a
|
|
105
|
+
`subjects` array (two or more `{ subjectType, subjectId }` refs), and an optional
|
|
106
|
+
`relation` field: `"equivalent"` (default — the subjects denote the same entity),
|
|
107
|
+
`"subsumes"` (the first subject is a superset of the others), or `"converts"` (the
|
|
108
|
+
subjects are related by a unit or scale transformation, parameterised by an optional
|
|
109
|
+
`conversion: { factor, offset, note }` object). A link may additionally carry a
|
|
110
|
+
`mappingClaimId` pointing to the Claim that evidences the mapping assertion itself;
|
|
111
|
+
when set, inquiry resolution through that link is subject to a weakest-link status cap —
|
|
112
|
+
a disputed mapping claim cannot yield a verified answer.
|
|
113
|
+
|
|
114
|
+
### Claim
|
|
115
|
+
|
|
116
|
+
An assertion about a real-world subject. A claim has a stable `id`, a `subjectType`
|
|
117
|
+
and `subjectId` pair identifying what is being asserted, a `claimType`, a
|
|
118
|
+
`fieldOrBehavior`, and a `value`. Claims carry optional `impactLevel`, integrity
|
|
119
|
+
anchors, policy references, derivation edges, and confidence basis metadata.
|
|
120
|
+
|
|
121
|
+
Derived trust status is never stored on the claim itself as source of truth; it is
|
|
122
|
+
computed from the surrounding bundle at evaluation time.
|
|
123
|
+
|
|
124
|
+
### Evidence
|
|
125
|
+
|
|
126
|
+
An item of support for a claim. Evidence is linked to a claim via `claimId`. Each
|
|
127
|
+
item carries `evidenceType`, `method`, `sourceRef`, an excerpt or summary, and
|
|
128
|
+
`observedAt`. Evidence can declare a `passing` boolean and a `blocking` flag; a
|
|
129
|
+
non-passing, non-blocked evidence item is a soft signal; a non-passing blocking
|
|
130
|
+
item can cause a `disputed` status outcome.
|
|
131
|
+
|
|
132
|
+
`supportStrength` (default `"entails"`) distinguishes full entailment from citation:
|
|
133
|
+
only `"entails"` evidence feeds policy requirement checks. `"cited"` evidence is
|
|
134
|
+
contextual but does not satisfy required-evidence policies.
|
|
135
|
+
|
|
136
|
+
### VerificationPolicy
|
|
137
|
+
|
|
138
|
+
A policy declares what evidence and methods are required to reach `verified` status
|
|
139
|
+
for a given `claimType`, and how long verification remains valid. Core fields:
|
|
140
|
+
`requiredEvidence` (array of evidence types), `requiredMethods`, `requiresCorroboration`,
|
|
141
|
+
`validityRule` (one of `duration`, `commit`, `historical`, `manual`), and
|
|
142
|
+
`acceptanceCriteria`.
|
|
143
|
+
|
|
144
|
+
Policies are resolved against claims by `verificationPolicyId` first, then by
|
|
145
|
+
`claimType` exact match, then by walking the `parentType` chain from most-specific
|
|
146
|
+
to most-general. See [Status Derivation](status-function.md) for how the resolved
|
|
147
|
+
policy feeds the derivation.
|
|
148
|
+
|
|
149
|
+
### VerificationEvent
|
|
150
|
+
|
|
151
|
+
An append-only event representing a status decision for a claim. Events carry
|
|
152
|
+
`claimId`, `status`, `actor`, `method`, `evidenceIds`, and timestamps. Events are
|
|
153
|
+
never updated; they accumulate as a ledger. The most recent event of a given kind
|
|
154
|
+
shapes the derived status via the fold described in [Status Derivation](status-function.md).
|
|
155
|
+
|
|
156
|
+
A verification event may carry `resolvesDispute: true` and an `authorityRef` to
|
|
157
|
+
indicate it is an authority-gated dispute-resolution decision (ADR 0003 §8).
|
|
158
|
+
|
|
159
|
+
### AuthorityTrace
|
|
160
|
+
|
|
161
|
+
A record establishing that a named actor held a named authority over a subject during
|
|
162
|
+
a time window. Authority traces are the credential that makes a dispute-resolution
|
|
163
|
+
event binding: the fold checks that the resolution event's actor has an active trace
|
|
164
|
+
at the decision timestamp. Fields: `actorRef`, `authorityType`, `authorityRef`,
|
|
165
|
+
`validFrom`, `validUntil`, `revokedAt`, and optional integrity anchors.
|
|
166
|
+
|
|
167
|
+
### InquiryRecord
|
|
168
|
+
|
|
169
|
+
An append-only record capturing the resolution of a consumer-side question (Inquiry)
|
|
170
|
+
against the ledger (ADR 0003 §6). An InquiryRecord carries the original question, the
|
|
171
|
+
resolution path (matched claim or named derivation rule plus input claims), the answer
|
|
172
|
+
with its status at evaluation time, a frozen snapshot of input claim statuses, the
|
|
173
|
+
`statusFunctionVersion` used, and the `resolvedAt` timestamp.
|
|
174
|
+
|
|
175
|
+
Records never go stale because they never assert present-tense truth; they assert what
|
|
176
|
+
was knowable at a specific moment. The `statusFunctionVersion` field enables
|
|
177
|
+
re-evaluation if the derivation algorithm changes.
|
|
178
|
+
|
|
179
|
+
### DerivationRule
|
|
180
|
+
|
|
181
|
+
A named, versioned rule that derives a boolean answer from existing claims (ADR 0003 §5).
|
|
182
|
+
Rules compose claims using value predicates (`eq`, `gt`, `gte`, `lte`, `in`, `exists`)
|
|
183
|
+
and status predicates (`acceptedStatuses`), combined with `"all"` or `"any"`. Rules
|
|
184
|
+
are promoted from Flow's gate-expectation language. The weakest-link confidence ceiling
|
|
185
|
+
propagates through rule evaluation unchanged.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Status semantics
|
|
190
|
+
|
|
191
|
+
Status is a pure, versioned function of the bundle data and a `now` timestamp. The
|
|
192
|
+
full specification of the derivation algorithm is in [status-function.md](status-function.md).
|
|
193
|
+
|
|
194
|
+
The eight possible statuses:
|
|
195
|
+
|
|
196
|
+
| Status | Meaning |
|
|
197
|
+
|---|---|
|
|
198
|
+
| `unknown` | No supporting evidence or events; the claim cannot be evaluated. |
|
|
199
|
+
| `proposed` | Evidence exists or a verification event indicates proposed, but policy requirements are not fully met. |
|
|
200
|
+
| `assumed` | The claim is treated as true for operational purposes without full verification evidence. |
|
|
201
|
+
| `verified` | A verification event asserts verified, required policy evidence is present, and the verification is still fresh. |
|
|
202
|
+
| `stale` | The most recent verified event has expired under the policy's validity rule. |
|
|
203
|
+
| `disputed` | A verified claim has blocking contradicting evidence, or a terminal dispute event exists. |
|
|
204
|
+
| `superseded` | A terminal event marks the claim as superseded. |
|
|
205
|
+
| `rejected` | A terminal event marks the claim as rejected. |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Normative schemas
|
|
210
|
+
|
|
211
|
+
The JSON schemas at [`schemas/`](schemas/) are the normative wire contracts for
|
|
212
|
+
all core record shapes. The following schema files are part of this format:
|
|
213
|
+
|
|
214
|
+
| Schema file | Record type(s) |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `trust-bundle.schema.json` | TrustBundle (top-level container) |
|
|
217
|
+
| `claim.schema.json` | Claim |
|
|
218
|
+
| `evidence.schema.json` | Evidence |
|
|
219
|
+
| `verification-policy.schema.json` | VerificationPolicy |
|
|
220
|
+
| `verification-event.schema.json` | VerificationEvent |
|
|
221
|
+
| `trust-report.schema.json` | TrustReport (derived, not emitted by producers) |
|
|
222
|
+
| `derivation-rule.schema.json` | DerivationRule |
|
|
223
|
+
| `inquiry-record.schema.json` | InquiryRecord |
|
|
224
|
+
|
|
225
|
+
Schemas are not duplicated in this directory. The reference implementation
|
|
226
|
+
validates TrustBundle input against these schemas via `validateTrustBundle()`.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Out of scope: future extension profiles
|
|
231
|
+
|
|
232
|
+
The following producer domains are explicitly out of scope for this core specification.
|
|
233
|
+
Each is a candidate for a future extension profile that imports the core record shapes
|
|
234
|
+
and adds domain-specific vocabulary:
|
|
235
|
+
|
|
236
|
+
- **Survey chains** — the source → extraction → candidate → review → claim provenance
|
|
237
|
+
path that Survey uses to build trust bundles. Survey emits bundles conforming to
|
|
238
|
+
this spec; the review-trail records above it are Survey-scoped.
|
|
239
|
+
- **Veritas standards** — repo-area claims, per-run evidence collection, merge-gate
|
|
240
|
+
integration, and the `ClaimReviewRecord` pattern from the Kontour Resource Shape.
|
|
241
|
+
- **Flow gates** — gate-expectation language, run-scoped views, gate results, and
|
|
242
|
+
the `GateRun` resource shape.
|
|
243
|
+
|
|
244
|
+
Extension profiles reference this spec as their foundation and declare any additional
|
|
245
|
+
fields or constraints. They do not modify the core record shapes.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Executable conformance
|
|
250
|
+
|
|
251
|
+
`spec/conformance/` contains test vector bundles and expected per-claim statuses at a
|
|
252
|
+
fixed `now`. The test at `tests/spec-conformance.test.ts` loads every test vector and
|
|
253
|
+
asserts that the reference implementation derives the expected statuses, making this
|
|
254
|
+
specification executable.
|
|
255
|
+
|
|
256
|
+
See [conformance/README.md](conformance/README.md) for the test vector inventory.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Canonical home
|
|
261
|
+
|
|
262
|
+
This repository (`hachure-org/spec`) is the canonical home of the Hachure
|
|
263
|
+
specification: prose, normative JSON Schemas, and conformance test vectors.
|
|
264
|
+
The reference implementation lives at
|
|
265
|
+
[`kontourai/surface`](https://github.com/kontourai/surface), which runs these
|
|
266
|
+
test vectors in its suite. Until the extraction settles, changes land here and
|
|
267
|
+
in the reference implementation together; this repo wins on conflict.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Spec Conformance Test vectors
|
|
2
|
+
|
|
3
|
+
This directory contains input bundles and expected per-claim statuses that make
|
|
4
|
+
the [Status Derivation specification](../status-function.md) executable.
|
|
5
|
+
|
|
6
|
+
Each test vector is a JSON file with an `input` (a valid TrustBundle) and an `expect`
|
|
7
|
+
object listing expected per-claim statuses at a fixed `now` timestamp. The test at
|
|
8
|
+
`tests/spec-conformance.test.ts` loads every test vector and asserts that the reference
|
|
9
|
+
implementation derives the expected statuses.
|
|
10
|
+
|
|
11
|
+
## Test vector inventory
|
|
12
|
+
|
|
13
|
+
| File | Scenario | Now |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `sf-verified-commit.json` | Commit-scoped policy — verified when integrity ref matches | 2026-06-10T00:00:00.000Z |
|
|
16
|
+
| `sf-stale-duration.json` | Duration policy — stale when window expired | 2026-06-10T00:00:00.000Z |
|
|
17
|
+
| `sf-disputed-blocking.json` | Verified event + blocking contradicting evidence → disputed | 2026-06-10T00:00:00.000Z |
|
|
18
|
+
| `sf-authority-resolved.json` | Disputed claim resolved by authority-gated event | 2026-06-10T00:00:00.000Z |
|
|
19
|
+
| `sf-reference-bundle-snapshot.json` | Full the reference bundle at fixed now — four claims | 2026-06-10T00:00:00.000Z |
|
|
20
|
+
|
|
21
|
+
## Test vector format
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"now": "<ISO 8601 string>",
|
|
26
|
+
"input": { /* TrustBundle */ },
|
|
27
|
+
"expect": {
|
|
28
|
+
"statusByClaimId": { "<claimId>": "<TrustStatus>" }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"now": "2026-06-10T00:00:00.000Z",
|
|
3
|
+
"input": {
|
|
4
|
+
"schemaVersion": 3,
|
|
5
|
+
"source": "spec-conformance:authority-resolved",
|
|
6
|
+
"claims": [
|
|
7
|
+
{
|
|
8
|
+
"id": "claim.status.current",
|
|
9
|
+
"subjectType": "data-field",
|
|
10
|
+
"subjectId": "dataset:program-status",
|
|
11
|
+
"surface": "public-data.program",
|
|
12
|
+
"claimType": "public-data-field",
|
|
13
|
+
"fieldOrBehavior": "currentStatus",
|
|
14
|
+
"value": "active",
|
|
15
|
+
"createdAt": "2026-05-01T00:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-05-01T00:00:00.000Z",
|
|
17
|
+
"impactLevel": "high",
|
|
18
|
+
"verificationPolicyId": "policy.public-data-field.basic"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"evidence": [
|
|
22
|
+
{
|
|
23
|
+
"id": "evidence.status.supporting",
|
|
24
|
+
"claimId": "claim.status.current",
|
|
25
|
+
"evidenceType": "source_excerpt",
|
|
26
|
+
"method": "observation",
|
|
27
|
+
"sourceRef": "primary source",
|
|
28
|
+
"excerptOrSummary": "Program is currently active.",
|
|
29
|
+
"observedAt": "2026-05-01T00:00:00.000Z",
|
|
30
|
+
"collectedBy": "crawler"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "evidence.status.conflicting",
|
|
34
|
+
"claimId": "claim.status.current",
|
|
35
|
+
"evidenceType": "source_excerpt",
|
|
36
|
+
"method": "observation",
|
|
37
|
+
"sourceRef": "secondary source",
|
|
38
|
+
"excerptOrSummary": "Program is inactive — conflicts with primary source.",
|
|
39
|
+
"observedAt": "2026-05-02T00:00:00.000Z",
|
|
40
|
+
"collectedBy": "crawler",
|
|
41
|
+
"passing": false,
|
|
42
|
+
"blocking": true
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"policies": [
|
|
46
|
+
{
|
|
47
|
+
"id": "policy.public-data-field.basic",
|
|
48
|
+
"claimType": "public-data-field",
|
|
49
|
+
"requiredEvidence": ["source_excerpt"],
|
|
50
|
+
"requiredMethods": ["observation"],
|
|
51
|
+
"requiresCorroboration": false,
|
|
52
|
+
"acceptanceCriteria": ["field verified from source"],
|
|
53
|
+
"reviewAuthority": "domain-expert",
|
|
54
|
+
"validityRule": { "kind": "duration", "durationDays": 60 },
|
|
55
|
+
"stalenessTriggers": ["source page changes"],
|
|
56
|
+
"conflictRules": [],
|
|
57
|
+
"impactLevel": "high"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"events": [
|
|
61
|
+
{
|
|
62
|
+
"id": "event.status.initial-verified",
|
|
63
|
+
"claimId": "claim.status.current",
|
|
64
|
+
"status": "verified",
|
|
65
|
+
"actor": "operator",
|
|
66
|
+
"method": "attestation",
|
|
67
|
+
"evidenceIds": ["evidence.status.supporting"],
|
|
68
|
+
"createdAt": "2026-05-01T00:00:00.000Z",
|
|
69
|
+
"verifiedAt": "2026-05-01T00:00:00.000Z"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": "event.status.authority-resolution",
|
|
73
|
+
"claimId": "claim.status.current",
|
|
74
|
+
"status": "verified",
|
|
75
|
+
"actor": "reviewer:alice",
|
|
76
|
+
"method": "authority-review",
|
|
77
|
+
"evidenceIds": ["evidence.status.supporting"],
|
|
78
|
+
"createdAt": "2026-05-10T00:00:00.000Z",
|
|
79
|
+
"verifiedAt": "2026-05-10T00:00:00.000Z",
|
|
80
|
+
"resolvesDispute": true,
|
|
81
|
+
"authorityRef": "authority.domain-expert"
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"authorityTrace": [
|
|
85
|
+
{
|
|
86
|
+
"id": "trace.alice.domain-expert",
|
|
87
|
+
"subject": {
|
|
88
|
+
"subjectType": "data-field",
|
|
89
|
+
"subjectId": "dataset:program-status"
|
|
90
|
+
},
|
|
91
|
+
"actorRef": "reviewer:alice",
|
|
92
|
+
"authorityType": "role",
|
|
93
|
+
"authorityRef": "authority.domain-expert",
|
|
94
|
+
"sourceRef": "org-policy-2026",
|
|
95
|
+
"observedAt": "2026-01-01T00:00:00.000Z",
|
|
96
|
+
"validFrom": "2026-01-01T00:00:00.000Z",
|
|
97
|
+
"validUntil": "2027-01-01T00:00:00.000Z"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"expect": {
|
|
102
|
+
"statusByClaimId": {
|
|
103
|
+
"claim.status.current": "verified"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"now": "2026-06-10T00:00:00.000Z",
|
|
3
|
+
"input": {
|
|
4
|
+
"schemaVersion": 3,
|
|
5
|
+
"source": "spec-conformance:disputed-blocking",
|
|
6
|
+
"claims": [
|
|
7
|
+
{
|
|
8
|
+
"id": "claim.fee.value",
|
|
9
|
+
"subjectType": "data-field",
|
|
10
|
+
"subjectId": "dataset:registration-fee",
|
|
11
|
+
"surface": "public-data.fees",
|
|
12
|
+
"claimType": "public-data-field",
|
|
13
|
+
"fieldOrBehavior": "registrationFee",
|
|
14
|
+
"value": 150,
|
|
15
|
+
"createdAt": "2026-06-01T00:00:00.000Z",
|
|
16
|
+
"updatedAt": "2026-06-01T00:00:00.000Z",
|
|
17
|
+
"impactLevel": "medium",
|
|
18
|
+
"verificationPolicyId": "policy.public-data-field.basic"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"evidence": [
|
|
22
|
+
{
|
|
23
|
+
"id": "evidence.fee.passing",
|
|
24
|
+
"claimId": "claim.fee.value",
|
|
25
|
+
"evidenceType": "source_excerpt",
|
|
26
|
+
"method": "observation",
|
|
27
|
+
"sourceRef": "source A: example.org/fees",
|
|
28
|
+
"excerptOrSummary": "Registration fee is $150.",
|
|
29
|
+
"observedAt": "2026-06-01T00:00:00.000Z",
|
|
30
|
+
"collectedBy": "crawler"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": "evidence.fee.conflicting",
|
|
34
|
+
"claimId": "claim.fee.value",
|
|
35
|
+
"evidenceType": "source_excerpt",
|
|
36
|
+
"method": "observation",
|
|
37
|
+
"sourceRef": "source B: fees.example.org",
|
|
38
|
+
"excerptOrSummary": "Registration fee is $200 — conflicts with $150 in source A.",
|
|
39
|
+
"observedAt": "2026-06-05T00:00:00.000Z",
|
|
40
|
+
"collectedBy": "crawler",
|
|
41
|
+
"passing": false,
|
|
42
|
+
"blocking": true
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"policies": [
|
|
46
|
+
{
|
|
47
|
+
"id": "policy.public-data-field.basic",
|
|
48
|
+
"claimType": "public-data-field",
|
|
49
|
+
"requiredEvidence": ["source_excerpt"],
|
|
50
|
+
"requiredMethods": ["observation"],
|
|
51
|
+
"requiresCorroboration": false,
|
|
52
|
+
"acceptanceCriteria": ["field verified from source"],
|
|
53
|
+
"reviewAuthority": "operator",
|
|
54
|
+
"validityRule": { "kind": "duration", "durationDays": 30 },
|
|
55
|
+
"stalenessTriggers": ["source page changes"],
|
|
56
|
+
"conflictRules": [],
|
|
57
|
+
"impactLevel": "medium"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"events": [
|
|
61
|
+
{
|
|
62
|
+
"id": "event.fee.verified",
|
|
63
|
+
"claimId": "claim.fee.value",
|
|
64
|
+
"status": "verified",
|
|
65
|
+
"actor": "operator",
|
|
66
|
+
"method": "attestation",
|
|
67
|
+
"evidenceIds": ["evidence.fee.passing"],
|
|
68
|
+
"createdAt": "2026-06-01T00:00:00.000Z",
|
|
69
|
+
"verifiedAt": "2026-06-01T00:00:00.000Z"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"expect": {
|
|
74
|
+
"statusByClaimId": {
|
|
75
|
+
"claim.fee.value": "disputed"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|