Skip to content

feat(security): validate nation_slug + idempotent Stripe webhook (fixes #13)#26

Merged
ianpatrickhines merged 3 commits into
mainfrom
claude/issue-13-validate-slug-idempotent-webhook
Jun 22, 2026
Merged

feat(security): validate nation_slug + idempotent Stripe webhook (fixes #13)#26
ianpatrickhines merged 3 commits into
mainfrom
claude/issue-13-validate-slug-idempotent-webhook

Conversation

@ianpatrickhines

Copy link
Copy Markdown
Owner

Closes #13.

What

  • nation_slug validation (src/lambdas/shared/validation.py): enforces ^[a-z0-9-]{1,63}$ at every entry point; invalid values rejected with 400 before the slug is used in DynamoDB keys, Secrets Manager names, or NB API URLs.
  • Idempotent Stripe webhook: processed Stripe event IDs are persisted in DynamoDB (TTL); duplicate deliveries no-op, so Stripe's legitimate retries don't double-write nation records.

Verified

  • pytest -q596 passed (+23 new: invalid-slug and duplicate-event cases)
  • mypy src/ → clean (23 files)

Provenance

Authored by a pr-driver Opus drive that hit the 80-turn ceiling before it could commit/push; the working tree was preserved, independently re-verified (tests + mypy) from the main session, then committed and opened here. No adversarial self-review ran (the drive was cut off before that step) — worth a careful human//ship review of the validation entry points and the webhook idempotency table wiring.

#13)

- Add shared/validation.py: nation_slug must match ^[a-z0-9-]{1,63}$,
  rejected with 400 at every entry point (used in DDB keys, Secrets
  Manager names, NB API URLs)
- Make Stripe webhook idempotent: persist processed event IDs in
  DynamoDB with TTL; no-op on duplicate delivery (Stripe retries)
- Tests cover invalid slugs and replayed webhook events (+23)

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ianpatrickhines and others added 2 commits June 22, 2026 08:13
…wline

Independent review caught a bypass: ^[a-z0-9-]{1,63}$ with .match()
accepts a trailing newline (Python $ matches before a final \n), so
"legit-slug\n" passed validation and flowed into Secrets Manager paths,
NB API URLs, and DynamoDB keys. Switched $ -> \Z in all four pattern
copies (shared/validation.py + 3 inlined handler copies). Added newline
regression cases to INVALID_SLUGS.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…ate-slug-idempotent-webhook

# Conflicts:
#	infrastructure/template.yaml
#	src/lambdas/nb_oauth_callback/handler.py
@ianpatrickhines
ianpatrickhines merged commit 0b7c177 into main Jun 22, 2026
3 checks passed
@ianpatrickhines
ianpatrickhines deleted the claude/issue-13-validate-slug-idempotent-webhook branch June 22, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate nation_slug format and make Stripe webhook idempotent

1 participant