Postmark

postmark forgejo

Notes

Review 8
  • 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

    1. 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.
    2. 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.
    3. Missing story note -- RESOLVED: story-postmark-email-inbound created 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.

  • Verdict: NEEDS_REFINEMENT

    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 permanent webhook endpoint / So that inbound emails are reliably processed
    • [x] Context -- Detailed background on Postmark inbound config, webhook.site expiry, security considerations
    • [x] File Targets -- 2 modify targets, 2 don't-touch targets
    • [x] Feature Flag -- none
    • [x] Acceptance Criteria -- 4 criteria
    • [x] Test Expectations -- 3 tests (manual + tofu plan)
    • [x] Constraints -- 5 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 (architecture note covering SDK/MCP deployment pattern)
    • [x] arch note verified -- arch-deployment-postmark exists and is active
    • [x] story:postmark-email label -- label present on board item
    • [ ] story note MISSING -- [SCOPE] postmark-project-page user-stories section has keys: sdk, mcp, ci. No "email" story entry exists. Create user story entry on postmark-project-page user-stories section for story key "email" linking to a story-postmark-email note.
    • [x] Forgejo issue -- https://forgejo.tail5b443a.ts.net/ldraney/pal-e-platform/issues/583, open

    File Targets

    • [x] terraform/modules/postmark/main.tf -- verified: file exists, currently contains only postmark_server and postmark_domain resources. Adding k8s resources here is consistent with the stated design decision.
    • [x] terraform/modules/postmark/variables.tf -- verified: file exists, currently has server_name, domain, return_path_subdomain variables.
    • [x] terraform/modules/networking/main.tf -- correctly listed as don't-touch. Funnel ingress pattern confirmed there (9 instances of tailscale.com/funnel annotation).
    • [x] terraform/dns.tf -- correctly listed as don't-touch.

    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 appear related to this work.
    • Tailscale operator must be deployed (it is -- networking module manages it).

    Acceptance Criteria

    • AC1: tofu plan shows resources -- agent-verifiable
    • AC2: webhook endpoint reachable at funnel URL -- requires deployed infrastructure (post-deployment validation)
    • AC3: InboundHookUrl points to funnel URL -- verifiable via tofu plan output
    • AC4: inbound emails queryable via search_inbound_messages -- requires real email flow (post-deployment validation)

    AC2 and AC4 are post-deployment validation criteria, not agent-verifiable. This is appropriate for infrastructure work.

    Blast Radius

    CRITICAL: The postmark module is instantiated TWICE in terraform/main.tf:

    • module.postmark_iss (intelligentstaffingsystems.ai)
    • module.postmark_landscaping (landscaping-assistant.app)

    Adding kubernetes_deployment_v1, kubernetes_service_v1, kubernetes_ingress_v1, and kubernetes_config_map_v1 directly to the module will create these resources for BOTH instances. The ticket only discusses the ISS domain inbound webhook. The agent needs clear guidance: either (a) add a boolean variable like enable_inbound_webhook to make the k8s resources conditional, or (b) confirm that both Postmark servers need inbound webhook endpoints.

    Additionally, the module's versions.tf only declares the postmark provider (marcus-carey/postmark ~> 1.0). Adding Kubernetes resources requires the hashicorp/kubernetes provider. Terraform inherits it from the root module, but the module should declare it in its own required_providers for explicitness.

    Decomposition Assessment

    • 2 file targets in 1 repo -- under threshold
    • 4 acceptance criteria -- under threshold
    • All changes in one module -- fits single agent pass
    • No decomposition needed.

    Recommendation

    • [SCOPE] Create user story entry "email" on postmark-project-page user-stories section, and create backing note story-postmark-email.
    • [BODY] Address shared module blast radius: the postmark module is instantiated twice (postmark_iss, postmark_landscaping). Add guidance for the agent -- either add an enable_inbound_webhook boolean variable to conditionally create k8s resources, or state that both instances need the webhook. Without this, the agent will create duplicate deployments/ingresses for both domains.
    • [BODY] Add constraint: module versions.tf needs kubernetes provider added to required_providers since the module will now manage Kubernetes resources alongside Postmark API resources.
  • Verdict: READY

    Override: Original NEEDS_REFINEMENT was a false positive — the review agent searched for project-postmark but the project page exists at postmark-project-page. Other review agents (1916, 1919) found it correctly. Story traceability is intact: story:ci maps to story-postmark-ci which is listed on postmark-project-page.

    Template Completeness

    • [x] All 12 template sections present and well-formed

    Traceability

    • [x] story:ci label — maps to story-postmark-ci on postmark-project-page
    • [x] arch:ci-pipeline label — arch-ci-pipeline note verified
    • [x] Forgejo issue — ldraney/postmark-account-sdk#3, open

    File Targets

    • [x] .woodpecker.yml — does not exist yet (create). Reference implementations confirmed.

    Dependencies

    • [x] Blocker #2 (SDK implementation) resolved — board item #1915 in done

    Acceptance Criteria

    4 criteria, all agent-verifiable, under 5-limit threshold.

    Decomposition

    Not needed — 1 file, 1 repo, well under 5-minute threshold.

  • Verdict: APPROVED

    Re-review of board item #1915 after refinement. Prior review review-1915-2026-07-25 returned NEEDS_REFINEMENT with three issues. All three are now resolved.

    Prior Issues -- Resolution

    • [x] [LABEL] arch:api changed to arch:domain-postmark -- arch-domain-postmark note verified, belongs to postmark project
    • [x] [BODY] tests/test_templates.py added to File Targets -- Templates API group now covered
    • [x] [SCOPE] Project page exists at postmark-project-page -- user-stories section confirmed with story key "sdk" linking to story-postmark-sdk

    Template Completeness

    • [x] Type -- Feature
    • [x] Lineage
    • [x] Repo
    • [x] User Story
    • [x] Context
    • [x] File Targets -- 7 items (pyproject.toml, src package, conftest, 4 test files)
    • [x] Feature Flag -- none (appropriate for SDK/infra work)
    • [x] Acceptance Criteria -- 6 items
    • [x] Test Expectations -- 2 items
    • [x] Constraints -- 5 items
    • [x] Checklist -- 3 items
    • [x] Related

    All 12 required sections present per template-issue-feature.

    Traceability

    • [x] story:sdk label -- Postmark SDK Foundation
    • [x] story note verified -- story-postmark-sdk exists in pal-e-docs
    • [x] story note on project page -- found in postmark-project-page user-stories section, key "sdk" links to story-postmark-sdk
    • [x] arch:domain-postmark label -- Postmark Domain Model
    • [x] arch note verified -- arch-domain-postmark note exists in pal-e-docs, documents PostmarkAccountSDK entity model
    • [x] Forgejo issue -- ldraney/postmark-account-sdk#2, open

    Full traceability triangle verified. All backing notes exist.

    File Targets

    • [x] pyproject.toml -- new file, project config with pytest/httpx dependencies
    • [x] src/postmark_account_sdk/ -- new SDK package (detailed structure in docs/acceptance-criteria.md: __init__.py, client.py, servers.py, domains.py, senders.py, templates.py)
    • [x] tests/conftest.py -- shared fixtures, token loading
    • [x] tests/test_servers.py -- Server Management API (5 endpoints)
    • [x] tests/test_domains.py -- Domains API (9 endpoints)
    • [x] tests/test_sender_signatures.py -- Sender Signatures API (8 endpoints). Note: acceptance-criteria.md calls this test_senders.py; cosmetic naming difference, not blocking since the doc is the detailed guide per Constraints section.
    • [x] tests/test_templates.py -- Templates API (1 endpoint: PUT /templates/push)

    All file targets are new files. Repo currently contains only Sprint 1 docs: CLAUDE.md, README.md, docs/, postmark-account-api.yaml. Verified via Forgejo API tree listing.

    Repo Placement

    OK -- Issue filed on ldraney/postmark-account-sdk, work targets same repo. Single-repo scope.

    Dependencies

    • Blocked by #1 (docs PR) -- RESOLVED. Board item #1911 in done column, PR #4 merged.
    • Sibling: ldraney/postmark-server-sdk#2 (board item #1914, 8 points) -- parallel server SDK issue, same sprint 2, same pattern. No ordering dependency.
    • Downstream: Sprint 3 items depend on SDKs:
      • #1917 -- Sprint 3: Woodpecker pipeline (postmark-account-sdk)
      • #1919 -- Sprint 3: MCP implementation (postmark-account-mcp)
    • Dependencies documented in Lineage and Related sections.

    Acceptance Criteria

    6 criteria, all verifiable by an agent:

    • AC1: "Every endpoint in postmark-account-api.yaml has at least one test" -- verifiable by cross-referencing swagger (23 endpoints across 4 groups per docs/acceptance-criteria.md)
    • AC2: "All tests pass against the real Postmark API" -- verifiable via pytest tests/ -v
    • AC3: "SDK client handles auth via POSTMARK_ACCOUNT_TOKEN env var" -- verifiable
    • AC4: "Error responses are handled gracefully" -- verifiable (agent interprets as proper exception handling)
    • AC5: "Tests are organized by API group matching the swagger spec sections" -- verifiable by file structure, 4 groups confirmed in swagger
    • AC6: "Destructive tests are safe" -- verifiable (create/cleanup pattern)

    The docs/acceptance-criteria.md provides detailed endpoint-to-test mapping (23 endpoints, 23 tests). Test Expectations are clear: full pytest suite, real API, no mocks.

    Blast Radius

    Clean. Greenfield SDK repo with no existing consumers. Sibling postmark-server-sdk#2 follows identical pattern (same template structure, same forgejo-sdk reference). No cross-repo impact. MCP repos (sprint 3) will consume the SDK but are not yet implemented.

    Decomposition Assessment

    • File targets: 7 files in 1 repo -- single-repo, under the >3 files across >2 repos threshold
    • Acceptance criteria: 6 items -- at the >5 threshold boundary, but tightly coupled (single SDK implementation with cross-cutting quality constraints)
    • Clear source of truth: swagger spec (23 endpoints) + docs/acceptance-criteria.md (complete endpoint-to-test mapping)
    • Clear pattern reference: ~/forgejo-sdk
    • Estimated agent work: 5-point story with established scaffolding. Manageable in a single agent pass.

    No decomposition needed. Work is coherent and single-repo with comprehensive documentation.

    Observations (non-blocking)

    • Issue File Targets say tests/test_sender_signatures.py but docs/acceptance-criteria.md says tests/test_senders.py. The Constraints section directs the agent to "Read docs/acceptance-criteria.md for the detailed endpoint-to-test mapping," so the doc naming will prevail. Cosmetic only.

    Recommendation

    No action needed. Scope is solid, all prior issues resolved, traceability complete.

  • Verdict: APPROVED

    Re-review of board item #1914 after refinement. Prior review review-1914-2026-07-25 returned NEEDS_REFINEMENT with two findings. Both addressed.

    Refinement Resolution

    • [LABEL] arch:api to arch:domain-postmark -- FIXED. Board item #1914 now carries arch:domain-postmark. Verified via fresh board pull.
    • [DECOMPOSE] Decomposition waived -- ACCEPTED. This is intentionally an 8-point ticket for agent-driven implementation where a dev agent implements the full SDK in one pass. The repo's docs/acceptance-criteria.md provides a detailed endpoint-to-test mapping (43 endpoints across 7 groups) that serves as the agent's implementation guide. Decomposition would add overhead without benefit for single-agent execution.

    Template Completeness

    • [x] Type -- Feature
    • [x] Lineage -- Blocked by #1 (docs PR), Sprint 2
    • [x] Repo -- ldraney/postmark-server-sdk
    • [x] User Story -- well-formed (developer wants pytest coverage of every endpoint)
    • [x] Context -- references swagger spec, forgejo-sdk pattern, token source
    • [x] File Targets -- 10 files/directories listed
    • [x] Feature Flag -- none (appropriate for SDK infrastructure)
    • [x] Acceptance Criteria -- 5 criteria, supplemented by docs/acceptance-criteria.md
    • [x] Test Expectations -- pytest command specified, real API (no mocks)
    • [x] Constraints -- forgejo-sdk patterns, uv/pyproject.toml
    • [x] Checklist -- present
    • [x] Related -- present

    Traceability

    • [x] story:sdk label -- Postmark SDK Foundation
    • [x] story note verified -- story-postmark-sdk exists in postmark-project-page user-stories section (key: sdk, metric: 100% endpoint coverage in pytest)
    • [x] arch:domain-postmark label -- corrected from prior review
    • [x] arch note verified -- arch-domain-postmark note exists in pal-e-docs (architecture type, active tag, ER diagram covering PostmarkServerSDK entities)
    • [x] Forgejo issue -- ldraney/postmark-server-sdk#2, state: open

    File Targets

    • [x] pyproject.toml -- to create. No conflict with existing repo contents (CLAUDE.md, README.md, docs/, swagger spec).
    • [x] src/postmark_server_sdk/ -- to create. Note: issue body uses postmark_server_sdk but docs/acceptance-criteria.md uses postmark_sdk. See recommendation.
    • [x] tests/conftest.py -- to create. Token loading from POSTMARK_SERVER_TOKEN env var.
    • [x] tests/test_sending.py -- to create. 4 endpoints (send, batch, template, batch-template).
    • [x] tests/test_bounces.py -- to create. 5 endpoints.
    • [x] tests/test_messages.py -- to create. 11 endpoints (7 outbound + 4 inbound).
    • [x] tests/test_templates.py -- to create. 6 endpoints (CRUD + validate).
    • [x] tests/test_stats.py -- to create. 12 endpoints across outbound stats.
    • [x] tests/test_server.py -- to create. 2 endpoints (get/edit config).
    • [x] tests/test_inbound.py -- to create. Note: issue says test_inbound.py but acceptance-criteria.md says test_inbound_rules.py. See recommendation.

    All targets are new files -- Sprint 1 (docs PR, #1910) is in done. No existing files to verify against.

    Repo Placement

    OK. Issue filed on ldraney/postmark-server-sdk, all work targets the same repo. No cross-repo concerns.

    Dependencies

    • Blocked by: ldraney/postmark-server-sdk#1 (docs PR) -- RESOLVED. Board item #1910 is in done column.
    • Sibling: Board item #1915 "Sprint 2: SDK implementation -- postmark-account-sdk" is in backlog with same labels. Independent -- can run in parallel.
    • Downstream: Sprint 3 MCP items (#1918 postmark-server-mcp, #1919 postmark-account-mcp) depend on SDK packages being installable. No blocking concern for this sprint.

    Acceptance Criteria

    5 criteria in the issue body, all agent-verifiable:

    • "Every endpoint in postmark-server-api.yaml has at least one test" -- verifiable by counting endpoints (43 per acceptance-criteria.md, 41 operationIds in swagger -- close enough, likely minor counting difference)
    • "All tests pass against the real Postmark API" -- verifiable via pytest tests/ -v
    • "SDK client handles auth via POSTMARK_SERVER_TOKEN env var" -- verifiable by code inspection
    • "Error responses are handled gracefully" -- verifiable but slightly vague (minor concern, carried from prior review)
    • "Tests are organized by API group matching the swagger spec sections" -- verifiable by file structure

    The docs/acceptance-criteria.md provides a detailed 7-section completion checklist plus per-endpoint test expectations for each group. This compensates for the issue body's higher-level AC.

    Blast Radius

    Sibling repo postmark-account-sdk (#1915) follows the identical pattern. Both SDKs will be pip-installed by MCP repos in Sprint 3. No downstream consumers exist yet. The arch:domain-postmark label fix applied to #1914 was also applied to #1915.

    Decomposition Assessment

    • File targets: 10+ files in 1 repo (single-repo, no multi-repo trigger)
    • Acceptance criteria: 5 in issue body (under threshold)
    • Estimated agent work: 43 endpoints, ~45 minutes. Exceeds 5-minute rule.
    • Waived. Caller explicitly states this is intentionally a large ticket (8 points) designed for agent-driven implementation in one pass. The docs/acceptance-criteria.md in the repo provides the detailed endpoint-to-test mapping that guides the dev agent. Decomposition would fragment the work without benefit.

    Recommendation

    Minor [BODY] items -- non-blocking, can be fixed during implementation or before:

    • [BODY] Align package directory name: issue body says src/postmark_server_sdk/, docs/acceptance-criteria.md says src/postmark_sdk/. Pick one and update the other. Recommend postmark_server_sdk to match repo name and distinguish from account SDK.
    • [BODY] Align test file name: issue body says tests/test_inbound.py, acceptance-criteria.md says tests/test_inbound_rules.py. Recommend test_inbound_rules.py to match the source module name inbound_rules.py.
    • [BODY] Acceptance-criteria.md completion checklist item 7 references Woodpecker CI (issue #3), which is Sprint 3 scope. Consider removing or marking as out-of-scope for this ticket.

    None of these block implementation. The dev agent should follow docs/acceptance-criteria.md as the authoritative source for file names and endpoint mappings.

  • Verdict: NEEDS_REFINEMENT

    Template Completeness

    • [x] Type -- Feature
    • [x] Lineage
    • [x] Repo
    • [x] User Story
    • [x] Context
    • [x] File Targets
    • [x] Feature Flag -- none (appropriate for SDK/infra work)
    • [x] Acceptance Criteria -- 6 items
    • [x] Test Expectations
    • [x] Constraints
    • [x] Checklist
    • [x] Related

    All 12 required sections present per template-issue-feature.

    Traceability

    • [x] story:sdk label -- Postmark SDK Foundation
    • [x] story note verified -- story-postmark-sdk exists in pal-e-docs
    • [ ] story note on project page MISSING -- [SCOPE] No project-postmark project page exists. The story note story-postmark-sdk references postmark-project-page in its Related section, suggesting this page should be created.
    • [x] arch:api label present
    • [ ] arch note WRONG PROJECT -- [LABEL] arch-api note exists but belongs to prediction-assistant (Kalshi), not postmark. The postmark project uses arch-domain-postmark, arch-dataflow-postmark, arch-deployment-postmark. Label should be arch:domain-postmark to reference the correct architecture note.
    • [x] Forgejo issue -- ldraney/postmark-account-sdk#2, open

    File Targets

    • [x] pyproject.toml -- new file, project config
    • [x] src/postmark_account_sdk/ -- new package directory
    • [x] tests/conftest.py -- new file, shared fixtures
    • [x] tests/test_servers.py -- covers Server Management API (5 endpoints)
    • [x] tests/test_domains.py -- covers Domains API (9 endpoints)
    • [x] tests/test_sender_signatures.py -- covers Sender Signatures API (8 endpoints)
    • [ ] tests/test_templates.py -- MISSING: [BODY] Templates API group (PUT /templates/push) has no test file listed. The swagger spec defines 4 API tag groups but only 3 test files are listed. AC #5 requires "Tests are organized by API group matching the swagger spec sections."

    Repo currently contains only docs from Sprint 1: CLAUDE.md, README.md, docs/, postmark-account-api.yaml. All file targets are new files, which is correct.

    Repo Placement

    OK -- Issue filed on ldraney/postmark-account-sdk, work targets same repo. Single-repo scope.

    Dependencies

    • Blocked by #1 (docs PR) -- RESOLVED (issue #1 closed, PR #4 merged). Blocker cleared.
    • Sibling: ldraney/postmark-server-sdk#2 (board item #1914, 8 points) -- parallel server SDK issue, same sprint 2, same pattern. No ordering dependency between the two SDKs.
    • Downstream: Sprint 3 items depend on SDKs being complete:
      • #1917 -- Sprint 3: Woodpecker pipeline (postmark-account-sdk)
      • #1919 -- Sprint 3: MCP implementation (postmark-account-mcp)
    • Dependencies are documented in the Lineage and Related sections.

    Acceptance Criteria

    6 criteria, all verifiable:

    • AC1: "Every endpoint in postmark-account-api.yaml has at least one test" -- verifiable by cross-referencing swagger paths vs test coverage. Swagger has 22 endpoints across 4 groups.
    • AC2: "All tests pass against the real Postmark API" -- verifiable via pytest tests/ -v
    • AC3: "SDK client handles auth via POSTMARK_ACCOUNT_TOKEN env var" -- verifiable
    • AC4: "Error responses are handled gracefully" -- slightly vague but acceptable (agent can interpret as proper exception handling)
    • AC5: "Tests are organized by API group matching the swagger spec sections" -- verifiable, but contradicted by missing templates test file in File Targets
    • AC6: "Destructive tests are safe" -- verifiable and important for account-level operations. Good addition vs the sibling server-sdk issue.

    Blast Radius

    Clean. Greenfield SDK repo with no existing consumers. Sibling postmark-server-sdk#2 follows identical pattern (same template structure, same forgejo-sdk reference). No cross-repo impact. MCP repos (sprint 3) will consume the SDK but are not yet implemented.

    The ~/forgejo-sdk pattern reference should provide a clear implementation model for the agent.

    Decomposition Assessment

    • File targets: 6 files (should be 7 with templates) in 1 repo -- under the >3 files across >2 repos threshold
    • Acceptance criteria: 6 items -- at the >5 threshold boundary
    • Estimated agent work: Single repo, clear swagger spec as source of truth, clear pattern to follow (forgejo-sdk). 4 API groups, 22 total endpoints. Manageable in a single agent pass despite being a 5-point story.

    No decomposition needed. The work is coherent and single-repo.

    Recommendations

    • [BODY] Add tests/test_templates.py to File Targets -- Templates API (PUT /templates/push) is the 4th API group in the swagger spec. AC #5 requires tests organized by API group.
    • [LABEL] Change arch:api label to arch:domain-postmark -- the arch-api note belongs to prediction-assistant, not postmark. The correct postmark arch note is arch-domain-postmark which documents the PostmarkAccountSDK entity model.
    • [SCOPE] Create project-postmark project page with user-stories section -- the story note story-postmark-sdk exists but no project page hosts it. The story note itself references postmark-project-page as a parent.
  • Verdict: NEEDS_REFINEMENT

    Template Completeness

    • [x] Type -- Feature
    • [x] Lineage -- Blocked by #1 (docs PR), Sprint 2
    • [x] Repo -- ldraney/postmark-server-sdk
    • [x] User Story -- present, well-formed
    • [x] Context -- present, references swagger spec and forgejo-sdk pattern
    • [x] File Targets -- 10 files/directories listed
    • [x] Feature Flag -- none (appropriate for SDK infra)
    • [x] Acceptance Criteria -- 5 criteria
    • [x] Test Expectations -- present, pytest command specified
    • [x] Constraints -- present, references forgejo-sdk patterns
    • [x] Checklist -- present
    • [x] Related -- present

    Traceability

    • [x] story:sdk label -- Postmark SDK Foundation
    • [x] story note verified -- story-postmark-sdk exists and is listed in postmark-project-page user-stories section (key: sdk, metric: 100% endpoint coverage in pytest)
    • [ ] arch:api label -- WRONG NOTE. arch-api belongs to prediction-assistant (Kalshi API integration), not postmark. The postmark project uses arch-domain-postmark (SDK client entities) and arch-dataflow-postmark (SDK-to-Postmark API call flow). [LABEL] Change arch:api to arch:domain-postmark or arch:dataflow-postmark.
    • [x] Forgejo issue -- ldraney/postmark-server-sdk#2, state: open

    File Targets

    • [x] pyproject.toml -- to create. Repo currently has only docs from Sprint 1 (CLAUDE.md, README.md, docs/, postmark-server-api.yaml). Verified no conflict.
    • [x] src/postmark_server_sdk/ -- to create. Package directory. Follows forgejo-sdk pattern (src/forgejo_sdk/ has client.py, __init__.py, and per-group modules).
    • [x] tests/conftest.py -- to create. Shared fixtures, token loading. Matches forgejo-sdk/tests/conftest.py pattern.
    • [x] tests/test_sending.py -- to create. Covers /email, /email/batch, /email/batchWithTemplates, /email/withTemplate endpoints.
    • [x] tests/test_bounces.py -- to create. Covers /bounces endpoints.
    • [x] tests/test_messages.py -- to create. Covers /messages/inbound, /messages/outbound, /messages/outbound/clicks, /messages/outbound/opens.
    • [x] tests/test_templates.py -- to create. Covers /templates, /templates/validate.
    • [x] tests/test_stats.py -- to create. Covers 9 /stats/outbound/* endpoints.
    • [x] tests/test_server.py -- to create. Covers /server endpoint.
    • [x] tests/test_inbound.py -- to create. Covers /triggers/inboundrules.

    Note: File targets list test files but do not explicitly list SDK source modules (e.g., src/postmark_server_sdk/client.py, __init__.py, per-group modules). The forgejo-sdk pattern includes per-group modules in src/. These implied files add to the true scope.

    Repo Placement

    OK. Issue filed on ldraney/postmark-server-sdk, all work targets the same repo. No cross-repo concerns for this sprint.

    Dependencies

    • Blocked by: ldraney/postmark-server-sdk#1 (docs PR) -- RESOLVED. Issue #1 is closed, board item #1910 is in done column.
    • Sibling: board item #1915 "Sprint 2: SDK implementation -- postmark-account-sdk" is in backlog with same labels (type:feature, arch:api, story:sdk). Independent -- can run in parallel.
    • Downstream: Sprint 3 MCP items (#1918, #1919) depend on SDK packages being installable. No blocking concern for this sprint.

    Acceptance Criteria

    5 criteria, all testable by an agent:

    • "Every endpoint in postmark-server-api.yaml has at least one test" -- verifiable by counting endpoints vs test functions
    • "All tests pass against the real Postmark API" -- verifiable via pytest tests/ -v
    • "SDK client handles auth via POSTMARK_SERVER_TOKEN env var" -- verifiable by code inspection
    • "Error responses are handled gracefully" -- verifiable but vague. What constitutes "graceful"? (minor concern)
    • "Tests are organized by API group matching the swagger spec sections" -- verifiable by file structure

    Test command is real: pytest tests/ -v. Token source documented: ~/secrets/postmark/intelligentstaffingsystems/.env.

    Blast Radius

    Sibling repo postmark-account-sdk (#1915) has an identical pattern. Both SDKs will be pip-installed by MCP repos in Sprint 3. No downstream consumers exist yet. The arch:api label mismatch affects #1915 too (same label, same wrong arch note).

    Decomposition Assessment

    • File targets: 10+ files in 1 repo (does not trigger ">3 files across >2 repos")
    • Acceptance criteria: 5 (does not trigger ">5 acceptance criteria")
    • Estimated agent work: 43 endpoints to implement in SDK + 43 tests across 7 test files + package setup + conftest. At ~1 min per endpoint (SDK method + test), estimated 45+ minutes. EXCEEDS 5-minute threshold.
    • 8 story points confirms large scope.

    NEEDS DECOMPOSITION -- route to skill-decompose-ticket. Recommended split: one sub-ticket per API group (sending, bounces, messages, templates, stats, server, inbound) plus one for package scaffolding (pyproject.toml, client.py, conftest.py).

    Recommendation

    • [LABEL] Change arch:api to arch:domain-postmark on board item #1914. The current arch-api note belongs to prediction-assistant, not postmark. Also affects sibling #1915.
    • [DECOMPOSE] 43 endpoints across 8 API groups, estimated 45+ minutes of agent work. Route to skill-decompose-ticket. Suggested sub-tickets: (1) package scaffolding, (2) sending endpoints, (3) bounces, (4) messages, (5) templates, (6) stats, (7) server config, (8) inbound rules.
  • Verdict: APPROVED

    Re-review of board item #1911 after refinement. All four issues from review-1911-2026-07-25 (NEEDS_REFINEMENT) have been resolved.

    Template Completeness

    • [x] Type -- Feature
    • [x] Lineage -- Standalone, Sprint 1
    • [x] Repo -- ldraney/postmark-account-sdk
    • [x] User Story -- complete As a/I want/So that
    • [x] Context -- detailed motivation and pattern references
    • [x] File Targets -- 6 files to create + 3 reference repos
    • [x] Feature Flag -- "none" (appropriate for docs-only PR)
    • [x] Acceptance Criteria -- 7 items
    • [x] Test Expectations -- "No tests -- docs only PR"
    • [x] Constraints -- 4 constraints with correct repo references
    • [x] Checklist -- 2 items (missing "Tests pass" but justified for docs-only)
    • [x] Related -- "postmark -- parent project"

    Traceability

    • [x] story:sdk label -- Postmark SDK Foundation
    • [x] story note verified -- story-postmark-sdk exists in pal-e-docs and listed in postmark-project-page user-stories section with key "sdk"
    • [x] arch:domain-postmark label -- Postmark Domain Model
    • [x] arch note verified -- arch-domain-postmark exists in pal-e-docs with mermaid ER diagram
    • [x] Forgejo issue -- ldraney/postmark-account-sdk#1, state: open

    File Targets

    • [x] ~/forgejo-mcp/ -- verified: CLAUDE.md symlink, README.md, docs/ directory with architecture.md (docs structure reference)
    • [x] ~/forgejo-sdk/ -- verified: pyproject.toml, src/, tests/ (SDK code structure reference)
    • [x] ~/postmark-email/postmark-account-api.yaml -- verified: 29k, Postmark Account-level API v0.9.0, 23 operations across 4 path groups
    • [x] ldraney/postmark-account-sdk -- verified on Forgejo (created 2026-07-25, not empty, main branch). Not cloned locally; implementing agent will clone.
    • [x] All 6 target files are "to be created" -- no pre-existing file verification needed beyond sources

    Repo Placement

    OK. Issue filed on ldraney/postmark-account-sdk, ### Repo section matches. Single-repo scope.

    Dependencies

    • Sprint 2: SDK implementation (#1915, 5pt) depends on this docs PR completing first -- documented by sprint numbering
    • Sprint 3: Woodpecker pipeline (#1917, 2pt) depends on Sprint 2
    • No items in in_progress blocking this ticket
    • Sibling Sprint 1 docs PRs (#1910 postmark-server-sdk, #1912 postmark-server-mcp, #1913 postmark-account-mcp) are independent -- can run in parallel

    Acceptance Criteria

    • [x] 7 AC items, all agent-verifiable (file existence, symlink check, content grep, mermaid presence)
    • [x] AC 7 now specifically enumerates endpoint groups: servers, domains, sender signatures
    • Minor note: swagger spec has a 4th path group /templates/push (1 utility PUT operation) not listed in the parenthetical. This is a cross-cutting operation, not an entity group -- the domain model in arch-domain-postmark also omits it. Implementing agent should include it if discovered during spec reading. Not a blocker.

    Blast Radius

    Minimal. Docs-only PR in a new repo. Swagger spec is copied, not modified at source. No downstream consumers affected.

    Decomposition Assessment

    6 file targets in 1 repo, 7 AC items. AC count is 7 (above >5 threshold) but all work is documentation generation from a swagger spec following a known pattern. Estimated agent time: under 5 minutes. No decomposition needed.

    Previous Review Issues -- Resolution

    # Original Issue Resolution
    1 [BODY] Constraints referenced ~/forgejo-sdk for docs pattern, but forgejo-sdk has no docs/ directory FIXED. Now cites ~/forgejo-mcp for docs structure, ~/forgejo-sdk for SDK code structure only
    2 [BODY] AC 7 was vague ("All docs reference the Postmark Account API endpoints") FIXED. Now enumerates specific endpoint groups: servers, domains, sender signatures
    3 [LABEL] arch:api label pointed to prediction-assistant arch note FIXED. Changed to arch:domain-postmark; arch-domain-postmark note exists
    4 [SCOPE] story note missing from project page FIXED. story-postmark-sdk exists and is listed on postmark-project-page user-stories section

    Recommendation

    No action needed. All previous NEEDS_REFINEMENT issues resolved. Ticket is ready for implementation.

Board 1