Skip to content

kunwarpadda/subscription-platform-core

Repository files navigation

Subscription Platform Core

A small, production-oriented TypeScript foundation for subscription lifecycle processing. It focuses on the parts that are hardest to retrofit later: explicit state transitions, durable webhook ingestion, idempotent processing, transactional audit/outbox writes, and authorization boundaries.

This is a clean-room reference project. It contains no customer records, provider fixtures, production metrics, or deployment claims.

What it demonstrates

  • An explicit subscription state machine with terminal states and same-state no-ops.
  • HMAC verification over the raw webhook body before persistence.
  • A PostgreSQL inbox with a unique (provider, event_id) boundary. Duplicate delivery exits before subscription, audit, or outbox effects.
  • A worker that locks pending events with FOR UPDATE SKIP LOCKED and commits the subscription update, audit entry, outbox message, and inbox completion in one transaction.
  • Optimistic subscription versions plus row locks to make concurrent updates visible.
  • A deterministic outbox deduplication key per aggregate version.
  • A deny-by-default RBAC policy for change, audit, and replay capabilities.
  • Unit tests plus a real PostgreSQL integration test in CI.

Processing model

flowchart LR
  Provider[Webhook provider] --> Verify[Verify raw-body HMAC]
  Verify --> Claim[Insert inbox row]
  Claim -->|unique conflict| Duplicate[Return duplicate; no effects]
  Claim -->|accepted| Worker[Worker locks pending row]
  Worker --> Transition[Validate state transition]
  Transition --> Commit[Atomic commit]
  Commit --> Subscription[(Subscription)]
  Commit --> Audit[(Audit log)]
  Commit --> Outbox[(Outbox)]
Loading

The HTTP process does not mutate a subscription. Its responsibility ends after a verified event is durably accepted. That separation closes the crash window between acknowledging a webhook and recording work to be done.

Run locally

Requirements: Node.js 22+, npm, and Docker.

cp .env.example .env
docker compose up -d postgres redis
npm install
set -a; source .env; set +a
npm run db:migrate
npm test
npm run start:dev

Run the inbox worker in a second terminal:

set -a; source .env; set +a
npm run worker

The liveness endpoint is GET /health/live. Webhooks are accepted at POST /webhooks/:provider with x-webhook-signature: sha256=<hex digest>. The body contract is:

{
  "eventId": "provider-event-id",
  "eventType": "subscription.state_requested",
  "occurredAt": "2026-01-01T00:00:00Z",
  "data": {
    "subscriptionId": "uuid-from-your-system",
    "targetState": "ACTIVE",
    "actorReference": "provider:account-reference"
  }
}

No seed data is included. Insert a local-only subscription explicitly if you want to exercise the worker end to end:

INSERT INTO subscriptions (id, state)
VALUES ('00000000-0000-0000-0000-000000000001', 'PENDING');

State model

Current Allowed next states
PENDING ACTIVE, CANCELED, EXPIRED
ACTIVE PAST_DUE, PAUSED, CANCELED
PAST_DUE ACTIVE, PAUSED, CANCELED, EXPIRED
PAUSED ACTIVE, CANCELED, EXPIRED
CANCELED terminal
EXPIRED terminal

Re-delivering the current state is an idempotent no-op. Illegal transitions fail processing and remain available for a bounded retry policy; they do not partially update domain state.

Repository map

  • src/domain: state machine and RBAC policy with no framework dependency.
  • src/application: webhook use cases and persistence ports.
  • src/infrastructure: HMAC and PostgreSQL adapters.
  • migrations: inbox, subscription, audit, and outbox schema.
  • test: transition, authorization, signature, duplicate-delivery, and PostgreSQL tests.
  • docs: architecture decisions, failure behavior, security boundary, and honest limitations.

Verification

npm run format:check
npm run lint
npm run build
npm test

See Architecture, Failure modes, Security, and Limitations before adapting this code.

License

MIT

About

Durable subscription lifecycle processing with transactional inbox, outbox, audit, and RBAC boundaries

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages