TN-032 β Define Mailpit Runtime Ownership and Disposable Verification Contract¶
| Field | Value |
|---|---|
| Status | Completed |
| Activity Type | Discovery and Assessment |
| Record Type | Live |
| Project | Tomcat Monitoring |
| Phase | Monitoring Integration and Runtime Deployment |
| Activity Date | 2026-08-27 |
| Recorded Date | 2026-08-27 |
| Owner | Project owner |
| Working Mode | Write |
| Authorization Status | Approved |
| Approved By | Project owner |
| Approval Date | 2026-08-27 |
π― Objective¶
Menetapkan ownership, immutable upstream identity, disposable topology, exact resources, security boundary, cleanup, dan implementation handoff Mailpit sebelum image pull atau component test diizinkan.
π Background¶
TN-031 menggantikan Gmail App Password dengan Mailpit lokal sebagai isolated SMTP capture. Mailpit merupakan runtime container baru sehingga Runtime Component Ownership Gate harus selesai sebelum source integration, image pull, atau component test.
Project owner menyetujui TN-032 untuk menentukan contract tersebut tanpa
menjalankan implementation. Working tree tomcat-monitoring dan
devops-handbook masih menyimpan perubahan TN-029 sampai TN-031 yang harus
dipertahankan.
π Scope¶
Aktivitas yang disetujui mencakup:
- memverifikasi upstream image source dan stable release Mailpit;
- menilai repository runtime, repository baru, dan direct-upstream exception;
- menentukan immutable image reference, ownership source, dan upgrade gate;
- menentukan disposable network, containers, internal endpoint, loopback ports, synthetic identity, lifecycle, rollback, serta cleanup contract;
- melakukan read-only collision inspection terhadap exact resource names dan ports; serta
- memperbarui Engineering Journal dan navigation.
Image pull, source atau validator change, dependency installation, network atau container creation, port publication, runtime execution, generated data, cleanup mutation, persistent deployment, external delivery, commit, dan push tidak termasuk.
π₯ Inputs¶
| Input | Relevant Evidence |
|---|---|
| TN-031 | Mailpit dipilih sebagai disposable SMTP capture; ownership dan immutable pin masih terbuka. |
| Official image documentation | Upstream menyediakan official Docker Hub image dan GHCR mirror dengan stable release tags. |
| Official GHCR package | v1.31.0 tersedia dengan multi-platform manifest digest dan platform-specific manifests. |
| Development host | x86_64 dengan rootless Podman 4.9.3. |
| Collision inspection | Candidate container names, network name, dan loopback ports tidak digunakan pada 2026-08-27. |
π Findings¶
Upstream identity and pinning¶
Mailpit upstream adalah axllent/mailpit. Official documentation menyatakan
Docker Hub sebagai source image resmi dan GHCR sebagai mirror. GHCR dipilih
karena halaman package resminya menyediakan immutable manifest identity yang
dapat ditelusuri tanpa bergantung pada mutable latest atau minor tag.
Identity yang dinilai dan kemudian diterima pada 2026-08-27 adalah:
| Property | Accepted Contract |
|---|---|
| Upstream source | https://github.com/axllent/mailpit |
| Registry | ghcr.io official mirror |
| Release | v1.31.0 |
| Immutable reference | ghcr.io/axllent/mailpit:v1.31.0@sha256:c96991d9bef73594c246d89ca81411d4e916f03e76a7d2d72fa2ab5dd3c9ce24 |
| Manifest scope | Multi-platform manifest list |
Observed linux/amd64 child |
sha256:29154cb86d35bcff4c0f82f185fc6720e89248b2cd2bc43f312a2b31fddd34ad |
| Mutable tags | latest, edge, dan minor-only tag dilarang sebagai runtime identity |
Tag tetap disertakan agar intent versi mudah dibaca, sedangkan digest menjadi
identity yang menentukan bytes. Implementation preflight harus membuktikan
bahwa resolved manifest, platform linux/amd64, dan reported Mailpit version
sesuai sebelum verification result diterima. Perubahan version atau digest
memerlukan assessment serta authorization baru.
Ownership assessment¶
| Option | Assessment | State |
|---|---|---|
| Existing generic runtime repository | Tidak tersedia dan tidak diperlukan oleh component lain saat ini. | Rejected |
| New generic Mailpit runtime repository | Memberi lifecycle build sendiri, tetapi berlebihan untuk disposable upstream test utility tanpa customization. | Rejected |
| Direct-upstream exception | Menjaga Mailpit sebagai bounded test dependency; no build, publication, persistent lifecycle, atau production ownership ditambahkan. | Accepted |
Pada accepted boundary, upstream memiliki image build dan release. Repository
tomcat-monitoring hanya memiliki immutable reference, disposable verification
script, temporary configuration, validation assertions, dan cleanup behavior.
Tidak ada Mailpit image yang dibangun, ditag ulang, atau dipublikasikan project.
Disposable topology¶
Host test driver
|-- http://127.0.0.1:19093 --> tm-tn033-alertmanager:9093
`-- http://127.0.0.1:18025 --> tm-tn033-mailpit:8025 API
tm-tn033-mailpit network
tm-tn033-alertmanager --SMTP--> mailpit:1025
tm-tn033-mailpit
| Resource | Exact Contract |
|---|---|
| Network | tm-tn033-mailpit |
| Mailpit container | tm-tn033-mailpit |
| Alertmanager container | tm-tn033-alertmanager |
| Mailpit network alias | mailpit |
| Mailpit SMTP | Internal mailpit:1025; never published to host |
| Mailpit API | Container 8025, host 127.0.0.1:18025 only |
| Alertmanager API | Container 9093, host 127.0.0.1:19093 only |
| Sender | alertmanager@tomcat-monitoring.invalid |
| Recipient | operator@tomcat-monitoring.invalid |
| Storage | No named volume atau host bind; disposable container storage only |
| Restart | Disabled; no persistent service behavior |
| External relay | Disabled and prohibited |
The .invalid domain keeps sender and recipient synthetic. The API and
Alertmanager ports are published only because the host test driver must inject
alerts and inspect captured messages. SMTP remains internal to the dedicated
network.
Read-only inspection found no existing exact container or network with these
names and no listener on ports 18025 or 19093. This observation is not a
reservation; implementation must repeat collision preflight immediately before
resource creation.
Lifecycle and cleanup contract¶
Implementation must use a temporary directory created with mktemp -d for the
temporary Alertmanager configuration and bounded evidence. A cleanup trap must
target only the two exact containers, exact network, and resolved temporary
directory. Cleanup must run after success, failure, or interruption.
The implementation record must distinguish:
- preflight absence and port availability;
- image acquisition using the accepted immutable reference;
- disposable network and container creation;
- Mailpit API readiness and Alertmanager readiness;
- synthetic firing and resolved capture assertions;
- exact cleanup; and
- post-cleanup absence plus closed loopback ports.
Image removal is not part of automatic cleanup. Removing the pulled image is a separate destructive action requiring exact digest inspection and explicit authorization. Rollback for source changes is a reviewed source reversal, not a runtime resource replacement; no persistent state exists to restore.
β οΈ Risks¶
| Risk | State | Mitigation or Follow-up |
|---|---|---|
| Mutable upstream tag changes silently | Mitigated by accepted contract | Pin version plus manifest digest; verify platform child and reported version. |
| Direct upstream becomes an unmanaged production dependency | Mitigated by boundary | Limit exception to disposable lab verification; reopen ownership gate for persistent or reusable use. |
| Mailpit API is exposed beyond the host | Mitigated by contract | Bind API only to 127.0.0.1; do not publish SMTP. |
| Local untrusted input reaches Mailpit | Mitigated by contract | Dedicated network, synthetic bounded messages, no external relay, and exact test lifetime. |
| Candidate port becomes occupied after assessment | Open implementation risk | Repeat collision preflight immediately before creation and fail closed. |
| Cleanup removes unrelated resource | Mitigated by contract | Exact TN-scoped names, ownership labels, collision failure, and no wildcard cleanup. |
| Image remains in local store | Accepted pending separate decision | Do not conflate disposable runtime cleanup with destructive image removal. |
β Open Questions¶
| Question | State | Owner | Closure Condition | Blocked Activity |
|---|---|---|---|---|
Apakah direct-upstream exception dengan exact v1.31.0 digest diterima? |
Answered | Project owner | Direct-upstream exception dan immutable reference diterima pada 2026-08-27 | N/A; implementation tetap memerlukan authorization terpisah |
| Apakah image harus dihapus setelah verification? | Deferred | Project owner | Exact local image identity tersedia dan destructive cleanup authorization diberikan | Image cleanup only; tidak memblokir component verification |
| Apakah Mailpit akan menjadi persistent atau reusable runtime? | Deferred | Project owner | Requirement baru tersedia; ownership gate dibuka kembali | Future persistent or shared use |
π‘ Recommendation¶
Terima direct-upstream exception dengan exact immutable reference
ghcr.io/axllent/mailpit:v1.31.0@sha256:c96991d9bef73594c246d89ca81411d4e916f03e76a7d2d72fa2ab5dd3c9ce24.
Gunakan topology, names, ports, synthetic identities, no-volume boundary, dan
cleanup contract TN-032 hanya untuk disposable lab verification.
Dengan Decision Gate diterima, TN-032 ditutup. Buka TN-033 untuk source implementation serta isolated Mailpit capture verification dengan authorization terpisah untuk source changes, exact image pull, disposable network/containers, loopback ports, runtime test, dan exact cleanup.
π€ Decision Handoff¶
Project owner menerima direct-upstream exception dan exact immutable reference
pada 2026-08-27. Upstream memiliki image build serta release, sedangkan
tomcat-monitoring memiliki immutable reference, disposable verification
script, temporary configuration, assertions, dan exact cleanup behavior.
Acceptance menutup Runtime Component Ownership Gate hanya untuk disposable lab verification. Persistent, reusable, production, retagged, atau project-built Mailpit tetap memerlukan ownership gate baru. Decision ini tidak mengizinkan image pull, source implementation, container execution, port publication, atau cleanup mutation.
βοΈ Commands Executed¶
# /home/eddywiyatno/git/tomcat-monitoring
git status --short --branch && uname -m && command -v podman && podman --version
ss -ltn '( sport = :18025 or sport = :19093 )'
podman container exists tm-tn033-mailpit; printf 'mailpit_container=%s\n' "$?"; podman container exists tm-tn033-alertmanager; printf 'alertmanager_container=%s\n' "$?"; podman network exists tm-tn033-mailpit; printf 'network=%s\n' "$?"
# Approved read-only retry outside the restricted sandbox
podman --version; podman container exists tm-tn033-mailpit; printf 'mailpit_container=%s\n' "$?"; podman container exists tm-tn033-alertmanager; printf 'alertmanager_container=%s\n' "$?"; podman network exists tm-tn033-mailpit; printf 'network=%s\n' "$?"; ss -ltn '( sport = :18025 or sport = :19093 )'
# /home/eddywiyatno/git/devops-handbook
git status --short --branch && sed -n '1,340p' docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-031-replace-gmail-lab-delivery-with-local-mailpit-capture-contract.md
git diff --check && git status --short --branch
sed -n '1,420p' docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-032-define-mailpit-runtime-ownership-and-disposable-verification-contract.md
rg -n '^## |TN-032|c96991d9bef73594c246d89ca81411d4e916f03e76a7d2d72fa2ab5dd3c9ce24|29154cb86d35bcff4c0f82f185fc6720e89248b2cd2bc43f312a2b31fddd34ad' docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-032-define-mailpit-runtime-ownership-and-disposable-verification-contract.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/index.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/.pages
rg -n '[[:blank:]]+$' docs/projects/tomcat-monitoring
rg -n 'BEGIN (RSA |EC |OPENSSH )?PRIVATE KE[Y]|bearer[_]token=|^[[:space:]]*passwor[d]=|https?://[^[:space:]/]+:[^[:space:]@]+@|[[:alnum:]._%+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}' docs/projects/tomcat-monitoring
test -f docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-032-define-mailpit-runtime-ownership-and-disposable-verification-contract.md && test -f docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-031-replace-gmail-lab-delivery-with-local-mailpit-capture-contract.md
command -v mkdocs || true
rg -n -C 2 'Mailpit|ownership|immutable' docs/projects/tomcat-monitoring/index.md docs/projects/tomcat-monitoring/architecture/index.md docs/projects/tomcat-monitoring/development/index.md docs/projects/tomcat-monitoring/infrastructure/index.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/index.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-032-define-mailpit-runtime-ownership-and-disposable-verification-contract.md
git diff --check
rg -n -C 2 'Mailpit.*(pending|not determined)|ownership.*pending|Decision Gate masih menunggu|TN-032 tetap `In Progress`|Pending project-owner' docs/projects/tomcat-monitoring
rg -n 'Status \| Completed|Direct-upstream exception.*Accepted|c96991d9bef73594c246d89ca81411d4e916f03e76a7d2d72fa2ab5dd3c9ce24|TN-032-define-mailpit' docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/TN-032-define-mailpit-runtime-ownership-and-disposable-verification-contract.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/index.md docs/projects/tomcat-monitoring/engineering-journal/monitoring-integration-and-runtime-deployment/.pages
rg -n '[[:blank:]]+$' docs/projects/tomcat-monitoring
git status --short --branch && git diff --stat
The initial Podman and socket inspection failed inside the restricted sandbox because the runtime directory and netlink socket were unavailable. The exact read-only check was repeated with approval outside the sandbox and succeeded; it did not create, start, stop, or remove any resource.
Official Mailpit Docker documentation, GHCR package metadata for v1.31.0,
upstream release information, and relevant upstream security advisories were
reviewed through read-only web access.
π§Ύ Outcome¶
Assessment menghasilkan direct-upstream recommendation, exact immutable image, repository boundary, disposable topology, security controls, resource names, ports, lifecycle, rollback, dan cleanup contract. Candidate resources tidak berkonflik ketika diperiksa pada 2026-08-27.
Project owner menerima direct-upstream exception, exact immutable image, repository boundary, disposable topology, security controls, resource names, ports, lifecycle, rollback, dan cleanup contract. Runtime Component Ownership Gate selesai untuk disposable lab verification.
Tidak ada source, image, container, network, port publication, runtime data, cleanup mutation, commit, atau push yang dibuat atau dijalankan.
Navigation, heading structure, digest transcription, link targets, trailing
whitespace, dan git diff --check lulus. Sensitive-data scan hanya menemukan
dua synthetic .invalid addresses yang memang menjadi contract test; tidak ada
credential atau personal address. MkDocs render tidak diverifikasi karena
executable tidak tersedia dan dependency installation tidak diotorisasi.
βοΈ Next Steps¶
Buka TN-033 untuk source implementation dan isolated Mailpit capture verification. Scope tersebut memerlukan authorization terpisah untuk source changes, exact image pull, disposable network dan containers, loopback ports, runtime test, serta exact cleanup.