confium 0.3.2 → 0.3.3

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: c8445c7b4b7f4fdea4740a5f22874c5a97eda59e75ebe5cf327dbc84b67ff6f2
4
- data.tar.gz: 68381a40a3a7f21b5f4330611bbe86e7abbf9223602288f105f611553e86cd21
3
+ metadata.gz: 4c325019a3961cbf877d81c11496cfccba51959282d930b1e5e0420b25b66958
4
+ data.tar.gz: 91ea66bd4a9541e38ce7c01c03c26408a8372debdce0539c13ab70aee4895970
5
5
  SHA512:
6
- metadata.gz: 00cf2dd64ba0bce3897db2d5f026818ccc5f90cc1ad1f27a65869827f530811df1a60c50e6fefeb9c83183859bccce81194b0e031e2fbff5b8213d53bb3cb4cb
7
- data.tar.gz: a2f6509125418022a2aa3d98d86b724cc841f7f3067884c482d345f2f3b28a0adb63b51dbba34d48dd5d64aa1c827a42d8bf86be273160feb631d5e8a68b72b9
6
+ metadata.gz: e70d630fd442cf891ff15cdd27fc335281488ca5c5985f298337559ad9caf2dfb77bdf7993dd47f766116512bff4e3a53e2939b55cc8b91f77744176780faaf5
7
+ data.tar.gz: 3f389ce934ed8f8f81bb13e87346f07b49d06f48acb1196c3774e7c01f1ad810185f22b6708edb0d887193afef4d5d850c3cd4fb6c58e2b246aae09300f5e419
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.3] — 2026-08-23
4
+
5
+ ### Added
6
+
7
+ - **Typed native errors everywhere**: PEM/DER, JSON, TOML, DSL, and
8
+ XML parse failures raise `Confium::ParseError`; out-of-range
9
+ sequence indexes raise `Confium::IndexError`; consistency-proof
10
+ failures raise `Confium::VerificationError` — each with a
11
+ structured `details` Hash (format, operation, index, ...).
12
+ Previously these surfaced as bare `RuntimeError`.
13
+
14
+ ### Added
15
+
16
+ - `Confium::Composite::Signature.components_to_json` /
17
+ `.from_json` — JSON transport for composite signatures with the
18
+ binary fields hex-encoded on the wire (fixes the Sinatra example's
19
+ happy path, which called a `from_json` that did not exist).
20
+ - Steep type checking in CI: the Steepfile never loaded before
21
+ (it used a `configure_code_diagnostics` API that does not exist in
22
+ steep 1.10). `sig/confium.rbs` now covers every pure-Ruby
23
+ subsystem — including the TC session machinery — and
24
+ `bundle exec steep check` is green and enforced. Only the FFI
25
+ layer is excluded (the ffi gem has no RBS signatures).
26
+
27
+ ### Fixed
28
+
29
+ - `Confium::PKI::CMS::SignedDataBuilder#build` raised KeyError on
30
+ the ECDSA-P256 path (`FrostP256.sign` returns `der`/`fixed`, not
31
+ `signature`); it now uses the DER form, which is what CMS carries.
32
+ - `Confium::PKI::CertificateBuilder`, `Confium::PKI::CNML`, and
33
+ `Confium::Transparency::OTS` were unreachable after
34
+ `require "confium"` (missing autoload wiring); the PKI namespace
35
+ file is now eager-required and registers them.
36
+ - All five `hello_*` quickstart examples, the Sinatra example's
37
+ happy path, and every page under `docs/` were rewritten against
38
+ the real APIs (see the docs audit), and CI now runs every example
39
+ on every push.
40
+
3
41
  ## [0.3.2] — 2026-08-22
4
42
 
5
43
  Native platform gems (linux x86_64/aarch64, macOS x86_64/arm64) ship
data/README.adoc CHANGED
@@ -10,7 +10,7 @@ Confium supports three deployment modes:
10
10
  * **Mode 2 — TC PKI replacement**: drop-in for existing PKI consumers (PKCS#11 server, OpenSSL 3.0 provider, JCE)
11
11
  * **Mode 3 — TC Certificate PKI**: institutional deployments with custom certificate formats (OIML CNML, BIPM, pharma, accreditation)
12
12
 
13
- This gem wraps the high-value Confium subsystems via a Rust native extension (built at `gem install` time with `rb_sys` + `magnus`). No separate C ABI library to install; everything is statically linked into the extension.
13
+ This gem wraps the high-value Confium subsystems via a Rust native extension. Pre-compiled platform gems are published for Linux and macOS, so `gem install` needs no Rust toolchain there; other platforms build from source at install time with `rb_sys` + `magnus`. No separate C ABI library to install; everything is statically linked into the extension.
14
14
 
15
15
  == Installation
16
16
 
@@ -18,7 +18,7 @@ Add to your Gemfile:
18
18
 
19
19
  [source,ruby]
20
20
  ----
21
- gem "confium", "~> 0.1"
21
+ gem "confium", "~> 0.3"
22
22
  ----
23
23
 
24
24
  Or install directly:
@@ -31,10 +31,18 @@ $ gem install confium
31
31
  === Prerequisites
32
32
 
33
33
  * Ruby ≥ 3.1
34
+ * Nothing else on the pre-compiled platforms: `x86_64-linux`,
35
+ `aarch64-linux`, `x86_64-darwin`, `arm64-darwin` (each gem carries
36
+ one extension per Ruby C-ABI window)
37
+
38
+ Source builds (other platforms, or installing from the repo) also
39
+ need:
40
+
34
41
  * Rust stable toolchain (`rustup default stable`)
35
42
  * C toolchain (clang/gcc/Xcode CLT)
36
43
 
37
- The gem compiles a Rust cdylib at install time and links it into Ruby as a native extension. There is no separate `libconfium` to install.
44
+ There is no separate `libconfium` to install — the extension
45
+ statically links everything.
38
46
 
39
47
  == Quick start
40
48
 
@@ -76,7 +84,7 @@ recovered = Confium::TC::FrostP256.recover_secret(shares.first(3).map { |s| { "x
76
84
  recovered == kp["private_key"] # => true
77
85
  ----
78
86
 
79
- == API surface (v0.1.0)
87
+ == API surface (v0.3)
80
88
 
81
89
  === `Confium::Transparency`
82
90
  - `MerkleTree.new` / `#append(artifact_hash)` / `#root` / `#length` / `#empty?` / `#inclusion_proof(seq)`
@@ -127,7 +135,7 @@ After checking out the repo:
127
135
  ----
128
136
  $ bundle install
129
137
  $ bundle exec rake compile # build the Rust extension
130
- $ bundle exec rspec # 75+ specs
138
+ $ bundle exec rspec # 226 specs
131
139
  ----
132
140
 
133
141
  == Architecture
data/confium.gemspec CHANGED
@@ -49,7 +49,6 @@ Gem::Specification.new do |spec|
49
49
 
50
50
  spec.add_development_dependency 'rake', '~> 13.0'
51
51
  spec.add_development_dependency 'rake-compiler', '~> 1.3.0'
52
- spec.add_development_dependency 'rake-compiler-dock', '~> 1.3'
53
52
  spec.add_development_dependency 'rspec', '~> 3.0'
54
53
  spec.add_development_dependency 'rubocop', '~> 1.0'
55
54
  spec.add_development_dependency 'steep', '~> 1.5'
@@ -63,7 +63,7 @@ impl SignerWrap {
63
63
 
64
64
  fn parse(expr: String) -> Result<Obj<PredicateWrap>, Error> {
65
65
  let predicate = dsl_parse(&expr)
66
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
66
+ .map_err(|e| crate::util::parse_error(e.to_string(), "Attributes.parse", Some("dsl"), None))?;
67
67
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
68
68
  Ok(ruby.obj_wrap(PredicateWrap { inner: predicate }))
69
69
  }
@@ -11,7 +11,7 @@ use confium_deployment::{
11
11
  manifest::{parse_manifest, Manifest as RustManifest},
12
12
  validate::validate_manifest,
13
13
  };
14
- use crate::util::enforce_size;
14
+ use crate::util::{enforce_size, parse_error};
15
15
  use magnus::{exception, function, method, typed_data::Obj, DataTypeFunctions, Error, Module, Object, Ruby, TypedData};
16
16
 
17
17
  #[derive(TypedData, DataTypeFunctions)]
@@ -24,7 +24,7 @@ impl Actor {
24
24
  fn from_json(json: String) -> Result<Obj<Self>, Error> {
25
25
  enforce_size(json.len())?;
26
26
  let actor: ActorIdentity = serde_json::from_str(&json)
27
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
27
+ .map_err(|e| parse_error(e.to_string(), "Actor.from_json", Some("json"), None))?;
28
28
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
29
29
  Ok(ruby.obj_wrap(Self {
30
30
  inner: std::cell::RefCell::new(actor),
@@ -93,7 +93,7 @@ impl Manifest {
93
93
  fn from_toml(toml_str: String) -> Result<Obj<Self>, Error> {
94
94
  enforce_size(toml_str.len())?;
95
95
  let manifest = parse_manifest(&toml_str)
96
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
96
+ .map_err(|e| parse_error(e.to_string(), "Manifest.from_toml", Some("toml"), None))?;
97
97
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
98
98
  Ok(ruby.obj_wrap(Self {
99
99
  inner: std::cell::RefCell::new(manifest),
@@ -26,7 +26,7 @@ fn native_armor(ruby: &Ruby, data: Value, type_str: Value) -> Result<magnus::RSt
26
26
  }
27
27
  };
28
28
  let armored = armor_bytes(&bytes, ty)
29
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
29
+ .map_err(|e| crate::util::parse_error(e.to_string(), "OpenPGP.armor", Some("openpgp"), None))?;
30
30
  Ok(bytes_to_rstring(ruby, &armored))
31
31
  }
32
32
 
@@ -34,7 +34,7 @@ fn native_armor(ruby: &Ruby, data: Value, type_str: Value) -> Result<magnus::RSt
34
34
  fn native_dearmor(ruby: &Ruby, data: Value) -> Result<magnus::RString, Error> {
35
35
  let bytes = bytes_from_value(data)?;
36
36
  let raw = dearmor_bytes(&bytes)
37
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
37
+ .map_err(|e| crate::util::parse_error(e.to_string(), "OpenPGP.dearmor", Some("openpgp"), None))?;
38
38
  Ok(bytes_to_rstring(ruby, &raw))
39
39
  }
40
40
 
@@ -10,7 +10,7 @@
10
10
  //! *building* + signing lands in a follow-up once the Rust builder API
11
11
  //! stabilizes (currently `confium_pki::cert::builder` is private).
12
12
 
13
- use crate::util::{bytes_from_value, bytes_to_rstring, enforce_size};
13
+ use crate::util::{bytes_from_value, bytes_to_rstring, enforce_size, parse_error};
14
14
  use chrono::{DateTime, Utc};
15
15
  use confium_pki::{
16
16
  cert::{Certificate as RustCert, CertificateSigningRequest as RustCsr},
@@ -34,7 +34,7 @@ impl Certificate {
34
34
  fn from_der(bytes: Value) -> Result<Obj<Self>, Error> {
35
35
  let der = bytes_from_value(bytes)?;
36
36
  let cert = RustCert::from_der(&der)
37
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
37
+ .map_err(|e| parse_error(e.to_string(), "Certificate.from_der", Some("der"), None))?;
38
38
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
39
39
  Ok(ruby.obj_wrap(Self { inner: cert }))
40
40
  }
@@ -42,7 +42,7 @@ impl Certificate {
42
42
  fn from_pem(pem: String) -> Result<Obj<Self>, Error> {
43
43
  enforce_size(pem.len())?;
44
44
  let cert = RustCert::from_pem(&pem)
45
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
45
+ .map_err(|e| parse_error(e.to_string(), "Certificate.from_pem", Some("pem"), None))?;
46
46
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
47
47
  Ok(ruby.obj_wrap(Self { inner: cert }))
48
48
  }
@@ -102,7 +102,7 @@ impl Csr {
102
102
  fn from_der(bytes: Value) -> Result<Obj<Self>, Error> {
103
103
  let der = bytes_from_value(bytes)?;
104
104
  let csr = RustCsr::from_der(&der)
105
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
105
+ .map_err(|e| parse_error(e.to_string(), "Csr.from_der", Some("der"), None))?;
106
106
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
107
107
  Ok(ruby.obj_wrap(Self { inner: csr }))
108
108
  }
@@ -110,7 +110,7 @@ impl Csr {
110
110
  fn from_pem(pem: String) -> Result<Obj<Self>, Error> {
111
111
  enforce_size(pem.len())?;
112
112
  let csr = RustCsr::from_pem(&pem)
113
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
113
+ .map_err(|e| parse_error(e.to_string(), "Csr.from_pem", Some("pem"), None))?;
114
114
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
115
115
  Ok(ruby.obj_wrap(Self { inner: csr }))
116
116
  }
@@ -135,7 +135,7 @@ impl SignedData {
135
135
  fn from_json(json: String) -> Result<Obj<Self>, Error> {
136
136
  enforce_size(json.len())?;
137
137
  let sd: RustSignedData = serde_json::from_str(&json)
138
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
138
+ .map_err(|e| parse_error(e.to_string(), "SignedData.from_json", Some("json"), None))?;
139
139
  let ruby = Ruby::get().map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
140
140
  Ok(ruby.obj_wrap(Self {
141
141
  inner: std::cell::RefCell::new(sd),
@@ -362,12 +362,12 @@ impl CertWrapper {
362
362
 
363
363
  fn xmldsig_canonicalize(xml: String) -> Result<String, Error> {
364
364
  enforce_size(xml.len())?;
365
- canonicalize(&xml).map_err(|e| Error::new(exception::runtime_error(), e.to_string()))
365
+ canonicalize(&xml).map_err(|e| parse_error(e.to_string(), "XMLDSig.canonicalize", Some("xml"), None))
366
366
  }
367
367
 
368
368
  fn xmldsig_canonicalize_exclusive(xml: String) -> Result<String, Error> {
369
369
  enforce_size(xml.len())?;
370
- canonicalize_exclusive(&xml).map_err(|e| Error::new(exception::runtime_error(), e.to_string()))
370
+ canonicalize_exclusive(&xml).map_err(|e| parse_error(e.to_string(), "XMLDSig.canonicalize_exclusive", Some("xml"), None))
371
371
  }
372
372
 
373
373
  pub fn init(ruby: &Ruby, parent: magnus::RModule) -> Result<(), Error> {
@@ -72,7 +72,7 @@ impl MerkleTree {
72
72
  .inner
73
73
  .borrow()
74
74
  .consistency_proof(old_size)
75
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
75
+ .map_err(|e| crate::util::index_error(e.to_string(), "MerkleTree.consistency_proof", Some(old_size as u64)))?;
76
76
  let ruby = Ruby::get()
77
77
  .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
78
78
  let arr = ruby.ary_new_capa(proof.len());
@@ -142,7 +142,7 @@ impl MerkleTree {
142
142
  .borrow()
143
143
  .verify_consistency(old_root_hash, new_root_hash, old_size, new_size, &proof_hashes)
144
144
  .map(|_| true)
145
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))
145
+ .map_err(|e| crate::util::verification_error(e.to_string(), "MerkleTree.verify_consistency", None, None))
146
146
  }
147
147
 
148
148
  fn root(&self) -> Value {
@@ -155,10 +155,10 @@ impl MerkleTree {
155
155
  let tree = self.inner.borrow();
156
156
  let proof = tree
157
157
  .inclusion_proof(seq)
158
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
158
+ .map_err(|e| crate::util::index_error(e.to_string(), "MerkleTree.inclusion_proof", Some(seq)))?;
159
159
  let entry = tree
160
160
  .entry(seq)
161
- .map_err(|e| Error::new(exception::runtime_error(), e.to_string()))?;
161
+ .map_err(|e| crate::util::index_error(e.to_string(), "MerkleTree.inclusion_proof", Some(seq)))?;
162
162
  // Re-derive the leaf hash with the same algorithm the tree uses
163
163
  // internally (H(0x01 | entry_hash)).
164
164
  let leaf_hash = hash_leaf(entry.entry_hash());
@@ -148,6 +148,19 @@ pub fn parse_error(msg: impl Into<String>, operation: &str, format: Option<&str>
148
148
  confium_error(msg, "ParseError", d)
149
149
  }
150
150
 
151
+ #[allow(dead_code)]
152
+ pub fn index_error(msg: impl Into<String>, operation: &str, index: Option<u64>) -> Error {
153
+ let ruby = match Ruby::get() {
154
+ Ok(r) => r,
155
+ Err(_) => return Error::new(exception::runtime_error(), msg.into()),
156
+ };
157
+ let d = new_details(&ruby);
158
+ let _ = d.aset("operation", operation);
159
+ let _ = d.aset("component", "Confium");
160
+ if let Some(i) = index { let _ = d.aset("index", i); }
161
+ confium_error(msg, "IndexError", d)
162
+ }
163
+
151
164
  #[allow(dead_code)]
152
165
  pub fn validation_error(msg: impl Into<String>, operation: &str, param: &str, expected: &str, actual: &str) -> Error {
153
166
  let ruby = match Ruby::get() {
data/lib/confium/audit.rb CHANGED
@@ -68,6 +68,7 @@ module Confium
68
68
  attr_reader :records
69
69
 
70
70
  def initialize
71
+ # @type ivar @records: Array[untyped]
71
72
  @records = []
72
73
  end
73
74
 
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Confium
6
+ module Composite
7
+ # JSON transport for composite signatures. The native extension
8
+ # defines Signature with algorithms/component_count/verify over
9
+ # component Hashes (algorithm, public_key, signature) whose
10
+ # binary fields cannot ride JSON directly, so the wire format
11
+ # hex-encodes them:
12
+ #
13
+ # json = Confium::Composite::Signature.components_to_json(components)
14
+ # sig = Confium::Composite::Signature.from_json(json)
15
+ # sig.verify(message)
16
+ class Signature
17
+ BINARY_FIELDS = %w[public_key signature].freeze
18
+
19
+ def self.components_to_json(components)
20
+ JSON.generate(components.map do |component|
21
+ component.transform_values do |value|
22
+ value.encoding == Encoding::ASCII_8BIT ? value.unpack1('H*') : value
23
+ end
24
+ end)
25
+ end
26
+
27
+ # Accepts either a bare JSON array of component Hashes or a
28
+ # {"components": [...]} envelope, with public_key/signature
29
+ # hex-encoded on the wire. Takes a JSON string or an
30
+ # already-parsed Array/Hash.
31
+ def self.from_json(json)
32
+ data = json.is_a?(String) ? JSON.parse(json) : json
33
+ components = data.is_a?(Hash) ? data['components'] : data
34
+ unless components.is_a?(Array) && !components.empty?
35
+ raise ArgumentError, 'expected a non-empty "components" array'
36
+ end
37
+
38
+ new(components.map { |c| decode_binary_fields(c) })
39
+ end
40
+
41
+ def self.decode_binary_fields(component)
42
+ BINARY_FIELDS.each_with_object(component.dup) do |field, decoded|
43
+ value = component.fetch(field)
44
+ decoded[field] = [value].pack('H*') if value.is_a?(String)
45
+ end
46
+ end
47
+ private_class_method :decode_binary_fields
48
+ end
49
+ end
50
+ end
@@ -21,6 +21,7 @@
21
21
  # Confium::Crypto.lookup(:hash) # => Confium::Digest
22
22
  module Confium
23
23
  module Crypto
24
+ # @type ivar @interfaces: Hash[Symbol, untyped]
24
25
  @interfaces = {}
25
26
 
26
27
  class << self
@@ -33,6 +33,7 @@ module Confium
33
33
 
34
34
  def initialize
35
35
  @content = nil
36
+ # @type ivar @signers: Array[Hash[Symbol, untyped]]
36
37
  @signers = []
37
38
  end
38
39
 
@@ -81,7 +82,9 @@ module Confium
81
82
  result.fetch('signature')
82
83
  when :ecdsa_p256
83
84
  result = Confium::TC::FrostP256.sign(private_key, payload)
84
- result.fetch('signature')
85
+ # CMS carries ECDSA signatures DER-encoded (DSA-Sig-Value);
86
+ # FrostP256.sign returns { "der" => ..., "fixed" => ... }.
87
+ result.fetch('der')
85
88
  else
86
89
  raise ArgumentError, "unsupported algorithm: #{algorithm.inspect}"
87
90
  end
data/lib/confium/pki.rb CHANGED
@@ -9,5 +9,7 @@
9
9
  module Confium
10
10
  module PKI
11
11
  autoload :CMS, 'confium/pki/cms'
12
+ autoload :CertificateBuilder, 'confium/pki/certificate_builder'
13
+ autoload :CNML, 'confium/pki/cnml'
12
14
  end
13
15
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Confium::Transparency namespace file.
4
+ #
5
+ # The Transparency module itself is defined by the native Rust
6
+ # extension via magnus at require time. This file registers
7
+ # pure-Ruby autoloads for the Transparency submodules.
8
+ module Confium
9
+ module Transparency
10
+ autoload :OTS, 'confium/transparency/ots'
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Confium
4
- VERSION = '0.3.2'
4
+ VERSION = '0.3.3'
5
5
  end
data/lib/confium.rb CHANGED
@@ -18,8 +18,7 @@ begin
18
18
  # 3.1 and 3.2 get exact-minor builds while 3.3 covers 3.3+).
19
19
  # Source builds install the extension flat, without a version
20
20
  # directory.
21
- major, minor = RUBY_VERSION.split('.').first(2).map(&:to_i)
22
- window = major > 3 || minor >= 3 ? '3.3' : "#{major}.#{minor}"
21
+ window = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3') ? '3.3' : RUBY_VERSION[/\A\d+\.\d+/]
23
22
  begin
24
23
  require_relative "confium_native/#{window}/confium_native"
25
24
  rescue LoadError
@@ -56,9 +55,21 @@ module Confium
56
55
  autoload :PolicyViolationError, 'confium/errors/policy_violation_error'
57
56
  autoload :SecureBytes, 'confium/secure_bytes'
58
57
  autoload :Policy, 'confium/policy'
59
- autoload :PKI, 'confium/pki'
58
+ # PKI is native-defined, so an autoload would never fire; the
59
+ # namespace file is eager-required and registers the pure-Ruby
60
+ # submodules (CMS, CertificateBuilder, CNML) as autoloads.
61
+ require_relative 'confium/pki'
60
62
  end
61
63
 
64
+ # Eager-load the Composite Signature JSON companion. The native
65
+ # extension defines Confium::Composite; this file reopens the class
66
+ # to add from_json transport.
67
+ require_relative 'confium/composite'
68
+
69
+ # Eager-load the Transparency namespace for the OTS autoload (the
70
+ # module itself is native-defined).
71
+ require_relative 'confium/transparency'
72
+
62
73
  # Eager-load the Audit Ruby companion. The native extension registers
63
74
  # `Confium::Audit` as a Ruby module with the `record`/`sink=`/`sink`
64
75
  # methods; the companion file defines the Sink class hierarchy on top
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.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Open
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-22 00:00:00.000000000 Z
11
+ date: 2026-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.3.0
55
- - !ruby/object:Gem::Dependency
56
- name: rake-compiler-dock
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.3'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.3'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rspec
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -144,6 +130,7 @@ files:
144
130
  - lib/confium.rb
145
131
  - lib/confium/audit.rb
146
132
  - lib/confium/cfm.rb
133
+ - lib/confium/composite.rb
147
134
  - lib/confium/crypto.rb
148
135
  - lib/confium/digest.rb
149
136
  - lib/confium/errors.rb
@@ -172,6 +159,7 @@ files:
172
159
  - lib/confium/tc/session.rb
173
160
  - lib/confium/tc/session_stub.rb
174
161
  - lib/confium/tc/share_file.rb
162
+ - lib/confium/transparency.rb
175
163
  - lib/confium/transparency/ots.rb
176
164
  - lib/confium/version.rb
177
165
  homepage: https://www.confium.org