Specification: Sending Library (Phase 1)
Specification: Sending Library (Phase 1)
Section titled “Specification: Sending Library (Phase 1)”Driving document for the implementing engineer. Scope: the common-module
worktree at projects/invitation-mail-server-worktrees/common-module (branch
jmpicnic/invitation-mail-server). Satisfies
requirements.md; verified per
verification.md. The construct-level blueprint is
Design §12 — library tables — this
specification sequences it and adds process gates; it does not restate file
contents.
Skills to load: kotlin-coding, unit-tests-backend, build-core-modules.
Worktree Strategy
Section titled “Worktree Strategy”Single worktree, single agent — no task worktrees needed.
T1.1 — Lift the Postmark send surface
Section titled “T1.1 — Lift the Postmark send surface”Move from operations (source paths in
Design §12 — PostmarkEmailSender + PostmarkServerProxy) into
lib/src/main/kotlin/cards/arda/common/lib/infra/email/postmark/:
wire types (PostmarkSendEmailRequest/Response, PostmarkSendAttachment),
SendEmailOutcome, the stateless sendEmail proxy, and fromHeader.
Package changes only; behavior byte-identical (REQ-LIB-002, REQ-LIB-007).
Lift means copy into common-module in this phase; deletion of the
operationsoriginals happens in Phase 3 (adoption), keeping the two PRs independently mergeable.
Verify: make build compiles; lifted serialization pin (BV-4-04) green.
T1.2 — Public API surface
Section titled “T1.2 — Public API surface”Create EmailMessage/EmailAttachment, EmailServer, SendRetryPolicy,
EmailSenderFactory, EmailSender interface, and PostmarkEmailSender
(retry core lifted from operations service/EmailSender.kt, generalized to
token-from-EmailServer + optional hooks) per
Design §8 Key Elements (REQ-LIB-001, 003–006, 008).
Verify: BV-3-01/02, BV-4-01/02/03, BV-7-02 green with MockEngine.
T1.3 — Component config binding
Section titled “T1.3 — Component config binding”EmailConfig.fromConfig + lazy emailConfiguration in
ConfigurationProvider, mirroring globalDsConfiguration
(REQ-LIB-009/010).
Verify: BV-2-01/02 green.
T1.4 — Test dependency
Section titled “T1.4 — Test dependency”Add ktor-client-mock (testImplementation, existing Ktor version) to
gradle/libs.versions.toml. No runtime dependency changes (REQ-LIB-011).
T1.5 — Quality gate and release prep
Section titled “T1.5 — Quality gate and release prep”- Full gate:
make build(Kover thresholds),make clqLint. - kotlin-coding review pass over every new line (monadic single-exit,
unitify(), no redundant construction) — non-negotiable per workspace conventions. - CHANGELOG entry under
Added(direct-edit model): one bullet, intent and outcome (new email-sending library + config binding).
STOP — review before PR
Section titled “STOP — review before PR”Present the diff summary, gate results, and CHANGELOG entry. Do not push or
open the PR until the user approves. After approval: push, open PR, run
/pr-steward. Merge (after approval) publishes 13.2.0 — the Phase 3 gate.
Acceptance Checklist
Section titled “Acceptance Checklist”- All REQ-LIB-001..011 satisfied; BV rows in verification.md implemented and green.
- No new runtime dependencies; single artifact unchanged.
- Wire-format golden pin proves serialization identical to pre-lift
operationsclient. - Kover ≥ 67% instruction / 73% line;
make clqLintgreen. - kotlin-coding review pass done.
- No
includeBuild/ absolute-path strays staged. - CHANGELOG
Addedentry present; PR merged; 13.2.0 visible on GitHub Packages.
Open Questions and Decisions
Section titled “Open Questions and Decisions”| # | Question | Options | Recommendation | Decision |
|---|---|---|---|---|
| 1 | Package for fromHeader — with the message model (infra/email) or beside sanitizeHeader (api/headers)? | (a) infra/email (b) api/headers | (a) — it is email-domain formatting, not header transport hygiene | (a) per recommendation; revisit only if a second consumer outside email appears |
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved