Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/156-objectstorage-qualification-lanes-probes.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
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>
2026-09-04 22:51:59 +09:00

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