Review: Add shared Postmark inbound webhook endpoint via Tailscale funnel (r2)
Verdict: APPROVED
Re-review of board item #2001 after refinement. All three issues from
review-2001-2026-08-04 have been resolved.Template Completeness
- [x] Type -- Feature
- [x] Lineage -- Standalone, follows PR #582
- [x] Repo -- ldraney/pal-e-platform
- [x] User Story -- As a platform operator / I want a shared webhook endpoint / So that inbound emails are reliably processed and queryable
- [x] Context -- Detailed background on Postmark inbound config, webhook.site expiry, security (no HMAC, Basic Auth recommended), architecture decision (shared platform service, not per-app)
- [x] File Targets -- 4 create/modify targets, 3 don't-touch targets with reasons
- [x] Feature Flag -- none
- [x] Acceptance Criteria -- 5 criteria
- [x] Test Expectations -- 3 tests (manual curl, manual email, tofu plan)
- [x] Constraints -- 6 constraints listed
- [x] Checklist -- Standard PR/tests/no-unrelated
- [x] Related -- References project page, arch note, PR #582
Traceability
- [x] arch:deployment-postmark label -- arch-deployment-postmark note exists in pal-e-docs (active architecture note)
- [x] arch note verified -- arch-deployment-postmark covers SDK/MCP deployment pattern with diagram
- [x] story:postmark-email label -- label present on board item
- [x] story note verified -- story-postmark-email-inbound exists (user-story note, active), linked from project-postmark-email user-stories section with key "inbound"
- [x] Forgejo issue -- https://forgejo.tail5b443a.ts.net/ldraney/pal-e-platform/issues/583, open
File Targets
- [x]
terraform/postmark-inbound.tf(new) -- verified: file does not exist yet. Will contain k8s deployment, configmap, service, secret, and ingress as top-level resources. Correct placement outside the per-app module. - [x]
terraform/modules/postmark/main.tf-- verified: contains postmark_server and postmark_domain resources only. Adding inbound_hook_url to postmark_server.this is a minimal change. - [x]
terraform/modules/postmark/variables.tf-- verified: currently has server_name, domain, return_path_subdomain. Adding inbound_hook_url (string, default "") is consistent. - [x]
terraform/main.tf-- verified: postmark_iss at line 168, postmark_landscaping at line 177. Issue correctly says to pass URL to ISS instance only; landscaping wired later. - [x]
terraform/modules/networking/main.tf-- correctly listed as don't-touch. Funnel pattern confirmed (9 tailscale.com/funnel annotations, ingress_class_name "tailscale"). - [x]
terraform/dns.tf-- correctly listed as don't-touch. - [x]
terraform/modules/postmark/versions.tf-- correctly listed as don't-touch. Only declares postmark provider. Kubernetes provider is at top level (versions.tf line 11-12, providers.tf line 1).
Repo Placement
OK -- issue filed on ldraney/pal-e-platform, all file targets are in that repo. Single-repo change.
Dependencies
- PR #582 (MX record + pillar secrets) -- stated as already merged. No blocker.
- No other board items on board-platform-playbook are related to this work or block it.
- Tailscale operator is deployed (networking module manages it). Not a blocker.
- Kubernetes provider is declared at root level -- no additional provider config needed.
Acceptance Criteria
- AC1: tofu plan shows new resources as top-level + updated InboundHookUrl on ISS server -- agent-verifiable
- AC2: webhook endpoint reachable at funnel URL, returns 200 on POST -- post-deployment validation
- AC3: InboundHookUrl on ISS Postmark server points to funnel URL with Basic Auth -- verifiable via tofu plan output
- AC4: inbound emails queryable via search_inbound_messages -- post-deployment validation
- AC5: postmark module remains clean, no kubernetes provider dependency -- agent-verifiable (check versions.tf unchanged)
AC2 and AC4 are post-deployment validation criteria. Appropriate for infrastructure work.
Blast Radius
Previous issue resolved: Webhook k8s resources now live at top level in
postmark-inbound.tf, not inside the per-app module. The module is instantiated twice (postmark_iss, postmark_landscaping), but only receives a new variable -- no k8s resources duplicated. Only the ISS instance gets the URL initially.No other services reference inbound webhook patterns. No existing
inbound_hook_url or postmark-inbound references found in the terraform directory.Decomposition Assessment
- 4 file targets (1 new, 3 modify) in 1 repo -- under threshold
- 5 acceptance criteria -- at threshold, not over
- Estimated agent work under 5 minutes -- straightforward k8s resource creation + variable wiring
- No decomposition needed.
Previous Review Issues -- Resolution Status
- Shared module blast radius -- RESOLVED: Webhook resources now live at top level in
postmark-inbound.tf, not inside the per-app module. Issue body clearly states the architecture decision and the agent's don't-touch boundaries. - Missing kubernetes provider -- RESOLVED: Top-level resources use the already-declared kubernetes provider (versions.tf line 11-12, providers.tf line 1). Module's versions.tf is explicitly listed as don't-touch.
- Missing story note -- RESOLVED:
story-postmark-email-inboundcreated as user-story note in project postmark-email. Linked from project-postmark-email user-stories section with key "inbound".
Recommendation
No action needed. All previous issues resolved. Scope is solid, file targets verified, traceability complete.