confium 0.6.3-aarch64-linux → 0.7.1-aarch64-linux

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: e7c4d93f65610ac51b8971063f71aacca6db68894fd069518d2f44d04305ea18
4
- data.tar.gz: 4e48317b7168323cf3bb4f10e5ecd5346b4fe47417a8aa75460842e4053db9ab
3
+ metadata.gz: 7cab2b2ace3e324582536762cd815c779eb2e2d4beb2aa8b9d14a96b217e6df6
4
+ data.tar.gz: de2dfb7bf71bfe5b54744f3e14a0ffaa12d63f5a32c6baa39ff3de1fce9c801c
5
5
  SHA512:
6
- metadata.gz: 2fdf87bc54d8521635ad2ab5b08aa23b7236ea396b5422f49a1fc0b5bb32d4b272029142b297848824ab31ad16af4b64ab1f2fcfcffae12743ac2daafdbbbe15
7
- data.tar.gz: 5342fd696b0768166d62a2325259ce6f29e089eb36b075fa7b96f774827d0ab5c9f2b50770cb4c0e016d43870d915e6fee8600b978f18f38ed713ad288a97b59
6
+ metadata.gz: 252ee6c69983a91d316b3d45c7a8f5cb3632494b6962bcce98202378c1860f168ae09f66fa6d36d1c516f6c683a21ea919d44422a7261df04a6478b198f065d2
7
+ data.tar.gz: ff7af357dc2d7f35f568ebd42fd0dca670312ef68953bf91f4c74108e9c6f7336ccf91a9dc9c802e4cb7f18208569ea6b9cffde9866a448ee8ecff2c1d153d62
data/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.1] — UNRELEASED (code on main; release on the owner's tag)
4
+
5
+ ### Added
6
+
7
+ - `Confium::Transparency::OTS` is now the real OpenTimestamps
8
+ wire-protocol binding (confium-transparency 0.9): `OTS::Client#stamp`
9
+ POSTs the 32-byte digest to the calendar pool and returns a `Proof`
10
+ carrying the parsed partial proof; `#upgrade` polls for a confirmed
11
+ one; `Proof#verify` replays the op tree and classifies attestations
12
+ (pending URIs, Bitcoin/Litecoin heights, `anchored`). Module-level
13
+ `OTS.stamp`/`verify`/`upgrade` over the default calendar pool.
14
+ Network failures raise (`IOError`/`ParseError`) — the stub-era
15
+ silent nil is gone.
16
+ - The calendar round trip releases the GVL (direct
17
+ `rb_thread_call_without_gvl` trampoline — magnus 0.8 does not wrap
18
+ it), so a slow calendar never freezes the VM.
19
+
20
+ ### Fixed
21
+
22
+ - The workspace's OTS file magic was missing its final two salt bytes
23
+ (29 vs 31; shifted every parse offset for real .ots files) — caught
24
+ by this binding's cross-checked specs, fixed in confium-transparency
25
+ v0.9.1.
26
+
27
+ ## [0.7.0] — 2026-09-07
28
+
29
+ ### Added
30
+
31
+ - `Confium::Transport::SignerClient` / `CoordinatorServer` —
32
+ coordinator sessions over any registry transport the extension
33
+ links, addressed by URL: `tcp://host:port` for local/trusted
34
+ networks, `noise://host:port` for Noise_XX
35
+ (`Noise_XX_25519_ChaChaPoly_BLAKE2s`) encrypted sessions.
36
+ `noise://` URLs take `key=<hex>` (local static private key;
37
+ ephemeral and trust-on-first-use when omitted) and `pinned=<hex>`
38
+ (SHA-256 fingerprint of the expected peer static key — the
39
+ handshake aborts on mismatch). The handshake carries a 10-second
40
+ deadline so a non-Noise peer fails fast instead of hanging.
41
+ `SignerClient` exposes `#register`, `#create_session`,
42
+ `#submit_commitment`, `#submit_share` (returns the aggregated
43
+ signature once the threshold is met, else nil);
44
+ `CoordinatorServer.new(url)` serves any linked scheme for tests
45
+ and single-process deployments.
46
+
47
+ ### Changed
48
+
49
+ - **BREAKING**: `Confium::Net` is `Confium::Transport`. Defining
50
+ `Confium::Net` shadowed Ruby stdlib `Net` for every constant
51
+ lookup under the `Confium` namespace — `Confium::Audit::OtlpSink`'s
52
+ `Net::HTTP` resolved to `Confium::Net::HTTP` and raised
53
+ `NameError`. No prior release shipped the `Net` names.
54
+
55
+ ## [0.6.3] — 2026-08-26
56
+
57
+ ### Added
58
+
59
+ - `Confium::TC::Session` — per-party threshold protocol sessions
60
+ over confium-tc-core 0.4: each signer process runs its own
61
+ session (`"FROST-ed25519-dkg"` for distributed key generation,
62
+ `"FROST-ed25519"` for signing with the DKG share and message) and
63
+ exchanges only `round_step` messages — the share never leaves the
64
+ process. `#round_step(incoming)` returns
65
+ `{ "outgoing" => [...], "complete" => bool }`; the completed DKG
66
+ session's `#result` is the party's share blob, the signing
67
+ session's `#result` an RFC 8032 Ed25519 signature verifiable under
68
+ the group public key.
69
+
3
70
  ## [0.6.2] — 2026-08-26
4
71
 
5
72
  ### Added
data/Cargo.lock CHANGED
@@ -135,6 +135,15 @@ dependencies = [
135
135
  "wyz",
136
136
  ]
137
137
 
138
+ [[package]]
139
+ name = "blake2"
140
+ version = "0.10.6"
141
+ source = "registry+https://github.com/rust-lang/crates.io-index"
142
+ checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
143
+ dependencies = [
144
+ "digest 0.10.7",
145
+ ]
146
+
138
147
  [[package]]
139
148
  name = "block-buffer"
140
149
  version = "0.10.4"
@@ -207,6 +216,30 @@ version = "1.0.4"
207
216
  source = "registry+https://github.com/rust-lang/crates.io-index"
208
217
  checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
209
218
 
219
+ [[package]]
220
+ name = "chacha20"
221
+ version = "0.9.1"
222
+ source = "registry+https://github.com/rust-lang/crates.io-index"
223
+ checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
224
+ dependencies = [
225
+ "cfg-if",
226
+ "cipher",
227
+ "cpufeatures 0.2.17",
228
+ ]
229
+
230
+ [[package]]
231
+ name = "chacha20poly1305"
232
+ version = "0.10.1"
233
+ source = "registry+https://github.com/rust-lang/crates.io-index"
234
+ checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
235
+ dependencies = [
236
+ "aead",
237
+ "chacha20",
238
+ "cipher",
239
+ "poly1305",
240
+ "zeroize",
241
+ ]
242
+
210
243
  [[package]]
211
244
  name = "chrono"
212
245
  version = "0.4.45"
@@ -229,6 +262,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
229
262
  dependencies = [
230
263
  "crypto-common 0.1.7",
231
264
  "inout",
265
+ "zeroize",
232
266
  ]
233
267
 
234
268
  [[package]]
@@ -301,7 +335,7 @@ checksum = "e8c96d4d5997726cf0eb794410e3e8bbce839cfba9c4a32e26ede0c076b02e64"
301
335
  dependencies = [
302
336
  "chrono",
303
337
  "confium-api",
304
- "confium-net",
338
+ "confium-net 0.3.0",
305
339
  "confium-store 0.3.0",
306
340
  "confium-tc-core 0.3.0",
307
341
  "data-encoding",
@@ -321,6 +355,26 @@ dependencies = [
321
355
  "zeroize",
322
356
  ]
323
357
 
358
+ [[package]]
359
+ name = "confium-coordinator"
360
+ version = "0.8.5"
361
+ source = "registry+https://github.com/rust-lang/crates.io-index"
362
+ checksum = "52f49eae3301b6f1f2f36b2eb66d0fdd863bcecb1dc18b51ec51e5f8d1bb9dc3"
363
+ dependencies = [
364
+ "chrono",
365
+ "confium-net 0.8.5",
366
+ "getrandom 0.4.3",
367
+ "hex",
368
+ "hmac 0.13.0",
369
+ "p256 0.14.0",
370
+ "rand_core 0.6.4",
371
+ "serde",
372
+ "serde_json",
373
+ "sha2 0.11.0",
374
+ "thiserror 2.0.20",
375
+ "tracing",
376
+ ]
377
+
324
378
  [[package]]
325
379
  name = "confium-core"
326
380
  version = "0.2.0"
@@ -413,6 +467,44 @@ dependencies = [
413
467
  "url",
414
468
  ]
415
469
 
470
+ [[package]]
471
+ name = "confium-net"
472
+ version = "0.8.5"
473
+ source = "registry+https://github.com/rust-lang/crates.io-index"
474
+ checksum = "2bd7098e54033a09b1f6a4ebd0c0f54d6c44da8f46cfdff7ae156895f1083fc6"
475
+ dependencies = [
476
+ "inventory",
477
+ "snafu 0.9.2",
478
+ "url",
479
+ ]
480
+
481
+ [[package]]
482
+ name = "confium-net-noise"
483
+ version = "0.8.5"
484
+ source = "registry+https://github.com/rust-lang/crates.io-index"
485
+ checksum = "213e90ce6daa40d1ec92d8e524276744a07f027c453bd32815f80c29ba947237"
486
+ dependencies = [
487
+ "confium-net 0.8.5",
488
+ "inventory",
489
+ "sha2 0.11.0",
490
+ "snafu 0.9.2",
491
+ "snow",
492
+ "url",
493
+ "x25519-dalek",
494
+ ]
495
+
496
+ [[package]]
497
+ name = "confium-net-tcp"
498
+ version = "0.8.3"
499
+ source = "registry+https://github.com/rust-lang/crates.io-index"
500
+ checksum = "1b80e3d692ed5328a72e754a0f73d81f6c8fde3714d05fc0be1953f657e05f76"
501
+ dependencies = [
502
+ "confium-net 0.8.5",
503
+ "inventory",
504
+ "snafu 0.9.2",
505
+ "url",
506
+ ]
507
+
416
508
  [[package]]
417
509
  name = "confium-observability"
418
510
  version = "0.3.0"
@@ -493,8 +585,8 @@ checksum = "3dd7d4965aef12324cb76d397294c317b83b774de029f1d37b387cf54ba9593c"
493
585
  dependencies = [
494
586
  "chrono",
495
587
  "confium-api",
496
- "confium-coordinator",
497
- "confium-net",
588
+ "confium-coordinator 0.3.0",
589
+ "confium-net 0.3.0",
498
590
  "confium-store 0.3.0",
499
591
  "confium-tc-keys",
500
592
  "data-encoding",
@@ -566,7 +658,7 @@ checksum = "add3e15337ce81944f78c9ce844d870a081cbe91506a85b9a5c4e4c0da983771"
566
658
  dependencies = [
567
659
  "chrono",
568
660
  "confium-api",
569
- "confium-net",
661
+ "confium-net 0.3.0",
570
662
  "confium-store 0.3.0",
571
663
  "data-encoding",
572
664
  "hex",
@@ -683,17 +775,18 @@ dependencies = [
683
775
 
684
776
  [[package]]
685
777
  name = "confium-transparency"
686
- version = "0.4.0"
778
+ version = "0.9.1"
687
779
  source = "registry+https://github.com/rust-lang/crates.io-index"
688
- checksum = "874cdab3dded22c22980d3a5b1f802301739368a32e9196bc645600329c07dcf"
780
+ checksum = "b4ec484381b582f508f774babbc1bf1b4a98c6aadd43cde806952c6e416b62ca"
689
781
  dependencies = [
690
782
  "chrono",
691
- "data-encoding",
783
+ "hex",
692
784
  "serde",
693
785
  "serde_json",
694
- "sha2 0.10.9",
695
- "snafu 0.8.9",
696
- "thiserror 1.0.69",
786
+ "sha2 0.11.0",
787
+ "subtle",
788
+ "thiserror 2.0.20",
789
+ "ureq",
697
790
  ]
698
791
 
699
792
  [[package]]
@@ -703,10 +796,13 @@ dependencies = [
703
796
  "chrono",
704
797
  "confium-attributes",
705
798
  "confium-composite",
799
+ "confium-coordinator 0.8.5",
706
800
  "confium-core",
707
801
  "confium-crypto-vss",
708
802
  "confium-crypto-zk",
709
803
  "confium-deployment",
804
+ "confium-net-noise",
805
+ "confium-net-tcp",
710
806
  "confium-observability",
711
807
  "confium-pki",
712
808
  "confium-privacy",
@@ -1215,6 +1311,18 @@ dependencies = [
1215
1311
  "wasi",
1216
1312
  ]
1217
1313
 
1314
+ [[package]]
1315
+ name = "getrandom"
1316
+ version = "0.3.4"
1317
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1318
+ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
1319
+ dependencies = [
1320
+ "cfg-if",
1321
+ "libc",
1322
+ "r-efi 5.3.0",
1323
+ "wasip2",
1324
+ ]
1325
+
1218
1326
  [[package]]
1219
1327
  name = "getrandom"
1220
1328
  version = "0.4.3"
@@ -1223,7 +1331,7 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
1223
1331
  dependencies = [
1224
1332
  "cfg-if",
1225
1333
  "libc",
1226
- "r-efi",
1334
+ "r-efi 6.0.0",
1227
1335
  "rand_core 0.10.1",
1228
1336
  ]
1229
1337
 
@@ -1785,6 +1893,17 @@ version = "0.3.34"
1785
1893
  source = "registry+https://github.com/rust-lang/crates.io-index"
1786
1894
  checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
1787
1895
 
1896
+ [[package]]
1897
+ name = "poly1305"
1898
+ version = "0.8.0"
1899
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1900
+ checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
1901
+ dependencies = [
1902
+ "cpufeatures 0.2.17",
1903
+ "opaque-debug",
1904
+ "universal-hash",
1905
+ ]
1906
+
1788
1907
  [[package]]
1789
1908
  name = "polyval"
1790
1909
  version = "0.6.2"
@@ -1879,6 +1998,12 @@ dependencies = [
1879
1998
  "proc-macro2",
1880
1999
  ]
1881
2000
 
2001
+ [[package]]
2002
+ name = "r-efi"
2003
+ version = "5.3.0"
2004
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2005
+ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
2006
+
1882
2007
  [[package]]
1883
2008
  name = "r-efi"
1884
2009
  version = "6.0.0"
@@ -2348,6 +2473,23 @@ dependencies = [
2348
2473
  "syn 2.0.119",
2349
2474
  ]
2350
2475
 
2476
+ [[package]]
2477
+ name = "snow"
2478
+ version = "0.10.0"
2479
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2480
+ checksum = "599b506ccc4aff8cf7844bc42cf783009a434c1e26c964432560fb6d6ad02d82"
2481
+ dependencies = [
2482
+ "aes-gcm",
2483
+ "blake2",
2484
+ "chacha20poly1305",
2485
+ "curve25519-dalek",
2486
+ "getrandom 0.3.4",
2487
+ "ring",
2488
+ "rustc_version",
2489
+ "sha2 0.10.9",
2490
+ "subtle",
2491
+ ]
2492
+
2351
2493
  [[package]]
2352
2494
  name = "spki"
2353
2495
  version = "0.7.3"
@@ -2666,6 +2808,15 @@ version = "0.11.1+wasi-snapshot-preview1"
2666
2808
  source = "registry+https://github.com/rust-lang/crates.io-index"
2667
2809
  checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
2668
2810
 
2811
+ [[package]]
2812
+ name = "wasip2"
2813
+ version = "1.0.4+wasi-0.2.12"
2814
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2815
+ checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
2816
+ dependencies = [
2817
+ "wit-bindgen",
2818
+ ]
2819
+
2669
2820
  [[package]]
2670
2821
  name = "wasm-bindgen"
2671
2822
  version = "0.2.126"
@@ -2870,6 +3021,12 @@ dependencies = [
2870
3021
  "memchr",
2871
3022
  ]
2872
3023
 
3024
+ [[package]]
3025
+ name = "wit-bindgen"
3026
+ version = "0.57.1"
3027
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3028
+ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
3029
+
2873
3030
  [[package]]
2874
3031
  name = "wnaf"
2875
3032
  version = "0.14.0"
@@ -2896,6 +3053,18 @@ dependencies = [
2896
3053
  "tap",
2897
3054
  ]
2898
3055
 
3056
+ [[package]]
3057
+ name = "x25519-dalek"
3058
+ version = "2.0.1"
3059
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3060
+ checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
3061
+ dependencies = [
3062
+ "curve25519-dalek",
3063
+ "rand_core 0.6.4",
3064
+ "serde",
3065
+ "zeroize",
3066
+ ]
3067
+
2899
3068
  [[package]]
2900
3069
  name = "x509-cert"
2901
3070
  version = "0.3.0"
data/README.adoc CHANGED
@@ -18,7 +18,7 @@ Add to your Gemfile:
18
18
 
19
19
  [source,ruby]
20
20
  ----
21
- gem "confium", "~> 0.3"
21
+ gem "confium", "~> 0.7"
22
22
  ----
23
23
 
24
24
  Or install directly:
@@ -78,18 +78,38 @@ kp = Confium::TC::FrostP256.generate_keypair
78
78
  shares = Confium::TC::FrostP256.split_secret(kp["private_key"], 3, 5)
79
79
  recovered = Confium::TC::FrostP256.recover_secret(shares.first(3).map { |s| { "x" => s.x, "y" => s.y_bytes } })
80
80
  recovered == kp["private_key"] # => true
81
+
82
+ # Distributed key generation + 2-of-3 FROST-ed25519 signing (each party
83
+ # holds its own Confium::TC::Session and only exchanges round messages)
84
+ parties = %w[alice bob carol]
85
+ sessions = parties.each_with_index.map do |id, i|
86
+ Confium::TC::Session.new("FROST-ed25519-dkg", parties: parties, threshold: 2, this_party_idx: i)
87
+ end
88
+ # run rounds: session.round_step(messages_in) -> {"outgoing" => [...], "complete" => bool}
89
+ # broadcast "outgoing" payloads between sessions until every session is complete
90
+ dkg_share = sessions.first.result # this party's share (embeds the group public key)
91
+
92
+ signers = sessions.first(2).map.with_index do |s, i|
93
+ Confium::TC::Session.new("FROST-ed25519",
94
+ parties: parties.first(2), threshold: 2, this_party_idx: i,
95
+ local_share: dkg_share, message: "authentic message")
96
+ end
97
+ # run rounds as above; the completed session's #result is an RFC 8032
98
+ # Ed25519 signature verifiable under the group public key
81
99
  ----
82
100
 
83
- == API surface (v0.3)
101
+ == API surface (v0.7)
84
102
 
85
103
  === `Confium::Transparency`
86
104
  - `MerkleTree.new` / `#append(artifact_hash)` / `#root` / `#length` / `#empty?` / `#inclusion_proof(seq)`
87
105
  - `InclusionProof#sequence` / `#steps` / `#verify(root)`
106
+ - `Ots.stamp(hash)` / `Ots.verify(proof)` / `Ots.upgrade(proof)` — real OpenTimestamps anchoring over the wire protocol (calendar HTTP, servers tried in order; the network round trip releases the GVL). `Ots::Client.new(servers)` for a custom pool; `Ots::Proof#verify` replays the op tree and classifies attestations. Network failures raise — there is no silent nil
88
107
 
89
108
  === `Confium::Composite` — PQ migration
90
109
  - `.generate_ed25519_keypair` → `{ private_key:, public_key: }`
91
110
  - `.sign_ed25519(private_key, message)` → component Hash
92
- - `Signature.new(components)` / `#verify(message)` / `#component_count` / `#algorithms`
111
+ - `Signature.new(components)` / `#verify(message)` / `#component_count` / `#algorithms` / `#to_json`
112
+ - `.from_json(json)` / `.components_to_json(components)` / `.canonical_json(json, data)`
93
113
  - `VerificationResult#all_verified?` / `#per_component`
94
114
 
95
115
  === `Confium::Attributes` — threshold policy DSL
@@ -99,11 +119,14 @@ recovered == kp["private_key"] # => true
99
119
  - DSL: `min_count("attr", n)`, `min_distinct("attr", n)`, `any("attr")`, `all("attr")`, `none("attr")`, `and(...)`, `or(...)`, `not(p)`
100
120
 
101
121
  === `Confium::PKI`
102
- - `Certificate.from_der(bytes)` / `.from_pem(str)` / `#to_der` / `#to_pem` / `#fingerprint_sha256` / `#serial_hex` / `#not_before` / `#not_after` / `#valid_at?(iso8601)` / `#public_key_bytes`
122
+ - `Certificate.from_der(bytes)` / `.from_pem(str)` / `#to_der` / `#to_pem` / `#fingerprint_sha256` / `#serial_hex` / `#not_before` / `#not_after` / `#valid_at?(iso8601)` / `#public_key_bytes`; DER parse failures carry a byte `offset` in the error details
123
+ - `CertificateBuilder` / `CMS::SignedDataBuilder` — build certificates and signed data in Ruby
124
+ - `PathValidator.validate(leaf, intermediates, root, now_iso8601 = nil)` → `PathValidationResult` (chain validation leaf → root at a point in time)
103
125
  - `CSR.from_der` / `.from_pem` / `#to_der` / `#to_pem`
104
126
  - `CMS::SignedData.from_json` / `#to_json` / `#signer_count` / `#content_type` / `#content` / `#certificate_count` / `#certificate_at(i)`
105
127
  - `CMS::Content#bytes` / `#length`
106
128
  - `XMLDSig.canonicalize(xml)` / `.canonicalize_exclusive(xml)` (Canonical XML RFC 3076 + Exclusive C14N)
129
+ - `Cnml` — institutional certificate workflow helpers
107
130
 
108
131
  === `Confium::Identity` — actor roles
109
132
  - `.actor_types` → `["manufacturer", "testing_lab", "issuing_authority_officer", "biml_director", "quorum_coordinator", "verifier"]`
@@ -123,6 +146,51 @@ recovered == kp["private_key"] # => true
123
146
  - `.partial_decrypt(party_index, share_bytes, ciphertext)` → `{ party_index:, bytes: }`
124
147
  - `.aggregate_partials(partials, threshold, ciphertext)` → shared_secret bytes
125
148
 
149
+ === `Confium::TC::Cmp20` / `Confium::TC::Gg18` — threshold ECDSA protocols
150
+ - `.keygen(threshold, parties)` → `{ public_key, shares }`
151
+ - `.sign(shares, public_key, message)` → DER ECDSA signature
152
+
153
+ === `Confium::TC::Session` — per-party threshold sessions (real FROST)
154
+ - `Session.new(scheme, parties:, threshold:, this_party_idx:, local_share: nil, message: nil)` — `"FROST-ed25519-dkg"` for distributed key generation, `"FROST-ed25519"` for signing (pass the DKG share and the message)
155
+ - `#scheme_name` / `#threshold` / `#party_count` / `#this_party_idx` / `#round` / `#complete?`
156
+ - `#round_step(messages)` → `{ "outgoing" => [{from, to, round, payload}...], "complete" => bool }` — feed each round's incoming messages, broadcast the outgoing ones
157
+ - `#result` — after DKG: share blob (group public key + party share); after signing: RFC 8032 Ed25519 signature
158
+
159
+ === `Confium::TC::Coordinator` — quorum signing orchestration
160
+ - `Coordinator.new(quorum_id:)` / `#create_session(message:, threshold:, scheme: "CMP20-ECDSA-P256")` / `#submit_commitment` / `#submit_share` / `#aggregate` / `#session_state`
161
+ - `SigningSession#add_commitment` / `#add_share` / `#threshold_met?` / `#aggregate` — the seam every transport adapts to
162
+ - `NetworkCoordinator` — TCP/NDJSON server (`#start` / `#stop` / `#running?`); `SignerClient` — remote submit + aggregate with typed `RemoteError`
163
+ - `ShareFile` — encrypted share-file persistence
164
+
165
+ === `Confium::Store::Keystore` — key handles and remote signing
166
+ - `Keystore.new(backend, **options)` / `.backends`
167
+ - `#sign(key_id, algorithm, message)` → signature bytes (sign-with-handle contract; cloud KMS backends `aws-kms` / `gcp-kms` / `azure-keyvault` via cargo features)
168
+
169
+ === `Confium::Audit` — structured audit trail
170
+ - `Audit.sink =` / `Audit.sink` / `Audit.enabled?` / `Audit.record(...)`
171
+ - `Sink` (base) / `MemorySink` / `StderrSink` / `FileSink`
172
+ - `OtlpSink.new(endpoint:, headers:, service_name:, ...)` — OTLP/HTTP export with retry and `#dropped` counter
173
+
174
+ === `Confium::OpenPGP`
175
+ - `.armor(data, type)` / `.dearmor(data)` — RFC 9580 §6 ASCII armor with CRC-24 (pure Ruby)
176
+ - `.verify_detached(message, signature, keys)` / `.verify(...)` — real signature verification when the extension is built with the `pgp` feature; `PGP_AVAILABLE` reports it
177
+
178
+ === `Confium::Transport` — coordinator clients over any transport
179
+ - `SignerClient.new(url)` — connect over any registry transport: `tcp://host:port` (local/trusted) or `noise://host:port?key=<hex>&pinned=<hex>` (Noise_XX encrypted, stable identity + peer pinning)
180
+ - `#register(signer_id, quorum_id)` / `#create_session(quorum_id, scheme, message, threshold, num_parties)` → session id
181
+ - `#submit_commitment(session_id, signer_id, bytes)` / `#submit_share(session_id, signer_id, bytes)`
182
+ - `CoordinatorServer.new(url)` — serve coordinator sessions over any linked scheme (test/in-process use)
183
+
184
+ === `Confium::ERS` — evidence records
185
+ - `EvidenceRecord.build_initial(...)` / `#renew(...)` / `#renewal_count` (RFC 4998 / RFC 6283 archival)
186
+
187
+ === `Confium::Policy` / `Confium::SecureBytes`
188
+ - `Policy.jurisdiction = :eu` — jurisdictional algorithm policy (EU/US profiles; SM2/SM3/SM4 for CN planned)
189
+ - `SecureBytes.wrap(raw)` — zeroize-on-clear wrapper for private keys, shares, and secrets (`#bytes` non-destructive read, `#clear`)
190
+
191
+ === Errors
192
+ - Typed error hierarchy (`ParseError`, `ThresholdError`, `VerificationError`, `PolicyViolationError`, ...) — native failures surface positional `details` hashes (including DER byte offsets for parse errors)
193
+
126
194
  == Development
127
195
 
128
196
  After checking out the repo:
data/confium.gemspec CHANGED
@@ -40,6 +40,8 @@ Gem::Specification.new do |spec|
40
40
  ]
41
41
  spec.files.reject! { |f| File.directory?(f) }
42
42
  spec.files.reject! { |f| f =~ /\.(dll|so|dylib|lib|bundle)\Z/ }
43
+ # Windows socket diagnostic crate — development-only, never shipped.
44
+ spec.files.reject! { |f| f.start_with?('ext/socket-smoke/') }
43
45
  spec.require_paths = ['lib']
44
46
 
45
47
  spec.required_ruby_version = '>= 3.1.0'
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Confium::Transparency::OTS — OpenTimestamps client interface.
3
+ # Confium::Transparency::OTS — OpenTimestamps calendar client.
4
4
  #
5
- # Wraps confium-transparency::ots::Client for anchoring Merkle tree
6
- # roots in the Bitcoin blockchain via OTS calendar servers.
7
- #
8
- # This is a pure-Ruby stub that defines the interface. The actual
9
- # OTS stamping requires network access to calendar servers and
10
- # will be wired through the Rust extension in a future PR
11
- # (TODO.completion/011-ots-ers-exposure.md).
5
+ # Real wire-protocol implementation over the native extension
6
+ # (confium-transparency 0.8.5+): stamps POST the 32-byte digest to a
7
+ # calendar server and parse the returned partial proof; verification
8
+ # replays the op tree from the digest and classifies attestations.
9
+ # Network failures raise (Confium::Transparency::OTS is backed by a
10
+ # real HTTP client) there is no silent nil.
12
11
 
13
12
  module Confium
14
13
  module Transparency
@@ -20,44 +19,48 @@ module Confium
20
19
  https://a.pool.eternitywall.com
21
20
  ].freeze
22
21
 
23
- # An OTS receipt proving that a hash was anchored in Bitcoin
24
- # at a specific block height.
25
- class Receipt
26
- attr_reader :bytes, :block_height
22
+ class << self
23
+ # Stamp a 32-byte digest via the default calendar pool.
24
+ # Returns a Proof (pending attestation — Bitcoin confirmation
25
+ # arrives later; poll with #upgrade).
26
+ #
27
+ # @param hash [String] 32-byte SHA-256 digest to anchor
28
+ # @return [Confium::Transparency::OTS::Proof]
29
+ # @raise [IOError, ArgumentError]
30
+ def stamp(hash)
31
+ default_client.stamp(hash)
32
+ end
27
33
 
28
- def initialize(bytes:, block_height: nil)
29
- @bytes = bytes
30
- @block_height = block_height
34
+ # Verify a proof: replay its op tree from the digest and
35
+ # classify the attestations.
36
+ #
37
+ # @param proof [Proof, String] the proof (or raw .ots bytes —
38
+ # pass the digest alongside for the String form)
39
+ # @param digest [String, nil] required when proof is bytes
40
+ # @return [Hash] { pending: [uri], bitcoin: [height],
41
+ # litecoin: [height], anchored: bool }
42
+ def verify(proof, digest = nil)
43
+ proof = Proof.new(digest, proof) if digest && proof.is_a?(String)
44
+ proof.verify
31
45
  end
32
46
 
33
- def to_bytes
34
- @bytes
47
+ # Upgrade a pending proof (fetch a more complete one).
48
+ #
49
+ # @return [Proof]
50
+ def upgrade(proof)
51
+ default_client.upgrade(proof)
35
52
  end
36
- end
37
53
 
38
- # Stamp a 32-byte hash via OTS calendar servers.
39
- # Returns a Receipt (stub: returns nil — requires network).
40
- #
41
- # @param hash [String] 32-byte SHA-256 hash to anchor
42
- # @return [Receipt, nil]
43
- def self.stamp(_hash)
44
- # Real implementation: calls the Rust OTS client which
45
- # submits the hash to calendar servers and returns a
46
- # merged proof. Requires network access.
47
- nil
48
- end
54
+ private
49
55
 
50
- # Verify an OTS receipt against a hash.
51
- # Returns true if the receipt proves the hash was anchored.
52
- #
53
- # @param receipt [Receipt, String] the OTS proof
54
- # @param hash [String] the 32-byte hash
55
- # @return [Boolean]
56
- def self.verify(_receipt, _hash)
57
- # Real implementation: calls the Rust OTS verifier which
58
- # walks the Bitcoin blockchain proof.
59
- false
56
+ def default_client
57
+ @default_client ||= Client.new(DEFAULT_CALENDARS)
58
+ end
60
59
  end
60
+
61
+ # The native Client is defined by the extension
62
+ # (Confium::Transparency::OTS::Client) with #stamp / #upgrade;
63
+ # the Proof class carries #digest / #to_bytes / #verify.
61
64
  end
62
65
  end
63
66
  end
@@ -5,8 +5,8 @@
5
5
  # The Transparency module itself is defined by the native Rust
6
6
  # extension via magnus at require time. This file registers
7
7
  # pure-Ruby autoloads for the Transparency submodules.
8
- module Confium
9
- module Transparency
10
- autoload :OTS, 'confium/transparency/ots'
11
- end
12
- end
8
+ # `require`, not `autoload`: the native extension defines the OTS
9
+ # constant at load time, which would shadow the autoload entry and
10
+ # keep this file from ever running — the Ruby-level convenience
11
+ # methods would silently vanish.
12
+ require 'confium/transparency/ots'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Confium
4
- VERSION = '0.6.3'
4
+ VERSION = '0.7.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: confium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.1
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Open
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-26 00:00:00.000000000 Z
11
+ date: 2026-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake