wip(pki): checkpoint Phase A metadata foundation

Checkpoint the current pre-release Phase A work before production
persistence integration continues.

Includes the consolidated transactional metadata SPI, POSIX append-only
metadata log, recovery epochs, mutation codec, state reducer, internal
transaction engine, transactional adapter, staged-content foundations,
and the related current lib/pki changes.

Validated baseline:
- lib tests pass
- focused metadata tests pass
- PMD passes with zero findings
- JavaDoc passes
- app compilation passes
- pki retains exactly 31 independently classified failures:
  2 credential snapshot/model cases and 29 revocation fixture/reference
  cases

This is a work-in-progress safety checkpoint, not a release-ready
milestone.
This commit is contained in:
2026-08-01 16:45:14 +02:00
parent 369c626ed8
commit 5420c19d08
147 changed files with 26788 additions and 1071 deletions

View File

@@ -0,0 +1,150 @@
/*******************************************************************************
* Copyright (C) 2026, Leo Galambos
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software must
* display the following acknowledgement:
* This product includes software developed by the Egothor project.
*
* 4. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
package zeroecho.core.spec;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import org.junit.jupiter.api.Test;
import zeroecho.core.alg.BootstrapAlgorithmIdentities;
import zeroecho.core.spi.AlgorithmExecutionCapabilities;
import zeroecho.core.spi.AlgorithmExecutionCapability;
/**
* Phase A regression tests for provider-independent identity and capability
* contracts.
*/
public final class AlgorithmIdentityPhaseATest {
@Test
void exactIdentityAlgebraAndCanonicalRoundTrip() {
System.out.println("exactIdentityAlgebraAndCanonicalRoundTrip");
AlgorithmIdentity first = BootstrapAlgorithmIdentities.rsaPss(BootstrapAlgorithmIdentities.SHA384,
BootstrapAlgorithmIdentities.SHA512, 40);
AlgorithmIdentity second = BootstrapAlgorithmIdentities.rsaPss(BootstrapAlgorithmIdentities.SHA384,
BootstrapAlgorithmIdentities.SHA512, 40);
AlgorithmIdentity different = BootstrapAlgorithmIdentities.rsaPss(BootstrapAlgorithmIdentities.SHA384,
BootstrapAlgorithmIdentities.SHA384, 40);
AlgorithmIdentityCatalog extension = AlgorithmIdentityCatalog.extension(List.of(
new AlgorithmIdentity(AlgorithmIdentity.Kind.SIGNATURE,
new AlgorithmIdentity.Family("example", "signature"),
new AlgorithmIdentity.DigestParameters(BootstrapAlgorithmIdentities.SHA384))));
AlgorithmIdentityCatalog merged = BootstrapAlgorithmIdentities.catalog().merge(List.of(extension));
assertEquals(first, second);
assertEquals(first.hashCode(), second.hashCode());
assertNotEquals(first, different);
assertEquals(BootstrapAlgorithmIdentities.RSA_PKCS1_SHA256,
merged.resolve(BootstrapAlgorithmIdentities.RSA_PKCS1_SHA256.canonicalForm()).orElseThrow());
assertFalse(first.canonicalForm().contains("BC"));
assertFalse(first.canonicalForm().contains("Sun"));
System.out.println("...canonical=" + abbreviate(first.canonicalForm()));
System.out.println("...ok");
}
@Test
void roleAndParameterContradictionsFailClosed() {
System.out.println("roleAndParameterContradictionsFailClosed");
assertThrows(IllegalArgumentException.class,
() -> new AlgorithmSuite(BootstrapAlgorithmIdentities.SHA256,
BootstrapAlgorithmIdentities.RSA_PUBLIC_KEY));
assertThrows(IllegalArgumentException.class,
() -> new AlgorithmIdentity.RsaPssParameters(BootstrapAlgorithmIdentities.RSA_PUBLIC_KEY,
BootstrapAlgorithmIdentities.MGF1, BootstrapAlgorithmIdentities.SHA256, 32, 1));
assertThrows(IllegalArgumentException.class,
() -> BootstrapAlgorithmIdentities.rsaPss(BootstrapAlgorithmIdentities.SHA256,
BootstrapAlgorithmIdentities.SHA256, -1));
assertThrows(IllegalArgumentException.class,
() -> AlgorithmIdentityCatalog.extension(List.of(BootstrapAlgorithmIdentities.SHA256)));
assertTrue(BootstrapAlgorithmIdentities.fromCompatibilityAlias("SHA1withRSA").isEmpty());
assertTrue(BootstrapAlgorithmIdentities.fromCompatibilityAlias("provider-specific").isEmpty());
System.out.println("...rejections=6");
System.out.println("...ok");
}
@Test
void parameterizedCapabilityDomainIsProviderMetadataOnly() {
System.out.println("parameterizedCapabilityDomainIsProviderMetadataOnly");
AlgorithmIdentity pss = BootstrapAlgorithmIdentities.rsaPss(BootstrapAlgorithmIdentities.SHA384,
BootstrapAlgorithmIdentities.SHA512, 40);
AlgorithmSuite suite = new AlgorithmSuite(pss, BootstrapAlgorithmIdentities.RSA_PUBLIC_KEY);
AlgorithmExecutionCapability capability = new TestPssCapability();
AlgorithmExecutionCapabilities capabilities = new AlgorithmExecutionCapabilities(List.of(capability));
assertEquals(1,
capabilities.supporting(pss, suite, AlgorithmExecutionCapability.Direction.VERIFY).size());
assertTrue(capabilities.supporting(pss, suite, AlgorithmExecutionCapability.Direction.SIGN).isEmpty());
assertEquals(pss, suite.signature());
System.out.println("...implementation=" + capability.implementationId());
System.out.println("...ok");
}
private static String abbreviate(String value) {
return value.length() <= 30 ? value : value.substring(0, 27) + "...";
}
/**
* Typed test-only parameter domain proving that a central enum is unnecessary.
*/
private static final class TestPssCapability implements AlgorithmExecutionCapability {
@Override
public String implementationId() {
return "test.rsa-pss-verify";
}
@Override
public String domainFingerprint() {
return "rsa-pss|sha384|mgf1-sha512|salt=0..64|verify";
}
@Override
public boolean supports(AlgorithmIdentity identity, AlgorithmSuite suite, Direction direction) {
if (!(identity.parameters() instanceof AlgorithmIdentity.RsaPssParameters parameters)) {
return false;
}
return identity.equals(suite.signature())
&& BootstrapAlgorithmIdentities.RSA_PUBLIC_KEY.equals(suite.publicKey())
&& BootstrapAlgorithmIdentities.SHA384.equals(parameters.hash())
&& BootstrapAlgorithmIdentities.SHA512.equals(parameters.maskHash())
&& parameters.saltLength() <= 64 && direction == Direction.VERIFY;
}
}
}