Non-negotiable constraints that apply to all work in this repository. Read this before making any changes.
Violations of these rules are Must fix in code review. Items marked [not yet enforced] rely on human review until tooling is added — they are the automation backlog.
-
XML element and attribute names must match the AWS S3 API specification exactly — Enforced by:
make integration-tests(CI gate) -
A compile check is not sufficient for XML correctness — always verify serialized output by running integration tests — Enforced by:
make integration-tests(CI gate) -
Path-style URLs only (
http://localhost:9090/<bucket>/<key>) — virtual-hosted-style (bucket.localhost) is not supported — Enforced by: [not yet enforced] -
Presigned URLs are accepted but signatures are not validated — do not add signature validation logic — Enforced by: [not yet enforced] (by design)
-
Never use AWS SDK v1 — it was removed in 5.x — Enforced by: human review
-
Never use legacy Jackson XML annotations from
com.fasterxml.jackson.dataformat.xml.annotation(e.g.@JacksonXmlRootElement,@JacksonXmlProperty) — usetools.jacksonpackages in 5.x — Enforced by: ArchUnitnoLegacyJacksonXmlAnnotations(make test) -
Business logic belongs in services only — controllers handle HTTP mapping, stores handle persistence; no cross-layer logic — Enforced by: ArchUnit
controllersMayNotAccessStoreDirect+storesMayNotAccessUpperLayers(partial — layering;make test); human review for service-layer logic -
Controllers never catch exceptions —
S3MockExceptionHandlerandIllegalStateExceptionHandlerare responsible for all error responses — Enforced by: human review -
Services throw
S3Exceptionconstants only (NO_SUCH_BUCKET,NO_SUCH_KEY, etc.) — no custom exception classes — Enforced by: human review
-
All dependency versions are declared in the root
pom.xml<properties>section — never declare versions in sub-module POMs — Enforced by: human review -
Update the copyright year to
2017-<current year>in the license header of every file you modify — Enforced by: human review -
Never update the copyright year in files you did not modify — copyright is bumped only when a file is actually changed — Enforced by: human review
-
S3Mock is not for production use — it has no authentication, authorization, or real encryption — Enforced by: [not yet enforced]
-
KMS key ARN format is validated, but no actual encryption is performed — do not add real KMS encryption — Enforced by: [not yet enforced] (by implementation)
-
The SSL certificate is self-signed — it is not suitable for any environment other than local testing — Enforced by: [not yet enforced] (by implementation)
No performance SLAs are defined for S3Mock. It is a local testing tool, not a throughput benchmark.
-
Never use JUnit 4 — it was removed in 5.x — Enforced by: human review
-
Never mock AWS SDK clients in integration tests (
*IT.kt) — use actual SDK v2 clients against a live S3Mock Docker container — Enforced by: human review -
Every code change must include unit tests (
*Test.ktinserver/) covering the new or modified logic — Enforced by: human review -
Spring-managed components (services, stores, controllers, filters,
@ControllerAdvice) must be tested with the Spring test harness —@SpringBootTest/@WebMvcTest+@MockitoBean, extendingServiceTestBase/StoreTestBase/BaseControllerTest— never standard Mockito unit tests (@ExtendWith(MockitoExtension)+@Mock+@InjectMocks). Plain classes with no injected collaborators (mostdto/model/util) may use a plain unit test. — Enforced by: ArchUnitnoStandardMockitoUnitTests(make test) -
Every behavior observable via the S3 HTTP API must be covered by an integration test (
*IT.ktinintegration-tests/) — Enforced by: human review
A task is not complete until all of the following are true:
- Unit tests cover the new or modified logic (
*Test.ktin the module the change was made) - Integration tests cover the observable HTTP/S3 behavior (
*IT.ktinintegration-tests/) CHANGELOG.mdhas an entry under the current version for any user-facing bug fix or featureREADME.mdis updated for any new API surface, configuration variable, port, or Spring profilemake lintpasses (ktlint + Checkstyle)