Email Integration -- Current-System Documentation Retrofit (Revision 1)
A project-completion deliverable. After the email integration’s implementation lands across all repositories, the current-system/ documentation tree (and the related domain/information-model/ tree) must be updated to reflect the deployed state. Aligned with the Revision 1 goal.md acceptance criterion #10 (Documentation is current) and the related runtime-design-review.md proposal under reviews/R1/.
Revision 1 note. Supersedes the prior current-system retrofit (now superseded by this document). Substantive changes:
- Inventory expanded to cover the Corporate Resource Group as a runtime instance group, the
arda.ardamails.comzone, the Postmark service overview and API observations note, the Postmark thin-wrapper constructs, thetools/gha-secret.tstransition utility, and drift-detection conventions.- Authentication retrofit: existing pages that reference API-gateway-level authorisers must be reconciled with the in-component (Ktor) authentication scheme adopted by the email service.
- Phase numbering removed. Retrofit happens once at project completion (no “after Phase 6” — the project’s final phase is
5b, but the retrofit trigger is project-completion, not a specific phase).- Architecture reconciliation: the existing
current-system/architecture/tree is enumerated as a touchpoint; pattern descriptions for instance groups, declarative-by-default operator scripts, third-party-API thin-wrappers, and AWS-account-vs-instance-group decoupling are aligned with the practices adopted in this project.- Per-decision references updated:
DQ-R1-NNNseries joins the existingDQ-001..013andDQ-201..208series.
Principle
Section titled “Principle”current-system/ describes what is, not what was designed. Retrofit is a snapshot of the deployed system. Any divergence between the design documents (under roadmap/in-progress/email-integration/revision-1/) and the implementation is resolved in favour of the implementation when retrofitting; significant divergences are recorded in the project’s decision log first.
Scope and ownership
Section titled “Scope and ownership”Retrofit happens once at project completion as part of the standard Arda lifecycle (per CLAUDE.md Project Workflow § Project Lifecycle, step 4). No incremental updates during implementation phases.
The shop-access functional domain sits at the bottom of the dependency hierarchy (see functional/index.md; the functional-tld.drawio.svg diagram in public/assets/diagrams/ is rendered there). The retrofit reaffirms this — the email module must not introduce upward dependencies into procurement, resources, or reference-data domains.
The Corporate Resource Group is a new instance group introduced by this project (founding member: Free Kanban Tool). It does not sit in the current-system/functional/ tree alongside Application Runtime modules; it is documented under current-system/oam/corporate/ (and as part of the runtime instance-group taxonomy under current-system/runtime/). The functional domain hierarchy is unaffected by Corporate.
Touchpoint inventory
Section titled “Touchpoint inventory”The pages below are identified by:
- Grepping the
current-system/tree for shop-access references and for two reference modules: the existingpdfRendermodule (similar location, different shape) and persistence-bearing modulesItem(functional/reference-data/item/index.md) andOrders(functional/procurement/, withorder-lifecycle.md,order-line-management.md,order-implementation-notes.md, etc.). - Surveying the new touchpoints introduced by Revision 1: instance groups, Corporate Resource Group, Postmark service, Postmark thin-wrappers, drift detection, and the
tools/operator-utility convention.
The pdfRender module has no persistence, no information model, and no lifecycle workflows, so it does not surface most of the touchpoints a stateful module needs. The Item and Orders precedents are a closer fit for the email module’s documentation footprint.
Each row will be revisited at retrofit time; some may be no-ops if the design intent already matches the implementation.
Pages to create
Section titled “Pages to create”In current-system/functional/shop-access/
Section titled “In current-system/functional/shop-access/”| Path | Purpose | Model after |
|---|---|---|
email-module.md | Module reference page: purpose, integrations, block diagram, public interface (EmailConfigurationService, EmailJobService), key types, HOCON configuration, ESO secret bindings, Helm contributions. Note: in-component authentication for email-service routes (no API-gateway authoriser). | shop-access/pdf-render-module.md (structure) and reference-data/item/index.md (persistence-bearing additions: bitemporal mention, DataAuthority pattern reference, persistence block diagram nodes) |
email-configuration-lifecycle.md | Provision flow (Scenario 1), bounded DNS verification (Scenarios 1b.1/.2/.3), lock/unlock (Scenario 6), decommission (Scenario 4). Sequence diagrams + UC references | procurement/order-lifecycle.md |
email-job-lifecycle.md | Send flow (Scenario 2), webhook event handling (Scenario 3), cancel (Scenario 5.a), resend (Scenario 5.b). Sequence diagrams + UC references | procurement/order-lifecycle.md |
email-implementation-notes.md | Data-model summary (entity fields, status enums); persistence schema (DDL highlights for email_configuration and email_job); bitemporal application policy (per DQ-240.a / DQ-250.c resolution); cross-Universe rule application; encryption envelope handling; cross-cutting links (cross-cutting-design.md OAM, audit). Implementation-internal notes that don’t belong in the public module page | procurement/order-implementation-notes.md |
index.md (optional) | Domain index for shop-access modules. Currently absent; consider creating to introduce both pdf-render and email together | None (new) |
In current-system/oam/postmark-service/
Section titled “In current-system/oam/postmark-service/”| Path | Purpose | Model after |
|---|---|---|
index.md | Postmark service overview: account topology (PostmarkProd / PostmarkNonProd), credential storage (1Password as system of record; per-partition Secrets Manager; ESO-projected at runtime), the Postmark Console as the primary OAM surface, drift-detection cadence and findings. | New page; sibling-of-similar-shape under current-system/oam/ |
postmark-api-observations.md | Postmark API surface design intent, captured during Revision-1 implementation: authentication models for both API and Webhooks, error model, idempotency conventions, retry policy, webhook payload shapes, version-pin assumptions. Written so future implementors do not re-derive these from third-party documentation. | New page; goal.md acceptance criterion #9 |
free-platform-server.md | Operational reference for the Free Kanban Tool’s Postmark server (the Corporate Resource Group’s founding consumer): server identity, sending domain (freekanban.arda.ardamails.com), token storage location (Free Kanban Generator Postmark 1Password item), drift assertions specific to this server. | None (new); cross-references current-system/oam/corporate/ for the Corporate-instance view |
In current-system/oam/corporate/
Section titled “In current-system/oam/corporate/”| Path | Purpose | Model after |
|---|---|---|
index.md | Corporate Resource Group overview: purpose, instance-group placement (peer to Application Runtimes), founding member (Free Kanban Tool), AWS-account placement note (Root account for now), reserved-name discipline. | New page |
free-kanban-tool.md | Free Kanban Tool operational reference: sending domain, Postmark server identity, DNS records (DKIM TXT + Return-Path CNAME), CDK construct identity, Corporate CLI invocation, drift-detection workflow link. | New page |
In current-system/oam/
Section titled “In current-system/oam/”| Path | Purpose | Model after |
|---|---|---|
drift-detection.md | Convention for periodic drift / integration tests. What “drift” means in each resource category; where the tests live (per-script CI workflow, scheduled trigger); how failures are surfaced (auto-opened GitHub issue with a fixed label set). Catalogue of current drift checks: Corporate Postmark, future Application Runtime Postmark, future 1Password vault assertion. | New page; informed by runtime-design-review.md § 5.5 |
operator-scripts.md | Generalised contract for operator-facing scripts (robust, self-defined, self-documenting). Catalogue of principal operator scripts: amm.sh (existing), deploy-root.sh (existing), tools/corporate-cli.ts (new). Distinction between principal scripts and tools/ ad-hoc utilities (e.g., tools/gha-secret.ts). | New page; informed by runtime-design-review.md § 5.3 / § 5.4 |
In current-system/runtime/
Section titled “In current-system/runtime/”| Path | Purpose | Model after |
|---|---|---|
instance-groups.md | Top-level taxonomy of instance groups: Application Runtimes (with pointer to platform-structure.md), Platform-level (Root, OAM), Corporate (with pointer to current-system/oam/corporate/). Naming and lifecycle conventions per group. AWS-account-vs-instance-group decoupling note. | New page; informed by runtime-design-review.md § 5.6 |
In current-system/runtime/iac/
Section titled “In current-system/runtime/iac/”| Path | Purpose | Model after |
|---|---|---|
external-resources.md | How external resources (Postmark accounts, 1Password vaults, GitHub organisation, etc.) are represented in the infrastructure repository. Distinction between referenced (Arda does not create) and API-managed (Arda creates / reconciles via API). Worked examples: Postmark accounts, 1Password vaults. | New page; informed by runtime-design-review.md § 5.1 |
instance-modeling.md | How the instances/ directory is structured. Cross-instance reference convention: direct TS import for compile-time constants; importValues(forElement) pattern for runtime-resolved values. platform/ vs instances/ distinction. | New page; informed by runtime-design-review.md § 5.2 |
tools.md | Convention for the tools/ directory: ad-hoc operator utilities (e.g., tools/gha-secret.ts). Inclusion criteria; relationship to instance-driven CLIs. | New page; informed by runtime-design-review.md § 5.4 |
root.md | Root-instance reference: ardamails.com zone, NS-delegation table to other instance groups, the existing root DNS structure. Sister-page to current-system/oam/corporate/index.md. | New page; informed by runtime-design-review.md § 5.7 |
failure-mode-analyses/ | Folder split from the existing iac/failure-mode-analysis.md (one file per analysed script: amm.md, plus corporate-cli.md and postmark-foundations.md as their analyses are produced). New index.md for the folder. | The existing single-file analysis becomes amm.md inside the folder |
In domain/information-model/
Section titled “In domain/information-model/”| Path | Purpose | Model after |
|---|---|---|
domain/information-model/<category>/email-configuration.md | Domain-level entity definition: class diagram, lifecycle, reference relationships, bitemporal classification. Category TBD at retrofit time — candidates: operations/ (configured tenant capability), assets/ (durable per-tenant resource), or a new shop-access subsection. EmailConfiguration is not transactional; it’s a tenant-scoped resource whose lifecycle is provisioning + verification + decommission. | transactions/purchase-orders.md (class diagram + relationships pattern); category-level index.md files for the chosen home |
domain/information-model/transactions/email-job.md | Domain-level entity definition: EmailJob is a transactional record (submit → status progression → terminal). | transactions/purchase-orders.md |
Pages to update
Section titled “Pages to update”| Path | Update |
|---|---|
current-system/functional/index.md | Confirm the shop-access section’s “Email” bullet matches the delivered module’s purpose; add a link to shop-access/email-module.md (and to the lifecycle / implementation-notes pages) next to the existing shop-access/pdf-render-module.md link. |
current-system/functional/api-endpoint-catalog.md | Add the three email module endpoints under a new sub-section: /v1/shop-access/email/email-configuration/*, /v1/shop-access/email/email-job/*, /v1/shop-access/email/postmark-events. Verify against the deployed OpenAPI. Note that authentication is in-component (Ktor) for each route — no API-gateway authoriser dependency. |
current-system/architecture/patterns/general/naming-conventions.md | Confirm any module-naming examples that include shopAccess — add shopAccess.email if the file enumerates modules. Reconcile with the reserved-name discipline (arda and partition names reserved at the ardamails.com level). |
current-system/architecture/structure/viewpoint-mapping.md | If shop-access is enumerated, add the email module entry. If instance-group taxonomy is part of the viewpoint mapping, reflect Application Runtime, Platform-level, and Corporate as peer instance groups. |
current-system/architecture/structure/design-framework.md | Verify any module-tier examples accommodate the email module’s L1/L2/L3/L4 layering. Add (or reconcile) a section on third-party-API thin-wrappers as a construct shape distinct from L2 / L3 CDK Constructs. |
current-system/architecture/structure/module-concept.md | Verify the documented module-concept handles the email module’s two-service shape (EmailConfigurationService + EmailJobService in one module). |
current-system/architecture/patterns/ | Reconcile pattern descriptions with the practices adopted in this project. At minimum: declarative-by-default operator scripts, cross-instance reference convention (TS import for constants; importValues for runtime-resolved values), thin-wrapper construct shape (platform/constructs/<provider>/), AWS-account-vs-instance-group decoupling. New worked examples may be drawn from this project. |
current-system/oam/service-monitoring.md | Document the email-module metrics (email_send_total{tenant, status}, email_provisioning_duration_seconds, etc.) and operator alerts (email_configuration_pending_stale, email_configuration_provisioning_stuck, drift-detection auto-issue) per the cross-cutting design. Cross-link the Postmark Console as the primary OAM surface for delivery diagnostics. |
current-system/oam/security/secrets-vault.md | If existing entries enumerate ESO-managed secrets, add {fqn}-I-EmailPostmarkAccountToken and {fqn}-I-EmailEncryptionKey. Add the OP_SERVICE_ACCOUNT_TOKEN GitHub Actions secret as a related-but-separate credential surface. |
current-system/oam/security/ | Reconcile any pages on credential management with the 1Password-as-system-of-record pattern. The Free Kanban Generator Postmark 1Password item is a worked example of a credential never persisted to AWS Secrets Manager. |
current-system/runtime/dns-structure.md | Add the ardamails.com mail root, the arda.ardamails.com Corporate sending zone, and per-partition mail sub-zones; confirm the diagram matches the deployed Route53 hierarchy. Capture the NS-delegation pattern from Root to each peer zone. |
current-system/runtime/index.md | If the runtime principles page authored in this project’s planning has not yet landed under current-system/, the retrofit incorporates it (or merges its content). The principle list (1: repo as platform reference; 2: IaC unit-tested; 3: operator-driven scripts; 4: drift detection; 5: instance groups; 6: code follows the CDK hierarchy) is the canonical version. |
current-system/runtime/iac/index.md | Update the IaC tools listing to include the third-party-API SDKs in use (Postmark client, GitHub Octokit, 1Password SDK). Update the directory map to reflect tools/ and the new instances/Corporate/, instances/Root/ directories. Reflect the platform/constructs/<provider>/ thin-wrappers as a construct category sibling to xgress/, compute/, etc. |
current-system/runtime/iac/apps.md | Generalise from “Infrastructure + Partition” Apps to “one or more top-level resources for a specific instance.” Note that some instances (Corporate, Root) deploy zero AWS-CDK stacks but still have an App-equivalent. |
current-system/runtime/iac/constructs.md | Reconcile with the third-party-API thin-wrapper convention at platform/constructs/<provider>/. The thin-wrappers follow a leaner shape than full CDK L2 constructs. |
current-system/runtime/iac/stacks.md | Add a section on Stacks for third-party services (where the exportDefinition / exportValues machinery is replaced by a typed result object written to 1Password or a context file). |
current-system/runtime/iac/orchestration.md | Rename to scope explicitly to amm.sh. Move the operator-script principles (operator-driven, robust, self-defined, self-documenting) into the new current-system/oam/operator-scripts.md page. |
current-system/runtime/platform-structure.md | Re-frame the document title and opening to “Application Runtime Platform Structure”; add a final section pointing to current-system/runtime/instance-groups.md for the broader instance-group taxonomy (Root, OAM, Corporate as peers). |
current-system/runtime/environments.md | Same re-framing — this page covers Application Runtime environments only. Add a leading note that Corporate-instance “environments” exist (e.g., the production Free Kanban Tool) but follow a different shape. |
current-system/data-model/index.md | Currently a stub. If the page is fleshed out before retrofit, ensure email entities are enumerated; otherwise no action. |
domain/information-model/<chosen-category>/index.md | When email-configuration.md and email-job.md are added (above), update the category index page to list them in the entity table. |
domain/information-model/index.md | Verify the top-level information-model TOC reflects the new entities; usually no-op if categories are auto-indexed by Starlight. |
Pages to verify (likely no-op)
Section titled “Pages to verify (likely no-op)”| Path | Reason to check |
|---|---|
current-system/architecture/patterns/persistence/data-authority-pattern.md | Verify the cross-Universe rule documented during this project (no FK across services; per-service inTransaction) is still accurate after the email module’s EmailConfigurationUniverse and EmailJobUniverse are deployed. |
current-system/architecture/patterns/persistence/bitemporal-persistence.md | Verify the bitemporal pattern application documented for the email module (per DQ-240.a / DQ-250.c) is consistent with the canonical pattern. Special case: the EmailJob webhook events use Postmark wire timestamp as effective_as_of while recorded_as_of = now() — if novel for Arda, consider a short note. |
current-system/architecture/patterns/persistence/universe-design.md | Verify the cross-Universe rule + per-service Universe ownership rule documented during this project is accurately reflected. |
current-system/architecture/patterns/persistence/parent-child-persistence.md | No-op expected; email module has no parent-child entity relationship. |
current-system/architecture/patterns/persistence/table-mappings.md | Verify if the page enumerates table-to-entity mappings; if so, add email_configuration and email_job. |
current-system/architecture/patterns/persistence/exposed-patterns.md | Verify if any patterns documented here changed during the email module implementation. |
current-system/context/system-context.md | Verify Postmark is now listed as an integrated external system; add 1Password as an integrated external system if it is not already enumerated (the email integration introduces 1Password as a first-class external resource consumed by the IaC pipeline). |
current-system/context/cloud-providers.md | Verify Postmark is listed alongside other cloud / SaaS providers. |
current-system/runtime/url-naming.md | Verify the /v1/shop-access/email/* path scheme is consistent with the documented URL convention. Confirm the arda.ardamails.com and freekanban.arda.ardamails.com naming is consistent with the DNS-naming convention. |
current-system/runtime/network-routing.md | Verify the inbound auth narrative is consistent with the in-component (Ktor) authentication adopted by the email service; if the page asserts API-gateway-level authorisers as universal, reconcile. |
current-system/runtime/mtls.md | No-op expected; the email service uses HTTPS over the existing routing path. Verify nothing in this page implies the email module requires mTLS. |
domain/information-model/meta/entity-references.md | Verify the cross-Universe reference shape used by EmailJob.EMAIL_CONFIG_REFERENCE_* (eId + rId + cached display fields, no FK) is accurately reflected as a worked example. |
domain/information-model/common/identity.md | No-op expected; email entities use the standard EntityId / Binding model. |
Diagrams to update
Section titled “Diagrams to update”| Path | Update |
|---|---|
public/assets/diagrams/functional-tld.drawio.svg | Already mentions “Email” as a Shop Access module (verified). No update expected unless module subdivision changes during implementation. |
public/assets/diagrams/mail-dns-structure.drawio.svg | Verify it matches the deployed Route53 hierarchy. The Revision-1 hierarchy has ardamails.com (Root), arda.ardamails.com (Corporate), and per-partition mail sub-zones ({partition}.ardamails.com). Update the diagram if it predates the Corporate split. |
public/assets/diagrams/instance-groups.drawio.svg (new) | New diagram showing Application Runtimes, Platform-level (Root, OAM), and Corporate as peer instance groups; the AWS-account placement note inside the Corporate box. |
Class diagram(s) inside domain/information-model/<category>/email-configuration.md and transactions/email-job.md | New PlantUML class diagrams modeled after transactions/purchase-orders.md. Validate via the plantuml-diagrams skill at retrofit time. |
Note on the precedent shift
Section titled “Note on the precedent shift”The original inventory (R1) was anchored on the pdfRender module, which has no persistence and no internal information model. R2 expanded the inventory after observing how persistence-bearing modules (Item, Orders) are documented:
- Per-behavior pages. Major workflows (provisioning lifecycle, send lifecycle) get their own pages alongside the module-level page, mirroring
procurement/order-lifecycle.md,order-creation.md,order-line-management.md. - Implementation-notes page. Captures schema-level + bitemporal-application choices that don’t belong in the public module page, mirroring
procurement/order-implementation-notes.md. - Domain information-model entries. Persisted entities get domain-level entity definitions under
domain/information-model/<category>/. Currentlytransactions/purchase-orders.mdis the worked example;email-job.mdfollows the same pattern.
EmailConfiguration’s classification (operations/ vs assets/ vs new) is left for retrofit-time decision because the canonical placement of “configured tenant capability” entities is not yet established in the domain model.
Revision 1 adds three additional precedent shifts:
- Instance-group documentation. The Corporate Resource Group is documented under
current-system/oam/corporate/(operational view) and undercurrent-system/runtime/instance-groups.md(taxonomy view). The pattern can be reused for future instance groups (OAM when defined; future Corporate sub-groups). - Third-party-API documentation. Postmark is the first third-party API for which Arda creates resources via IaC;
current-system/oam/postmark-service/(operational view) andcurrent-system/runtime/iac/external-resources.md(pattern view) are the worked examples. - Drift-detection documentation. A new page
current-system/oam/drift-detection.mdcaptures the convention; the Corporate Postmark drift workflow is the founding instance.
Process at retrofit time
Section titled “Process at retrofit time”- Walk the inventory above. For each row, decide create / update / no-op based on the deployed implementation.
- For each create / update: produce a draft, then run
make pr-checksin thedocumentationworktree. - Move project documents from
roadmap/in-progress/email-integration/toroadmap/completed/email-integration/perCLAUDE.mdProject Lifecycle step 4. Note that the original (pre-revision) and revision-1 sub-tree both move; the relationship between them is preserved. - Update internal links in moved documents (e.g., scenario references) if the move changes relative paths.
- Open a single PR (or one per repo if more than one repository is touched) with the standard CHANGELOG entries.
Out of scope for retrofit
Section titled “Out of scope for retrofit”- Re-litigating design decisions. The decision log is frozen at project completion; new questions surfaced during retrofit are recorded as follow-ups.
- Refactoring the
current-system/structure beyond the touchpoints inventoried above. Larger restructuring is a separate effort. - Cross-domain documentation (e.g., procurement consumers of the email module). Procurement’s adoption is a downstream project that owns its own documentation updates.
- Documentation for OAM capabilities outside the email integration (the wider OAM tooling roadmap is separate).
References
Section titled “References”- Project goal
- Architecture overview
- Phase structure
- Cross-cutting design
- Runtime documentation design review — the proposal that drives much of the runtime-section reconciliation enumerated above
- Decision log — including
DQ-R1-NNNRevision-1 entries
Copyright: © Arda Systems 2025-2026, All rights reserved