hachure 0.8.0 → 0.9.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 +12 -2
- package/conformance/manifest.json +1 -1
- package/conformance/merge/merge-agree-values.json +4 -4
- package/conformance/merge/merge-collision-order-independence.json +7 -7
- package/conformance/merge/merge-conflict-status.json +4 -4
- package/conformance/merge/merge-conflict-value.json +4 -4
- package/conformance/sf-authority-resolved.json +2 -2
- package/conformance/sf-disputed-blocking.json +2 -2
- package/conformance/sf-expired-window.json +3 -3
- package/conformance/sf-no-freshness-fields.json +2 -2
- package/conformance/sf-reference-bundle-snapshot.json +5 -5
- package/conformance/sf-revoked-event.json +2 -2
- package/conformance/sf-stale-duration.json +2 -2
- package/conformance/sf-verified-commit.json +2 -2
- package/merge.md +18 -13
- package/package.json +1 -1
- package/schemas/claim.schema.json +2 -2
- package/schemas/trust-bundle.schema.json +1 -1
- package/schemas/trust-report.schema.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ Resource Shape envelope. Product-specific records use product-scoped namespaces
|
|
|
73
73
|
Pre-1.0: the format uses hard breaking changes rather than compatibility aliases.
|
|
74
74
|
No forward or backward compatibility guarantees are made across versions. Version
|
|
75
75
|
bumps are reflected in `schemaVersion` (an integer field in TrustBundle, currently
|
|
76
|
-
`
|
|
76
|
+
`5`) and in the status function version (a string exported by the reference
|
|
77
77
|
implementation as `statusFunctionVersion`, currently `"2"`).
|
|
78
78
|
|
|
79
79
|
Schema version `4` adds optional claim freshness fields (`expiresAt` /
|
|
@@ -84,6 +84,14 @@ every bundle valid at `schemaVersion` `3` remains valid; only the deriver
|
|
|
84
84
|
`status-function.md` and the `sf-expired-window` / `sf-revoked-event` /
|
|
85
85
|
`sf-no-freshness-fields` conformance vectors.
|
|
86
86
|
|
|
87
|
+
Schema version `5` renames the Claim `surface` field to `facet` and makes it
|
|
88
|
+
optional (previously required) — the one deliberate hard break named above.
|
|
89
|
+
Bundles declaring `schemaVersion` `2` through `4` are no longer schema-valid
|
|
90
|
+
under this release: their `surface` field is rejected by `claim.schema.json`'s
|
|
91
|
+
`additionalProperties: false`. Producers MUST re-emit as `facet` and self-declare
|
|
92
|
+
`schemaVersion: 5`. See `merge.md` §4 for `facet`'s (unchanged) treatment in claim
|
|
93
|
+
identity.
|
|
94
|
+
|
|
87
95
|
---
|
|
88
96
|
|
|
89
97
|
## Conformance language
|
|
@@ -140,7 +148,9 @@ a disputed mapping claim cannot yield a verified answer.
|
|
|
140
148
|
### Claim
|
|
141
149
|
|
|
142
150
|
An assertion about a real-world subject. A claim has a stable `id`, a `subjectType`
|
|
143
|
-
and `subjectId` pair identifying what is being asserted,
|
|
151
|
+
and `subjectId` pair identifying what is being asserted, an optional `facet` (a
|
|
152
|
+
producer-defined grouping or namespace for the claim — see `merge.md` §4 for why
|
|
153
|
+
it's excluded from cross-producer claim identity), a `claimType`, a
|
|
144
154
|
`fieldOrBehavior`, and a `value`. Claims carry optional `impactLevel`, integrity
|
|
145
155
|
anchors, policy references, derivation edges, and confidence basis metadata.
|
|
146
156
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schemaComment": "Machine-readable conformance manifest for the Hachure trust format. Not a JSON Schema itself — a structured index of what an implementation must pass to claim conformance at each level. Additive to, not a replacement for, index.mjs's `testVectors` export (which lists raw vectors, not levels/pass-criteria).",
|
|
3
3
|
"manifestVersion": 1,
|
|
4
4
|
"appliesTo": {
|
|
5
|
-
"schemaVersion": [
|
|
5
|
+
"schemaVersion": [5],
|
|
6
6
|
"statusFunctionVersion": "2"
|
|
7
7
|
},
|
|
8
8
|
"levels": [
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"now": "2026-06-10T00:00:00.000Z",
|
|
4
4
|
"inputs": [
|
|
5
5
|
{
|
|
6
|
-
"schemaVersion":
|
|
6
|
+
"schemaVersion": 5,
|
|
7
7
|
"source": "producer-a:run-1",
|
|
8
8
|
"producerId": "producer-a",
|
|
9
9
|
"claims": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"id": "producer-a.claim.readiness.coverage",
|
|
12
12
|
"subjectType": "repo",
|
|
13
13
|
"subjectId": "repo-1",
|
|
14
|
-
"
|
|
14
|
+
"facet": "readiness",
|
|
15
15
|
"claimType": "coverage",
|
|
16
16
|
"fieldOrBehavior": "coverage",
|
|
17
17
|
"value": 91,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"events": []
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
"schemaVersion":
|
|
27
|
+
"schemaVersion": 5,
|
|
28
28
|
"source": "producer-b:run-7",
|
|
29
29
|
"producerId": "producer-b",
|
|
30
30
|
"claims": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"id": "producer-b.claim.readiness.coverage",
|
|
33
33
|
"subjectType": "repo",
|
|
34
34
|
"subjectId": "repo-1",
|
|
35
|
-
"
|
|
35
|
+
"facet": "readiness",
|
|
36
36
|
"claimType": "coverage",
|
|
37
37
|
"fieldOrBehavior": "coverage",
|
|
38
38
|
"value": 91,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Hand-derivation (merge.md §5/§6/§8). This vector's inputs/expect are STRUCTURALLY identical to .kontourai/flow-agents/hachure-identifier-merge/design.md §11 'Worked example + independent hand-derivation' -- the bundle-level source/producerId values were genericized from design.md §11's worked example (survey -> producer-a, veritas -> producer-b, flow -> producer-c; mapping recorded in this session's deliver.md History) to keep this shipped, machine-checked conformance fixture vendor-neutral, consistent with the rest of this repo's conformance vectors and merge.md's own examples (plan.md AC7). This rename does NOT change expect: source/producerId are bundle-level fields, not part of the Claim record being compared, so the tie-break outcome below is unaffected -- re-derived by hand against the renamed inputs. shared.claim.x appears in Bundle A (subjectId r1,
|
|
2
|
+
"$comment": "Hand-derivation (merge.md §5/§6/§8). This vector's inputs/expect are STRUCTURALLY identical to .kontourai/flow-agents/hachure-identifier-merge/design.md §11 'Worked example + independent hand-derivation' -- the bundle-level source/producerId values were genericized from design.md §11's worked example (survey -> producer-a, veritas -> producer-b, flow -> producer-c; mapping recorded in this session's deliver.md History) to keep this shipped, machine-checked conformance fixture vendor-neutral, consistent with the rest of this repo's conformance vectors and merge.md's own examples (plan.md AC7). This rename does NOT change expect: source/producerId are bundle-level fields, not part of the Claim record being compared, so the tie-break outcome below is unaffected -- re-derived by hand against the renamed inputs. shared.claim.x appears in Bundle A (subjectId r1, facet readiness, claimType coverage, value 91) and Bundle B (subjectId r2, facet governance, claimType policy-check, value true) -- content differs under the same id, so per merge.md §5 rule 2 this is a collision, reported as {collection: 'claims', id: 'shared.claim.x'}. Per merge.md §6's tie-break, compute a canonical (sorted-key) serialization of each variant: A's serialization starts '{\\\"claimType\\\":\\\"coverage\\\",...}', B's starts '{\\\"claimType\\\":\\\"policy-check\\\",...}' -- lexicographically 'coverage' < 'policy-check' ('c' < 'p'), so A's record is the deterministically-kept content regardless of whether the implementation is handed [A,B,C], [B,A,C], [C,B,A], or any other permutation of the 3 inputs -- this is the vector that exercises the order-independence MUST (test/merge.test.mjs asserts identical output across every permutation of inputs). hachure-facet-rename provenance note: this vector's claim key was renamed surface -> facet (0.9.0). The tie-break outcome is unaffected by that rename and was re-derived by hand, not merely asserted: both colliding records' sorted-key canonical serializations still diverge for the first time inside the claimType value ('coverage' vs 'policy-check'), a key that is alphabetically earlier than every other property on this claim shape (id, subjectType, subjectId, facet, fieldOrBehavior, value, createdAt, updatedAt) both before and after the rename -- the facet/surface key itself never becomes part of the comparison because the strings already diverge before either serialization reaches that key, regardless of where the renamed key sorts relative to the others. (Confirmed by direct RFC-8785-shaped sorted-key serialization of both the pre-rename and post-rename claim objects: both produce the same 'A sorts first' result.) Bundle C's claim ('unrelated.claim.y') never collides with anything, and its id is a distinct string never repeated. Status-function.md Step 6 ('no policy, no evidence') applies to both surviving claim ids ('shared.claim.x' from kept content A, and 'unrelated.claim.y') since no bundle attaches any policy or evidence/events -> both derive 'unknown'.",
|
|
3
3
|
"now": "2026-06-10T00:00:00.000Z",
|
|
4
4
|
"inputs": [
|
|
5
5
|
{
|
|
6
|
-
"schemaVersion":
|
|
6
|
+
"schemaVersion": 5,
|
|
7
7
|
"source": "producer-a",
|
|
8
8
|
"producerId": "producer-a",
|
|
9
9
|
"claims": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"id": "shared.claim.x",
|
|
12
12
|
"subjectType": "repo",
|
|
13
13
|
"subjectId": "r1",
|
|
14
|
-
"
|
|
14
|
+
"facet": "readiness",
|
|
15
15
|
"claimType": "coverage",
|
|
16
16
|
"fieldOrBehavior": "coverage",
|
|
17
17
|
"value": 91,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"events": []
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
"schemaVersion":
|
|
27
|
+
"schemaVersion": 5,
|
|
28
28
|
"source": "producer-b",
|
|
29
29
|
"producerId": "producer-b",
|
|
30
30
|
"claims": [
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"id": "shared.claim.x",
|
|
33
33
|
"subjectType": "repo",
|
|
34
34
|
"subjectId": "r2",
|
|
35
|
-
"
|
|
35
|
+
"facet": "governance",
|
|
36
36
|
"claimType": "policy-check",
|
|
37
37
|
"fieldOrBehavior": "signed-off",
|
|
38
38
|
"value": true,
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"events": []
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
"schemaVersion":
|
|
48
|
+
"schemaVersion": 5,
|
|
49
49
|
"source": "producer-c",
|
|
50
50
|
"producerId": "producer-c",
|
|
51
51
|
"claims": [
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"id": "unrelated.claim.y",
|
|
54
54
|
"subjectType": "gate",
|
|
55
55
|
"subjectId": "g1",
|
|
56
|
-
"
|
|
56
|
+
"facet": "gates",
|
|
57
57
|
"claimType": "gate-status",
|
|
58
58
|
"fieldOrBehavior": "passed",
|
|
59
59
|
"value": true,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"now": "2026-06-10T00:00:00.000Z",
|
|
4
4
|
"inputs": [
|
|
5
5
|
{
|
|
6
|
-
"schemaVersion":
|
|
6
|
+
"schemaVersion": 5,
|
|
7
7
|
"source": "producer-a:run-3",
|
|
8
8
|
"producerId": "producer-a",
|
|
9
9
|
"claims": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"id": "producer-a.claim.access.grant",
|
|
12
12
|
"subjectType": "resource",
|
|
13
13
|
"subjectId": "svc-1",
|
|
14
|
-
"
|
|
14
|
+
"facet": "access",
|
|
15
15
|
"claimType": "access-check",
|
|
16
16
|
"fieldOrBehavior": "granted",
|
|
17
17
|
"value": true,
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
|
-
"schemaVersion":
|
|
78
|
+
"schemaVersion": 5,
|
|
79
79
|
"source": "producer-b:run-4",
|
|
80
80
|
"producerId": "producer-b",
|
|
81
81
|
"claims": [
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"id": "producer-b.claim.access.grant",
|
|
84
84
|
"subjectType": "resource",
|
|
85
85
|
"subjectId": "svc-1",
|
|
86
|
-
"
|
|
86
|
+
"facet": "access",
|
|
87
87
|
"claimType": "access-check",
|
|
88
88
|
"fieldOrBehavior": "granted",
|
|
89
89
|
"value": true,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"now": "2026-06-10T00:00:00.000Z",
|
|
4
4
|
"inputs": [
|
|
5
5
|
{
|
|
6
|
-
"schemaVersion":
|
|
6
|
+
"schemaVersion": 5,
|
|
7
7
|
"source": "producer-a:run-2",
|
|
8
8
|
"producerId": "producer-a",
|
|
9
9
|
"claims": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"id": "producer-a.claim.pricing.tier",
|
|
12
12
|
"subjectType": "repo",
|
|
13
13
|
"subjectId": "repo-2",
|
|
14
|
-
"
|
|
14
|
+
"facet": "pricing",
|
|
15
15
|
"claimType": "pricing-field",
|
|
16
16
|
"fieldOrBehavior": "tier",
|
|
17
17
|
"value": "gold",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"events": []
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
|
-
"schemaVersion":
|
|
53
|
+
"schemaVersion": 5,
|
|
54
54
|
"source": "producer-b:run-9",
|
|
55
55
|
"producerId": "producer-b",
|
|
56
56
|
"claims": [
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"id": "producer-b.claim.pricing.tier",
|
|
59
59
|
"subjectType": "repo",
|
|
60
60
|
"subjectId": "repo-2",
|
|
61
|
-
"
|
|
61
|
+
"facet": "pricing",
|
|
62
62
|
"claimType": "pricing-field",
|
|
63
63
|
"fieldOrBehavior": "tier",
|
|
64
64
|
"value": "silver",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:authority-resolved",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.status.current",
|
|
9
9
|
"subjectType": "data-field",
|
|
10
10
|
"subjectId": "dataset:program-status",
|
|
11
|
-
"
|
|
11
|
+
"facet": "public-data.program",
|
|
12
12
|
"claimType": "public-data-field",
|
|
13
13
|
"fieldOrBehavior": "currentStatus",
|
|
14
14
|
"value": "active",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:disputed-blocking",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.fee.value",
|
|
9
9
|
"subjectType": "data-field",
|
|
10
10
|
"subjectId": "dataset:registration-fee",
|
|
11
|
-
"
|
|
11
|
+
"facet": "public-data.fees",
|
|
12
12
|
"claimType": "public-data-field",
|
|
13
13
|
"fieldOrBehavior": "registrationFee",
|
|
14
14
|
"value": 150,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:expired-window",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.window.expires-at",
|
|
9
9
|
"subjectType": "data-field",
|
|
10
10
|
"subjectId": "dataset:session-token",
|
|
11
|
-
"
|
|
11
|
+
"facet": "public-data.status",
|
|
12
12
|
"claimType": "public-data-field",
|
|
13
13
|
"fieldOrBehavior": "tokenValid",
|
|
14
14
|
"value": true,
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"id": "claim.window.ttl",
|
|
23
23
|
"subjectType": "data-field",
|
|
24
24
|
"subjectId": "dataset:cache-entry",
|
|
25
|
-
"
|
|
25
|
+
"facet": "public-data.status",
|
|
26
26
|
"claimType": "public-data-field",
|
|
27
27
|
"fieldOrBehavior": "cacheFresh",
|
|
28
28
|
"value": true,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:no-freshness-fields",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.api.rate-limit",
|
|
9
9
|
"subjectType": "api",
|
|
10
10
|
"subjectId": "public-api",
|
|
11
|
-
"
|
|
11
|
+
"facet": "api.guarantees",
|
|
12
12
|
"claimType": "software-evidence",
|
|
13
13
|
"fieldOrBehavior": "rate limit is enforced",
|
|
14
14
|
"value": "100 requests/minute",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "kontour-surface-validation-fixtures",
|
|
6
6
|
"identityLinks": [
|
|
7
7
|
{
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"id": "claim.repo-governance.api-proof",
|
|
24
24
|
"subjectType": "repo-surface",
|
|
25
25
|
"subjectId": "example/repo:src/api",
|
|
26
|
-
"
|
|
26
|
+
"facet": "repo-governance.developer-evidence",
|
|
27
27
|
"claimType": "software-evidence",
|
|
28
28
|
"fieldOrBehavior": "acceptanceCriteriaLane",
|
|
29
29
|
"value": "npm test passed for API surface change",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"id": "claim.field-attested-records.registration-status",
|
|
50
50
|
"subjectType": "attested-record",
|
|
51
51
|
"subjectId": "field-attested-records:denver-example-record",
|
|
52
|
-
"
|
|
52
|
+
"facet": "field-attested-records.public-data",
|
|
53
53
|
"claimType": "public-data-field",
|
|
54
54
|
"fieldOrBehavior": "registrationStatus",
|
|
55
55
|
"value": "OPEN",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"id": "claim.fact-resolution.w2-wages",
|
|
71
71
|
"subjectType": "fact",
|
|
72
72
|
"subjectId": "fact-resolution:demo-case-2025:w2.wages",
|
|
73
|
-
"
|
|
73
|
+
"facet": "fact-resolution.financial-facts",
|
|
74
74
|
"claimType": "verified-financial-fact",
|
|
75
75
|
"fieldOrBehavior": "w2.wages",
|
|
76
76
|
"value": 123456,
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"id": "claim.surface.future-console",
|
|
91
91
|
"subjectType": "roadmap-item",
|
|
92
92
|
"subjectId": "kontour-surface:hosted-console",
|
|
93
|
-
"
|
|
93
|
+
"facet": "surface.roadmap",
|
|
94
94
|
"claimType": "roadmap-capability",
|
|
95
95
|
"fieldOrBehavior": "implementationStatus",
|
|
96
96
|
"value": "planned",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:revoked-event",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.access.grant",
|
|
9
9
|
"subjectType": "credential",
|
|
10
10
|
"subjectId": "access:deploy-key-7",
|
|
11
|
-
"
|
|
11
|
+
"facet": "access-control.grants",
|
|
12
12
|
"claimType": "software-evidence",
|
|
13
13
|
"fieldOrBehavior": "deployKeyValid",
|
|
14
14
|
"value": true,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:stale-duration",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.public.field",
|
|
9
9
|
"subjectType": "data-field",
|
|
10
10
|
"subjectId": "dataset:registration-status",
|
|
11
|
-
"
|
|
11
|
+
"facet": "public-data.status",
|
|
12
12
|
"claimType": "public-data-field",
|
|
13
13
|
"fieldOrBehavior": "registrationStatus",
|
|
14
14
|
"value": "OPEN",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"now": "2026-06-10T00:00:00.000Z",
|
|
3
3
|
"input": {
|
|
4
|
-
"schemaVersion":
|
|
4
|
+
"schemaVersion": 5,
|
|
5
5
|
"source": "spec-conformance:verified-commit",
|
|
6
6
|
"claims": [
|
|
7
7
|
{
|
|
8
8
|
"id": "claim.api.rate-limit",
|
|
9
9
|
"subjectType": "api",
|
|
10
10
|
"subjectId": "public-api",
|
|
11
|
-
"
|
|
11
|
+
"facet": "api.guarantees",
|
|
12
12
|
"claimType": "software-evidence",
|
|
13
13
|
"fieldOrBehavior": "rate limit is enforced",
|
|
14
14
|
"value": "100 requests/minute",
|
package/merge.md
CHANGED
|
@@ -42,7 +42,7 @@ identifier for the *system* that produced the bundle, distinct from
|
|
|
42
42
|
|
|
43
43
|
```jsonc
|
|
44
44
|
{
|
|
45
|
-
"schemaVersion":
|
|
45
|
+
"schemaVersion": 5,
|
|
46
46
|
"source": "producer-a:run-48213", // unchanged: free text, may vary per run
|
|
47
47
|
"producerId": "producer-a", // OPTIONAL, new: stable across runs
|
|
48
48
|
"claims": [ /* ... */ ]
|
|
@@ -114,7 +114,7 @@ for agreement/conflict comparison, §7) **if and only if:**
|
|
|
114
114
|
is equal once (1) is applied (same `fieldOrBehavior`, same `qualifiers`
|
|
115
115
|
after the existing trim/lowercase/sort normalization).
|
|
116
116
|
|
|
117
|
-
**`claimType` and `
|
|
117
|
+
**`claimType` and `facet` are explicitly excluded from the identity key —
|
|
118
118
|
this is a deliberate design decision, not an oversight:**
|
|
119
119
|
|
|
120
120
|
- `claimType` is excluded because the canonical claim key is defined over
|
|
@@ -124,13 +124,13 @@ this is a deliberate design decision, not an oversight:**
|
|
|
124
124
|
`claimType` taxonomies are still the same logical claim for merge
|
|
125
125
|
purposes; reusing the canonical key means merge and Inquiry matching never
|
|
126
126
|
diverge on this point.
|
|
127
|
-
- `
|
|
127
|
+
- `facet` is excluded because it is a producer-defined grouping or
|
|
128
128
|
namespace for related claims, not the primary thing users evaluate. Two
|
|
129
|
-
producers will pick unrelated `
|
|
130
|
-
claims — there is no shared `
|
|
129
|
+
producers will pick unrelated `facet` values for logically identical
|
|
130
|
+
claims — there is no shared `facet` vocabulary across producers;
|
|
131
131
|
including it in the identity key would make cross-producer matches
|
|
132
|
-
essentially never fire. `
|
|
133
|
-
producer's bundle (grouping, reporting `
|
|
132
|
+
essentially never fire. `facet` remains meaningful *within* one
|
|
133
|
+
producer's bundle (grouping, reporting `byFacet` counts) but plays no
|
|
134
134
|
role in cross-producer identity.
|
|
135
135
|
|
|
136
136
|
This means: **claims are never collapsed into one record by claim identity.**
|
|
@@ -386,9 +386,14 @@ claim).
|
|
|
386
386
|
|
|
387
387
|
## Versioning
|
|
388
388
|
|
|
389
|
-
This document introduces no change to `statusFunctionVersion` (stays `"2"`)
|
|
390
|
-
|
|
391
|
-
`
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
389
|
+
This document introduces no change to `statusFunctionVersion` (stays `"2"`).
|
|
390
|
+
`schemaVersion` itself has moved since this document's `producerId` addition
|
|
391
|
+
first shipped: it is now `5` (README.md's Namespace and versioning section is
|
|
392
|
+
the single source of truth for the current value), reflecting the unrelated
|
|
393
|
+
`surface` → `facet` rename described in §4 — not anything this document
|
|
394
|
+
introduces. Nothing in this document depends on that hard break: the
|
|
395
|
+
`producerId` field (§2) is optional and ignored by the unchanged
|
|
396
|
+
status-derivation fold, and remains schema-valid at `schemaVersion` `5`
|
|
397
|
+
exactly as it was when it shipped. A bundle merged under this document and fed
|
|
398
|
+
to the unchanged fold produces identical per-claim results to a bundle that
|
|
399
|
+
was never merged.
|
package/package.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"$id": "https://hachure.org/schemas/claim.schema.json",
|
|
4
4
|
"title": "Hachure Claim",
|
|
5
5
|
"type": "object",
|
|
6
|
-
"required": ["id", "subjectType", "subjectId", "
|
|
6
|
+
"required": ["id", "subjectType", "subjectId", "claimType", "fieldOrBehavior", "value", "createdAt", "updatedAt"],
|
|
7
7
|
"properties": {
|
|
8
8
|
"id": { "type": "string" },
|
|
9
9
|
"subjectType": { "type": "string" },
|
|
10
10
|
"subjectId": { "type": "string" },
|
|
11
|
-
"
|
|
11
|
+
"facet": { "type": "string" },
|
|
12
12
|
"claimType": { "type": "string" },
|
|
13
13
|
"fieldOrBehavior": { "type": "string" },
|
|
14
14
|
"value": {},
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"additionalProperties": false,
|
|
7
7
|
"required": ["schemaVersion", "source", "claims", "evidence", "policies", "events"],
|
|
8
8
|
"properties": {
|
|
9
|
-
"schemaVersion": { "enum": [
|
|
9
|
+
"schemaVersion": { "enum": [5] },
|
|
10
10
|
"source": { "type": "string" },
|
|
11
11
|
"producerId": {
|
|
12
12
|
"type": "string",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"statusFunctionVersion"
|
|
24
24
|
],
|
|
25
25
|
"properties": {
|
|
26
|
-
"schemaVersion": { "enum": [
|
|
26
|
+
"schemaVersion": { "enum": [5] },
|
|
27
27
|
"id": { "type": "string" },
|
|
28
28
|
"generatedAt": { "type": "string", "format": "date-time" },
|
|
29
29
|
"source": { "type": "string" },
|