kairos-chain 3.46.0 → 3.47.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 372dd921a298d45c97b957ae724a253bb22da73b5bb211025fe894eab5de4ff7
4
- data.tar.gz: f15e37a2caeef2d4d08b92f49608aa52307b1a93124a1742d3f40c10ae145bf8
3
+ metadata.gz: e43541279a3d104b85372574c94f6fdf2d96188fb7de83d5a4d84c3f470634d7
4
+ data.tar.gz: 21b58d11561dd6d4177a7aa3d3832bdfe4fbde80ff2da2af198662d655a6fc81
5
5
  SHA512:
6
- metadata.gz: c9fc60d9acee8dcb8b7a2bfb43021d3c8b129cb94471fe8488092683ade4755665faa72860fb8c1bed77d254e977226c3d8cd85bec4dfe95eea2d0dc12352190
7
- data.tar.gz: e5769c4b23ce1daef9704423f41e097d8969f5b86442ab1592beab4e3dc7623a3a79e30aba51d7ca2d5621e55fd635db740b5489761995bc2b9b33de8eb0b80e
6
+ metadata.gz: 41bc6c95594567c2e80ed006ea2bd21e7926361bf3cfb14fdf5a6b0a4aac17b9dca3f65faf17be1a4e86b16ce3fb9285af121d747fcdeac66eca58857d4af0bd
7
+ data.tar.gz: 77a5ac53384830598e90b408b4c737eb8549c219dfdeb47c38feb5939c46829c2b53dc9744da1a9914033521ff1fdf126f8d941989fe62857316863a75790e5f
data/CHANGELOG.md CHANGED
@@ -4,6 +4,47 @@ All notable changes to the `kairos-chain` gem will be documented in this file.
4
4
 
5
5
  This project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [3.47.0] - 2026-07-22
8
+
9
+ ### Synoptis — selective disclosure sdp-1 (AUD-L4 slice 1)
10
+
11
+ Implements AUD-L4 design v0.3 (SDP-1..5, FROZEN, review-converged) slice 1
12
+ in the synoptis SkillSet. All additive: sdp-1 builds on khab-1/map-1/rpr-1
13
+ exactly as each prior slice built on its predecessors; no pre-existing file
14
+ changed.
15
+
16
+ - `conventions/sdp-1.md`: content-addressed selective-disclosure convention —
17
+ hash-based salted field-level disclosure (content-blinding: field values
18
+ hidden, record digest / field names / count public; the ZK membership
19
+ family is disclosed as out of scope for a later convention). Field
20
+ commitments (one salted digest per field, total coverage, `sdp-1/field`
21
+ domain separation), convention-determined disclosure profile (closed
22
+ schema; predicate + opened set + currency, `format` always opened),
23
+ presentation (closed schema per shape), three predicates
24
+ (typed-existence / claimed-verdict / conforming-verdict with foreignness,
25
+ anterior-tolerance assessment, and sibling-aware tolerance-target
26
+ coherence inside the checked predicate), extent-bounded currency scan
27
+ (issuer rule, residues disclosed unconditionally), computational
28
+ hiding/soundness base stated (no trusted setup).
29
+ - `selective_disclosure.rb`: build/parse/verify for field commitments,
30
+ profile, presentation (refuse-not-coerce, canonical-serialization
31
+ equality everywhere); signature verification from the record DIGEST alone
32
+ via the unchanged map-1 §1.1 attestation signature — blinded verdicts
33
+ without record content; conforming-verdict refuses (never degrades) when
34
+ operator credential or rpr-1 §2.1 assessment material is missing;
35
+ currency scan with unestablished-vs-unretracted discipline.
36
+ - `bin/sdp_verify.rb`: offline verifier (commit / binding / presentation /
37
+ profile / currency / convention), exit-code discipline (0/1/2), strict
38
+ intake (delete_suffix, canonical numerals).
39
+ - `test/test_sdp_disclosure.rb`: 61 design-constraint assertions
40
+ (SDP-1..5), including crafted-record shape refusal, verdict-vocabulary
41
+ closure, sibling-target coherence (rpr-1 §2.1 pooling agreement),
42
+ hiding of withheld values across artifacts and error paths, and
43
+ khab/map/rpr non-interference (37/75/76/88 regression green).
44
+
45
+ Implementation review: 3 rounds, R3 4/6 APPROVE + executable-probe
46
+ personas 2/2, zero remaining P0/P1 (dispositions in docs/drafts/).
47
+
7
48
  ## [3.46.0] - 2026-07-22
8
49
 
9
50
  ### Synoptis — reproduction endorsement rpr-1 (AUD-L3 slice 1)
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "3.46.0"
2
+ VERSION = "3.47.0"
3
3
  CHANGELOG_URL = "https://github.com/masaomi/KairosChain_2026/blob/main/CHANGELOG.md"
4
4
  end
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # sdp_verify — offline verifier for sdp-1 selective-disclosure artifacts
5
+ # (SDP-1..5, aud_l4_selective_disclosure_design v0.3).
6
+ #
7
+ # Verifies with EXACTLY the disclosed trust base: the artifacts named on the
8
+ # command line plus the shipped sdp-1, rpr-1, and map-1 convention
9
+ # definitions. No registry, no network, no producer cooperation. (Authentic
10
+ # chain/log views are the caller's inputs; their integrity is the
11
+ # khab-1/map-1 surfaces' business.)
12
+ #
13
+ # Usage:
14
+ # sdp_verify.rb commit <record.json> [salts.json]
15
+ # builds the sdp-1 field-commitments auxiliary for a canonical record;
16
+ # prints the auxiliary record and (fresh or supplied) salts as JSON.
17
+ # sdp_verify.rb binding <aux.json> <record.json> <salts.json>
18
+ # checks the SDP-2 binding: every field digest and the record digest
19
+ # recompute from record + salts.
20
+ # sdp_verify.rb presentation <presentation.json> [operator_credential.json] [assessment.json]
21
+ # verifies a presentation. conforming-verdict REQUIRES both extras;
22
+ # assessment.json = {"targets":[...record strings...],
23
+ # "declarations":[{"tolerance":"...","position":N}...],
24
+ # "endorsement_position":N}.
25
+ # sdp_verify.rb profile <presentation.json>
26
+ # prints the disclosure profile and what it does/does not show.
27
+ # sdp_verify.rb currency <entries.json> <carrier_entry_hash> <extent>
28
+ # runs the sdp-1 §5 retraction scan over a supplied entry view.
29
+ # sdp_verify.rb convention
30
+ # prints the shipped sdp-1 convention digest.
31
+ #
32
+ # Exit status: 0 = VERIFIED/REPORT, 1 = REJECTED, 2 = usage / unresolvable.
33
+
34
+ require 'json'
35
+ require 'digest'
36
+ require_relative '../lib/synoptis/anchoring/entry'
37
+ require_relative '../lib/synoptis/anchoring/chain_credential'
38
+ require_relative '../lib/synoptis/anchoring/reproduction'
39
+ require_relative '../lib/synoptis/anchoring/selective_disclosure'
40
+
41
+ SD = Synoptis::Anchoring::SelectiveDisclosure
42
+ CRED = Synoptis::Anchoring::ChainCredential
43
+
44
+ def die(msg)
45
+ warn "sdp_verify: #{msg}"
46
+ exit 2
47
+ end
48
+
49
+ def reject(msg)
50
+ puts "REJECTED: #{msg}"
51
+ exit 1
52
+ end
53
+
54
+ # Read a record artifact: at most one trailing newline is tolerated (file
55
+ # convenience); any other surrounding bytes stay in the string and fail the
56
+ # canonical check downstream (refuse-not-coerce). delete_suffix, not chomp:
57
+ # chomp also swallows CRLF, which would coerce a non-canonical artifact.
58
+ def read_file(path)
59
+ File.read(path).delete_suffix("\n")
60
+ rescue SystemCallError => e
61
+ die "cannot read #{path}: #{e.message}"
62
+ end
63
+
64
+ def load_json(path, label)
65
+ parsed = JSON.parse(File.read(path))
66
+ die "#{path}: #{label} must be a JSON object or array, got #{parsed.class}" unless parsed.is_a?(Hash) || parsed.is_a?(Array)
67
+ parsed
68
+ rescue JSON::ParserError, SystemCallError => e
69
+ die "cannot read #{path}: #{e.message}"
70
+ end
71
+
72
+ def load_json_hash(path, label)
73
+ parsed = load_json(path, label)
74
+ die "#{path}: #{label} must be a JSON object, got #{parsed.class}" unless parsed.is_a?(Hash)
75
+ parsed
76
+ end
77
+
78
+ # Canonical base-10 numerals only: leading zeros are refused, not
79
+ # reinterpreted (a non-canonical numeral is a malformed input, exit 2).
80
+ def strict_int(value, label)
81
+ die "#{label} must be a canonical base-10 integer, got #{value.inspect}" unless value.is_a?(String) && value.match?(/\A(0|[1-9]\d*)\z/)
82
+ Integer(value, 10)
83
+ end
84
+
85
+ HEX64 = /\A[a-f0-9]{64}\z/
86
+
87
+ mode = ARGV.shift
88
+
89
+ case mode
90
+ when 'commit'
91
+ die 'usage: sdp_verify.rb commit <record.json> [salts.json]' unless (1..2).cover?(ARGV.size)
92
+ record = read_file(ARGV[0])
93
+ salts = ARGV[1] ? load_json_hash(ARGV[1], 'salts') : nil
94
+ built = begin
95
+ SD.build_field_commitments(record, salts: salts)
96
+ rescue SD::DisclosureError => e
97
+ reject e.message
98
+ end
99
+ puts JSON.pretty_generate(built)
100
+ warn 'NOTE: keep the salts private; each opened salt discloses exactly its field (sdp-1 §6).'
101
+
102
+ when 'binding'
103
+ die 'usage: sdp_verify.rb binding <aux.json> <record.json> <salts.json>' unless ARGV.size == 3
104
+ aux = read_file(ARGV[0])
105
+ record = read_file(ARGV[1])
106
+ salts = load_json_hash(ARGV[2], 'salts')
107
+ ok = begin
108
+ SD.verify_field_commitments(aux, record, salts)
109
+ rescue SD::DisclosureError => e
110
+ reject e.message
111
+ end
112
+ reject 'auxiliary is NOT checkably bound to the record (SDP-2: a bound-by-assertion auxiliary is a re-authoring)' unless ok
113
+ puts "VERIFIED: auxiliary is checkably bound to record #{Digest::SHA256.hexdigest(record)[0, 12]}… (total coverage, SDP-2)"
114
+
115
+ when 'presentation'
116
+ die 'usage: sdp_verify.rb presentation <presentation.json> [operator_credential.json] [assessment.json]' unless (1..3).cover?(ARGV.size)
117
+ pres = read_file(ARGV[0])
118
+ operator = ARGV[1] ? load_json_hash(ARGV[1], 'operator credential') : nil
119
+ assessment = ARGV[2] ? load_json_hash(ARGV[2], 'assessment material') : nil
120
+ report = begin
121
+ SD.verify_presentation(pres, operator_credential: operator, assessment: assessment)
122
+ rescue SD::DisclosureError, CRED::CredentialError => e
123
+ reject e.message
124
+ end
125
+ unless report[:valid]
126
+ puts "REJECTED: presentation does not verify (predicate #{report[:predicate]})"
127
+ report[:failures].each { |f| puts " - #{f}" }
128
+ exit 1
129
+ end
130
+ puts "VERIFIED: #{report[:predicate]} over committed record #{report[:record_sha256][0, 12]}…"
131
+ report[:opened].each { |n, v| puts " opened #{n} = #{v.inspect}" }
132
+ report[:notes].each { |n| puts " NOTE: #{n}" }
133
+ puts 'NOTE: soundness = sha256 collision resistance + Ed25519, no setup; hiding is computational, content-only (SDP-5, sdp-1 §6).'
134
+
135
+ when 'profile'
136
+ die 'usage: sdp_verify.rb profile <presentation.json>' unless ARGV.size == 1
137
+ pres = read_file(ARGV[0])
138
+ p = begin
139
+ SD.parse_presentation!(pres)
140
+ rescue SD::DisclosureError => e
141
+ reject e.message
142
+ end
143
+ profile = p['profile']
144
+ puts "profile (meaning fixed by sdp-1 §2, never producer gloss — SDP-4):"
145
+ puts " predicate: #{profile['predicate']}"
146
+ puts " opened: #{profile['opened'].join(', ')}"
147
+ puts " withheld: every other field of the referenced record (values only; names and count are public)"
148
+ puts " currency: #{profile['currency']}"
149
+ puts ' shows: existence and the opened values of ONE committed record'
150
+ puts ' never: non-existence, uniqueness, sibling records, contrary verdicts, producer selection (SDP-3)'
151
+
152
+ when 'currency'
153
+ die 'usage: sdp_verify.rb currency <entries.json> <carrier_entry_hash> <extent>' unless ARGV.size == 3
154
+ entries = load_json(ARGV[0], 'entries')
155
+ die "#{ARGV[0]}: entries must be a JSON array" unless entries.is_a?(Array)
156
+ carrier = ARGV[1].to_s
157
+ die 'carrier_entry_hash must be 64-char lowercase hex' unless carrier.match?(HEX64)
158
+ extent = strict_int(ARGV[2], 'extent')
159
+ scan = begin
160
+ SD.scan_currency(entries: entries, carrier_entry_hash: carrier, extent: extent)
161
+ rescue SD::DisclosureError => e
162
+ reject e.message
163
+ end
164
+ puts "REPORT: #{scan[:status]} (scanned extent #{scan[:scanned_extent]})"
165
+ puts " hits (positions): #{scan[:hits].join(', ')}" if scan[:hits]&.any?
166
+ puts " NOTE: #{scan[:note]}"
167
+ exit(scan[:status] == 'retracted' ? 1 : 0)
168
+
169
+ when 'convention'
170
+ puts "sdp-1 convention sha256: #{SD.convention_sha256}"
171
+
172
+ else
173
+ die 'usage: sdp_verify.rb commit|binding|presentation|profile|currency|convention …'
174
+ end
@@ -0,0 +1,182 @@
1
+ # sdp-1 — KairosChain Selective Disclosure Convention, version 1
2
+
3
+ Status: committed verification convention (SDP-1..5 of
4
+ aud_l4_selective_disclosure_design v0.3, FROZEN). The SHA-256 over this file's
5
+ raw bytes is the convention integrity digest; every artifact that names
6
+ `sdp-1` commits it as its convention reference. A verifier holding a
7
+ definition whose digest does not match the committed one MUST treat the
8
+ artifact's convention as unresolvable and refuse to verify under it. Any
9
+ change to this convention is a new identifier (`sdp-2`, ...); this file is
10
+ never edited in place.
11
+ sdp-1 builds on khab-1 (record commitments, cumulative commitments, proofs),
12
+ map-1 (credentials, §1.1 attestation signatures, types, retraction), and
13
+ rpr-1 (endorsement records) and modifies none of them: every khab-1/map-1/
14
+ rpr-1 artifact is valid, and verifiable by its own procedure, with or without
15
+ any sdp-1 artifact present (SDP-2).
16
+
17
+ All record literals below are canonical JSON (keys sorted recursively,
18
+ `JSON.generate` compact form). A record is valid only in its canonical
19
+ serialization with exactly the fields shown — a non-canonical or extra-field
20
+ record is not an sdp-1 artifact and is ignored as noise (map-1 §4 precedent).
21
+
22
+ ## 0. Scope and disclosed narrowness
23
+
24
+ sdp-1 realizes the mechanism family "hash-based salted field-level selective
25
+ disclosure": it blinds the *values* of fields of a committed canonical-JSON
26
+ record while the record's committed digest, its field *names*, and its field
27
+ *count* stay public. It does NOT blind which committed record an assertion
28
+ concerns: the AUD-L4 *membership* predicate family (showing that some record
29
+ is a member without revealing which) requires a zero-knowledge proving
30
+ system and is deliberately outside sdp-1 — a later convention covers it.
31
+ This narrowness is disclosed, not hidden (rpr-1 bit-identity precedent).
32
+ Because a record's committed digest is revealed, the khab-1 record
33
+ commitment IS that digest (khab-1 §1), so khab-1 inclusion and consistency
34
+ proofs over the referenced record apply unchanged, and the open-level
35
+ selection and currency reads (SDP-3) remain available to the verifier.
36
+
37
+ ## 1. Field commitments (SDP-2 auxiliary, checkably bound)
38
+
39
+ {"fields":{"<name>":"<64-hex>",...},"format":"sdp-1/field-commitments",
40
+ "record_sha256":"<64-hex>"}
41
+
42
+ `record_sha256` is the SHA-256 of the target record string (= its khab-1
43
+ record commitment). `fields` carries one entry per top-level field of the
44
+ target record — coverage is total, so the auxiliary determines exactly one
45
+ record shape and an omitted field cannot be hidden by omission. Field names
46
+ match `[a-z0-9_]+`. Each field digest is the SHA-256 of the UTF-8 bytes of:
47
+
48
+ sdp-1/field|<salt>|<name>|<canonical JSON of the value>
49
+
50
+ where `<salt>` is 32-char lowercase hex (16 random bytes, fresh per field
51
+ per auxiliary). The `sdp-1/field` domain prefix is role separation (MPR-3
52
+ register): a field digest cannot verify as a record commitment or vice
53
+ versa. The auxiliary is committed as an ordinary internal-chain record
54
+ alongside its target; both records' membership and order are khab-1's
55
+ business, unchanged.
56
+
57
+ Checkable binding (SDP-2): a holder of the target record and the salts can
58
+ recompute `record_sha256` and every field digest; the auxiliary commits the
59
+ same content the record commits, or the recomputation fails. An auxiliary
60
+ whose digests do not recompute is not a conforming sdp-1 artifact. Residue
61
+ disclosed: binding checkability is available to holders of the record and
62
+ salts (the producer, and anyone the producer opens to); a third party holds
63
+ the binding as committed material whose consistency is attested by the
64
+ recomputations of others — the MPR-4 production/verification asymmetry.
65
+
66
+ ## 2. Disclosure profile (SDP-4, closed schema)
67
+
68
+ {"currency":"scan-checkable","format":"sdp-1/profile",
69
+ "opened":["format","verdict"],"predicate":"claimed-verdict"}
70
+
71
+ `predicate` is one of `typed-existence` | `claimed-verdict` |
72
+ `conforming-verdict`. `currency` is one of `scan-checkable` |
73
+ `unestablished` (SDP-3: which currency reading the presentation supports is
74
+ declared, never implied). `opened` is the sorted, duplicate-free list of
75
+ opened field names and MUST include `format` (the record's format field is
76
+ always opened, so the closed schema of the referenced record kind is
77
+ readable and coverage is checkable against it). The schema is closed: no
78
+ other fields exist, so a profile cannot carry producer gloss — a profile
79
+ means what this section says a profile of its form means (SDP-4 pinning),
80
+ and a presentation's profile is checked against its actual opened set, so a
81
+ profile that overstates or understates what is opened fails verification
82
+ (statement-determining, SDP-4).
83
+
84
+ What every sdp-1 profile discloses by construction (SDP-3): the proof shows
85
+ the named predicate over the named committed record and withholds the values
86
+ of every field not listed in `opened`; it shows nothing about other records,
87
+ contrary verdicts, or the producer's selection among presentable records.
88
+
89
+ ## 3. Presentation (offline artifact, never committed)
90
+
91
+ base fields, always present:
92
+
93
+ {"aux_record":"<field-commitments record string>",
94
+ "format":"sdp-1/presentation",
95
+ "opened":{"<name>":{"salt":"<32-hex>","value":<JSON value>},...},
96
+ "profile":{...profile object...}}
97
+
98
+ additionally, exactly when `profile.predicate` is `claimed-verdict` or
99
+ `conforming-verdict`: `"credential"` (the endorser's map-1 credential
100
+ object) and `"signature"` (128-hex, the map-1 §1.1 attestation signature
101
+ over the referenced endorsement record). Additionally, exactly when
102
+ `profile.currency` is `scan-checkable`: `"carrier_entry_hash"` (64-hex, the
103
+ anchor-log entry that carried the referenced record's attestation — the
104
+ producer's disclosure that makes the retraction scan runnable). The schema
105
+ is closed per shape (rpr-1 per-mode precedent).
106
+
107
+ `opened` keys must equal `profile.opened` exactly. Each opened field
108
+ verifies by recomputing §1's field digest from `salt`, the name, and the
109
+ canonical JSON of `value` against the auxiliary's committed digest.
110
+
111
+ ## 4. Predicates (SDP-1 bounds)
112
+
113
+ - `typed-existence`: a committed record of the opened `format` exists with
114
+ digest `record_sha256`. Membership in an anchored state is shown, when
115
+ wanted, by a khab-1 inclusion proof over `record_sha256` — unchanged, not
116
+ part of the presentation.
117
+ - `claimed-verdict`: the opened `format` must be `rpr-1/endorsement` and
118
+ `verdict` must be opened. The signature verifies under the presented
119
+ credential over the signing string
120
+
121
+ map-1/attestation|<credential digest>|<record_sha256>
122
+
123
+ which requires NO record content (map-1 §1.1 commits the payload by
124
+ digest). The claim is exactly: this credential's holder claimed this
125
+ verdict in this committed endorsement — the weaker predicate under its
126
+ own name (SDP-1 face/substance rule). No foreignness, anteriority, or
127
+ conformance is asserted.
128
+ - `conforming-verdict`: `claimed-verdict`, and additionally
129
+ `adjudication_mode`, `target_sha256`, and `tolerance_sha256` are opened
130
+ (plus `procedure_sha256` exactly when the opened mode is `procedure`),
131
+ and verification REQUIRES the operator credential (foreignness: endorser
132
+ credential digest ≠ operator credential digest, rpr-1 §3) and the rpr-1
133
+ §2.1 declaration-set material (targets, declarations with positions, the
134
+ endorsement's committed position); the invoked tolerance must assess as
135
+ conforming, and it must be bound to the endorsement's opened target or to
136
+ a sibling target sharing its committed computation identification (the
137
+ rpr-1 §2.1 pooling rule: a sibling menu is one menu; a tolerance bound to
138
+ an unrelated computation fails), decided from the supplied target records.
139
+ Where the material is not supplied, or the coherence is undecidable in the
140
+ supplied view, verification fails — refuse, not degrade (SDP-1 upward
141
+ bound: the open form's conformance conditions are inside the checked
142
+ predicate, never alongside it).
143
+
144
+ ## 5. Currency scan (SDP-3)
145
+
146
+ Given a view of anchor-log entries (each with `entry_hash`,
147
+ `attestation_type`, `depositor`, `position`, and retraction `metadata`), the
148
+ scan reports whether a `retraction` entry from the carrier's own depositor
149
+ (map-1 §3 issuer rule) targets `carrier_entry_hash` at a committed position
150
+ at or before a named extent. The verdict is `retracted` / `unretracted` up
151
+ to that extent, or `unestablished` where the carrier entry — or its
152
+ depositor, without which the issuer rule is undecidable — is not in the
153
+ supplied view. Duplicate views of one committed entry are one entry.
154
+ Same-issuer retractions beyond the extent or without a decidable position,
155
+ and non-issuer entries targeting the carrier (which retract nothing), are
156
+ disclosed as residue lines, never silently dropped. `unretracted` speaks
157
+ only to the scanned view and extent — absence beyond them proves nothing
158
+ (MPR-9 register). A profile declaring `currency: "unestablished"` supports
159
+ no scan and says so on its face.
160
+
161
+ ## 6. Hiding and soundness base (SDP-1/SDP-5)
162
+
163
+ Hiding is computational and content-only: a withheld value is hidden exactly
164
+ as far as its field's salt is secret and sha256 preimage resistance holds —
165
+ 16-byte random salts make guess-and-confirm infeasible even for low-entropy
166
+ values (the MPR-2 caveat is answered by the salt, and returns in full if a
167
+ salt is reused or leaks). What sdp-1 never hides: the record's committed
168
+ digest, field names and count, the profile, the producer's credential where
169
+ presented, and the fact of presentation itself — a presentation's existence,
170
+ timing, and provenance are outside any profile's promise (SDP-1). Soundness
171
+ rests on SHA-256 collision resistance and Ed25519 unforgeability only; there
172
+ is no setup to trust (SDP-5: transparent, stated rather than implied).
173
+
174
+ ## 7. Verification procedure and trust base
175
+
176
+ All sdp-1 verification needs only: the artifacts named above, this
177
+ definition, the map-1 definition (credentials, signatures, retraction), the
178
+ rpr-1 definition (for verdict predicates), and authentic views of the
179
+ logs/chains the artifacts reference. No registry, no network, no producer
180
+ cooperation for verification — production of presentations, like production
181
+ of proofs, remains the producer's act (MPR-4 asymmetry), and the producer's
182
+ selection among presentable records is invisible by construction (SDP-3).