Production Capstone: Build, Test, Secure, Publish, and Optimize a Multi-Module JVM Platform: Security, Governance, and Reliability Validation
Validate the platform as an interacting control system. Prove wrapper integrity, repository origin, version governance, verification metadata, cache trust, artifact traceability, clean-room reproducibility, Maven interoperability, and the distinction between a build that succeeds and a build that is trustworthy.
Learning objectives
- Validate security controls as interacting layers rather than isolated checkboxes.
- Prove clean-room reproducibility and artifact traceability with independent evidence.
- Separate successful compilation, trustworthy dependency provenance, and vulnerability assessment.
- Evaluate architecture tradeoffs without losing objective invariants.
- Build an evidence matrix mapping each invariant to source, signal, verification, and owner.
A trusted build is not the same as vulnerability-free software. Wrapper integrity, repository origin, dependency verification, tests, and reproducibility establish important provenance/correctness evidence. They do not replace vulnerability analysis, threat modeling, runtime hardening, or organizational approval.
1. Security controls form a chain, not a checklist
Consider the capstone as six linked control layers. A weakness at one layer can invalidate confidence produced by another:
| Layer | Control | Evidence | Common false assumption |
|---|---|---|---|
| Bootstrap | Wrapper distribution + JAR checksums | Pinned properties + independent hash | “Wrapper is in Git, therefore trusted.” |
| Origin | Central repositories and plugin repositories | Settings policy and dependency reports | “HTTPS proves correct repository namespace.” |
| Integrity | Dependency verification metadata | Reviewed checksums/signatures where used | “Version lock means bytes are authentic.” |
| Execution | Toolchain, tests, task wiring | JDK/tool report + test XML + dry-run | “Build green means intended tests ran.” |
| Publication | Coordinates, POM/module metadata, staged checksum | Repository tree + metadata + SHA-256 | “Upload success means interoperable contract.” |
| Delivery | Promotion + caches + credentials | Promotion log, cache/secret policy | “Same version string means same artifact.” |
2. Revalidate executable bootstrap identity
Before trusting any new evidence, recheck the bootstrap:
grep '^distributionUrl=' gradle/wrapper/gradle-wrapper.properties
grep '^distributionSha256Sum=' gradle/wrapper/gradle-wrapper.properties
sha256sum gradle/wrapper/gradle-wrapper.jar
printf 'expected wrapper jar: 7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d
'
./gradlew -version
If a Wrapper file changes, invalidate prior bootstrap evidence even if application source is unchanged. Executable build logic is part of the supply chain.
3. Prove dependency/plugin origin separately from version selection
Version governance answers “which version?” Repository policy answers “from where?” Dependency verification answers “which bytes?” Keep them distinct:
./gradlew :core:dependencyInsight \
--dependency org.apache.commons:commons-lang3 \
--configuration runtimeClasspath
sed -n '1,180p' settings.gradle.kts
sed -n '1,260p' gradle/verification-metadata.xml
For this capstone, project repositories are forbidden and Maven Central is the declared external dependency source. Core Gradle plugins ship with the pinned Gradle distribution; no community plugin is required. That reduces—but does not eliminate—the executable supply-chain surface.
4. Prove declared intent and resolved state
Inspect the platform constraints, versionless catalog aliases, lockfiles, and resolved graph together. None is a universal substitute for the others:
sed -n '1,220p' platform/build.gradle.kts
cat gradle/libs.versions.toml
find . -name gradle.lockfile -print -exec sed -n '1,120p' {} \;
./gradlew :core:dependencies --configuration runtimeClasspath
Expected: the catalog expresses coordinates, the platform expresses accepted versions, lock state captures selected versions for locked configurations, and dependency reports show the actual graph.
5. Validate credential containment
The mandatory path has no real credentials. Still, scan source/governance/evidence before handoff:
grep -RInE '(password|passwd|secret|token|private[_-]?key|BEGIN .*PRIVATE KEY)' \
--exclude-dir=.git --exclude-dir=.gradle --exclude-dir=.lab-gradle \
--exclude-dir=build --exclude-dir=staging-repo --exclude-dir=release-repo . || true
Review every match; words such as “secret policy” in documentation are not leaks. In production, secrets belong in the CI/credential system and should be supplied via appropriately scoped providers, never committed to build scripts, logs, Build Scans, or command history.
6. Reproducibility requires independent workspaces
Re-run the clean-room test from Lesson 2 and record:
| Variable | Workspace A | Workspace B | Must match? |
|---|---|---|---|
| Source/governance manifest | Same accepted inputs | Same accepted inputs | Yes |
| Checkout absolute path | Different | Different | No |
| Gradle User Home | Isolated A | Isolated B | No |
| Build cache | Disabled for proof | Disabled for proof | Yes: disabled |
| JDK/toolchain | 21 / release17 | 21 / release17 | Yes |
| Core JAR SHA-256 | Recorded | Recorded | Yes |
If checksums differ, do not hide the difference. Inspect ZIP entry ordering/timestamps, generated files, manifests, absolute paths, locale/timezone influence, tool/JDK drift, and undeclared environment inputs.
7. Trace promoted bytes back to source and tests
Create a concise evidence chain:
source-files.sha256
-> wrapper/JDK identity
-> dependency graph + lock/verification metadata
-> unit + integration test reports
-> staged core-1.0.0.jar SHA-256
-> staging POM/module metadata
-> promotion checksum equality
-> release core-1.0.0.jar SHA-256
-> Maven clean-consumer compile evidence
Traceability fails if any link is replaced with an assertion such as “CI was green” without the actual report/artifact identity.
8. Three claims that must not be collapsed
| Claim | What the capstone can prove | What it does not prove |
|---|---|---|
| Compiles/tests successfully | Declared source compiles and intended tests execute under recorded toolchain. | No malicious dependency, no vulnerability, or safe runtime behavior in every environment. |
| Dependency provenance/integrity policy passes | Repository policy + verification metadata match reviewed external inputs. | Publisher is benevolent, vulnerability-free, or legally acceptable. |
| Artifact reproducible/traceable | Clean builds reproduce bytes and promotion preserves exact accepted artifact. | Operational environment is secure or deployment is correctly configured. |
9. Test the main architecture tradeoffs
| Decision axis | Stricter/central choice | More flexible choice | Orbit decision and evidence |
|---|---|---|---|
| Maven vs Gradle primary model | One authoritative Gradle build | Two source builds | One Gradle build + Maven consumer to reduce drift while proving interoperability. |
| Central governance vs autonomy | Platform constraints/settings policy | Per-module versions/repos | Central dependency/repository policy; modules retain implementation/task ownership. |
| Clean room vs cache speed | Always uncached | Always warm cache | Clean-room release proof plus bounded caches for routine CI throughput. |
| Rich metadata vs Maven compatibility | Gradle Module Metadata only | POM-only lowest common denominator | Publish both; verify Maven consumer against POM contract. |
| Strict version policy vs ecosystem compatibility | Every difference rejected | Unbounded conflict resolution | Explicit constraints/locks; exceptions require documented graph evidence. |
10. Optimize only a measured critical path
Compare profile reports under the same source, JDK, test set, cache mode, and worker settings. If configuration dominates, improve configuration behavior; if one test task dominates, investigate that test path; if dependency resolution dominates only on cold agents, cache/network policy may matter. Do not disable tests, verification, or declared inputs to make the profile prettier.
After any optimization, rerun clean check, clean-room
reproducibility, staged checksum capture, and the relevant failure
drill. Performance changes are build-logic changes and can alter
correctness.
11. Evidence matrix: invariant → source → verification → failure → owner
| Invariant | Configuration source | Independent evidence | Failure signal | Owner |
|---|---|---|---|---|
| I-01 Tool identity | Wrapper properties/JAR; CI JDK policy | Wrapper hashes; -version |
Hash/version mismatch | Build platform |
| I-02 Java 17 target | JavaCompile release/toolchain | javap major 61 |
Wrong major/API compile behavior | JVM platform |
| I-03 Graph policy | Platform, catalog, lockfiles | dependencyInsight + lock diff | Unmanaged/divergent selection | Dependency governance |
| I-04 Required tests | test suites + check dependency | XML reports + dry-run | Missing/zero suite or failed test | Module owner |
| I-05 Clean build | Declared source/model only | fresh copy + isolated user home | Requires hidden local state | Build platform |
| I-06 Reproducibility | Archive/task inputs | two-workspace SHA-256 | Different accepted-output bytes | Release engineering |
| I-07 Origin/integrity | settings + verification metadata | repository model + checksum enforcement | Unexpected repo/hash | Supply-chain owner |
| I-08 Secrets | credential policy | source/evidence scan + CI controls | secret in source/log/state | Security + CI owner |
| I-09 Promotion | release procedure | stage/release SHA equality | rebuild or byte drift | Release manager |
| I-10 Cache trust | CI cache policy | writer/reader lane evidence | untrusted writer feeds trusted lane | CI platform |
| I-11 Maven boundary | published POM + Maven consumer | clean Maven compile | consumer resolution/compile mismatch | Library/API owner |
12. Reliability acceptance gate
Before failure injection, freeze a known-good evidence snapshot: source manifest, wrapper/JDK identity, dependency reports, lockfiles, verification metadata, unit/integration report paths, clean-room hashes, staged/release hashes, Maven consumer result, and profile baseline. That snapshot is the reference state for every drill in Lesson 4.
Knowledge check
Why are lockfiles and verification metadata separate?
Lockfiles capture selected versions; verification metadata validates expected artifact bytes/signatures. They answer different questions.
Does reproducible output prove dependency provenance?
No. Reproducibility says identical declared inputs/tooling reproduce bytes; it does not establish that upstream dependencies were trustworthy.
Why publish both POM and Gradle Module Metadata?
The POM supports Maven and broad ecosystem interoperability; Gradle Module Metadata can represent richer Gradle variants. Both should be inspected for the intended contract.
What must happen after a performance optimization?
Re-run correctness, test, provenance, and reproducibility evidence relevant to the change; performance cannot waive invariants.
Who should own a missing integration-test report?
The module/build owner responsible for test wiring, with CI enforcing the evidence gate. The absence is a verification failure, not merely a reporting cosmetic issue.
Why is a secret scan only one control?
Scanning may miss encoded/indirect leaks. Proper secret storage, least privilege, log hygiene, rotation/revocation, and CI policy are still required.
Official references and version notes
- Gradle 9.7.1 release notes — pinned Gradle baseline for the capstone.
- Gradle Wrapper and release checksums — wrapper/distribution identity and integrity.
- Gradle JVM toolchains — build JVM versus compiler/test launchers.
- Dependency verification — checksum/signature verification metadata and review workflow.
- Repository declarations and content filtering — dependency origin controls.
- Java testing and JVM Test Suite — unit/integration verification model.
- Maven Publish — Gradle publication to Maven repository layout and clean Maven consumption.
- Build Cache and Configuration Cache — bounded build-state reuse.
- Gradle performance guidance — measurement-first optimization and profiling.
- Apache Maven release history — Maven 3.9.16 GA consumer baseline; Maven 4.0.0-rc-6 remains pre-GA.
- Apache Maven Wrapper 3.3.4 — stable Maven Wrapper baseline.
- Maven Compiler Plugin 3.15.0 — clean Maven consumer compilation baseline.
- JUnit 6.1.3 — Java 17+ test runtime baseline.
- Apache Commons Lang release notes — Commons Lang 3.20.0 dependency baseline.
Version-sensitive statements were rechecked against primary documentation on 2026-08-24. Mandatory work remains local/free. Hosted CI, commercial build analytics, production repository managers, remote caches, and real signing/credential systems are optional integration boundaries only.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.