The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
159 lines
11 KiB
Plaintext
159 lines
11 KiB
Plaintext
Sub-scope 07 (objectstorage) qualification source sets — manifest and probes
|
|
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
|
|
generatedAt=2026-08-30T03:02:47+00:00
|
|
cwd=/shared/codebase/clean-architecture-backend-template/src
|
|
|
|
=== OWNED FILES ===
|
|
40858f581274cdc9a0ca5c748179d24261b26dd0 objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3DirectTransferQualificationTest.java 24
|
|
ed5ca64050483df64c2ed9323a3689442b5105f1 objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3ManagedCommonSubsetQualificationTest.java 27
|
|
843ff6cb1ca56f9c0aa983a19b8946aab439b20d objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferContractTest.java 25
|
|
f9852e21f73a70c2e72a15884f5bc3754e04a144 objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectContractTest.java 291
|
|
7a58f87e6179c11b2365c03b2cc48531d68825cb objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferFaultTest.java 32
|
|
668cb4d072928aa0731dbb160b6845cc564f8f73 objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectFaultTest.java 147
|
|
|
|
files: 6
|
|
|
|
=== 8.1 lane registration: strict, non-skipping, required classes ===
|
|
$ sed -n '12,16p;53,84p' adapter/outbound/objectstorage/build.gradle
|
|
strictTestLanes {
|
|
sourceSet('objectStorageMinioContractTest') { compilesAgainst 'main', 'test' }
|
|
sourceSet('objectStorageMinioFaultTest') { compilesAgainst 'main', 'test' }
|
|
sourceSet('objectStorageAwsQualificationTest') { compilesAgainst 'main', 'test' }
|
|
}
|
|
def objectStorageMinioContractQualification = registerStrictQualificationTest(
|
|
name: 'objectStorageMinioContractTest',
|
|
sourceSet: sourceSets.objectStorageMinioContractTest,
|
|
requiredClasses: [
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.MinioDirectTransferContractTest',
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.MinioManagedObjectContractTest'
|
|
],
|
|
description: 'Runs the non-skipping exact-release MinIO managed object contract.')
|
|
objectStorageMinioContractQualification.configure {
|
|
shouldRunAfter tasks.named('test')
|
|
}
|
|
|
|
def objectStorageMinioFaultQualification = registerStrictQualificationTest(
|
|
name: 'objectStorageMinioFaultTest',
|
|
sourceSet: sourceSets.objectStorageMinioFaultTest,
|
|
requiredClasses: [
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.MinioDirectTransferFaultTest',
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.MinioManagedObjectFaultTest'
|
|
],
|
|
description: 'Runs the non-skipping digest-pinned MinIO/Toxiproxy fault contract.')
|
|
objectStorageMinioFaultQualification.configure {
|
|
shouldRunAfter objectStorageMinioContractQualification
|
|
}
|
|
|
|
registerStrictQualificationTest(
|
|
name: 'objectStorageAwsQualificationTest',
|
|
sourceSet: sourceSets.objectStorageAwsQualificationTest,
|
|
requiredClasses: [
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.AwsS3DirectTransferQualificationTest',
|
|
'dev.caskeleton.adapter.outbound.objectstorage.qualification.AwsS3ManagedCommonSubsetQualificationTest'
|
|
],
|
|
description: 'Runs only with explicit protected AWS sandbox authority and exact inputs.')
|
|
exit=0
|
|
|
|
=== 8.2 conditional sibling: which lanes actually call a provider ===
|
|
$ grep -c 'client\.' adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectContractTest.java adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectFaultTest.java adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferContractTest.java adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferFaultTest.java adapter/outbound/objectstorage/src/objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3ManagedCommonSubsetQualificationTest.java adapter/outbound/objectstorage/src/objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3DirectTransferQualificationTest.java
|
|
adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectContractTest.java:2
|
|
adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectFaultTest.java:2
|
|
adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferContractTest.java:0
|
|
adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioDirectTransferFaultTest.java:0
|
|
adapter/outbound/objectstorage/src/objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3ManagedCommonSubsetQualificationTest.java:0
|
|
adapter/outbound/objectstorage/src/objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3DirectTransferQualificationTest.java:0
|
|
exit=0
|
|
|
|
--- the AWS lane body in full ---
|
|
$ cat adapter/outbound/objectstorage/src/objectStorageAwsQualificationTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/AwsS3ManagedCommonSubsetQualificationTest.java
|
|
package dev.caskeleton.adapter.outbound.objectstorage.qualification;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import java.util.Map;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
class AwsS3ManagedCommonSubsetQualificationTest {
|
|
|
|
@Test
|
|
void protectedLaneRequiresExplicitAuthorityAndExactSandboxInputs() {
|
|
Map<String, String> environment = System.getenv();
|
|
|
|
assertThat(environment.get("OBJECT_STORAGE_AWS_QUALIFICATION_ENABLED"))
|
|
.as("protected AWS qualification authority")
|
|
.isEqualTo("true");
|
|
assertThat(environment.get("OBJECT_STORAGE_AWS_BUCKET"))
|
|
.as("exact sandbox bucket")
|
|
.isNotBlank();
|
|
assertThat(environment.get("OBJECT_STORAGE_AWS_REGION"))
|
|
.as("exact sandbox region")
|
|
.isNotBlank();
|
|
assertThat(environment.get("OBJECT_STORAGE_AWS_EXPECTED_OWNER"))
|
|
.as("exact expected owner")
|
|
.matches("[0-9]{12}");
|
|
}
|
|
}
|
|
exit=0
|
|
|
|
=== 8.3 pinned identities: image digests must agree across lanes and evidence ===
|
|
$ grep -rn 'sha256:' adapter/outbound/objectstorage/src/objectStorageMinioContractTest adapter/outbound/objectstorage/src/objectStorageMinioFaultTest adapter/outbound/objectstorage/src/test/resources/object-storage/minio-provider-evidence.json
|
|
adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectContractTest.java:44: "minio/minio@sha256:4c4a4876193f030c81f57aabb22bcb9a73462010eb61fcab66908e03e5484af8";
|
|
adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectFaultTest.java:39: "minio/minio@sha256:4c4a4876193f030c81f57aabb22bcb9a73462010eb61fcab66908e03e5484af8");
|
|
adapter/outbound/objectstorage/src/objectStorageMinioFaultTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectFaultTest.java:42: "ghcr.io/shopify/toxiproxy@sha256:"
|
|
adapter/outbound/objectstorage/src/test/resources/object-storage/minio-provider-evidence.json:5: "image": "minio/minio@sha256:4c4a4876193f030c81f57aabb22bcb9a73462010eb61fcab66908e03e5484af8",
|
|
adapter/outbound/objectstorage/src/test/resources/object-storage/minio-provider-evidence.json:6: "toxiproxyImage": "ghcr.io/shopify/toxiproxy@sha256:9378ed52a28bc50edc1350f936f518f31fa95f0d15917d6eb40b8e376d1a214e",
|
|
exit=0
|
|
|
|
=== 8.4 what the live MinIO contract actually proves ===
|
|
$ grep -n 'ifNoneMatch\|ifMatch\|assertPreconditionFailed\|overwritten' adapter/outbound/objectstorage/src/objectStorageMinioContractTest/java/dev/caskeleton/adapter/outbound/objectstorage/qualification/MinioManagedObjectContractTest.java
|
|
112: .ifNoneMatch("*")
|
|
126: var overwrittenDespiteCreateOnlyCondition =
|
|
132: .ifNoneMatch("*")
|
|
141: assertThat(overwrittenDespiteCreateOnlyCondition.eTag()).isNotBlank();
|
|
162: .ifMatch(head.eTag())
|
|
177: .ifNoneMatch("*")
|
|
184: var overwrittenControlCreate =
|
|
190: .ifNoneMatch("*")
|
|
195: assertThat(overwrittenControlCreate.eTag()).isNotBlank();
|
|
196: assertPreconditionFailed(
|
|
203: .ifMatch("\"definitely-stale-etag\"")
|
|
266: .ifNoneMatch("*")
|
|
270: var overwritten =
|
|
276: assertThat(overwritten.asByteArray()).containsExactly(content);
|
|
283: private static void assertPreconditionFailed(
|
|
exit=0
|
|
|
|
$ cat adapter/outbound/objectstorage/src/test/resources/object-storage/minio-provider-evidence.json
|
|
{
|
|
"schema": 1,
|
|
"providerType": "s3-compatible-minio-community-release-2024-01-16t16-07-38z",
|
|
"providerVersion": "release-2024-01-16t16-07-38z-sdk-2.30.0",
|
|
"image": "minio/minio@sha256:4c4a4876193f030c81f57aabb22bcb9a73462010eb61fcab66908e03e5484af8",
|
|
"toxiproxyImage": "ghcr.io/shopify/toxiproxy@sha256:9378ed52a28bc50edc1350f936f518f31fa95f0d15917d6eb40b8e376d1a214e",
|
|
"profile": "managed-common",
|
|
"status": "UNSUPPORTED",
|
|
"excludedProfiles": [
|
|
"managed-single-create-only",
|
|
"conditional-control-create",
|
|
"managed-multipart-create-only",
|
|
"direct-single-create-only",
|
|
"direct-multipart-create-only"
|
|
],
|
|
"limitations": [
|
|
"PutObject If-None-Match was accepted and overwrote an existing object",
|
|
"stale PutObject If-Match returned HTTP 412 but create-if-absent control CAS is not safe",
|
|
"CompleteMultipartUpload accepted If-None-Match despite a pre-existing target and overwrote it",
|
|
"managed immutable create, conditional control creation, and multipart create-only are disabled",
|
|
"local single-node container evidence only",
|
|
"not AWS evidence",
|
|
"not production TLS or deployment-topology evidence"
|
|
]
|
|
}
|
|
exit=0
|
|
|
|
$ grep -n 'MINIO_COMMUNITY_2024_01_16\|release-2024-01-16' adapter/outbound/objectstorage/src/main/java/dev/caskeleton/adapter/outbound/objectstorage/s3/S3ProviderType.java adapter/outbound/objectstorage/src/main/java/dev/caskeleton/adapter/outbound/objectstorage/s3/S3ProviderVersion.java
|
|
adapter/outbound/objectstorage/src/main/java/dev/caskeleton/adapter/outbound/objectstorage/s3/S3ProviderType.java:8: MINIO_COMMUNITY_2024_01_16("s3-compatible-minio-community-release-2024-01-16t16-07-38z");
|
|
adapter/outbound/objectstorage/src/main/java/dev/caskeleton/adapter/outbound/objectstorage/s3/S3ProviderVersion.java:7: S3ProviderType.MINIO_COMMUNITY_2024_01_16, "release-2024-01-16t16-07-38z-sdk-2.30.0");
|
|
exit=0
|
|
|