Review: Sprint 2: SDK implementation -- postmark-server-sdk

review-1914-2026-07-25 Review

review needs-refinement

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.