Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

121 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Loyalty Interchange Protocol (LIP) πŸ‘‹

npm License: Apache-2.0 TypeScript Node.js OpenAPI Docker Status

LIP is an open, vendor-neutral loyalty protocol and reference platform for developers building restaurant, QSR, coffee, convenience, and franchise ordering systems. It ships everything needed to go from zero to a working loyalty integration: a normative protocol spec, a deterministic reference engine, an HTTP API, a TypeScript SDK, a local Admin dashboard, a SQLite sandbox, Docker runtime, runnable examples, and black-box conformance tests.

Important

Customer authentication is intentionally outside the LIP transaction boundary. The app BFF integrates Clerk, Auth0, or another identity provider, keeps the merchant API key server-side, and maps authenticated customers to opaque LIP member_id values. A LIP member is not automatically a platform customer. For example, a pilot app's demo guests can exist in that app's BFF/customer-data layer without ever being provisioned in a managed customer identity platform.

πŸ“– Documentation: loyalty-interchange.mintlify.app β€” new here? Start at Get started. (The guides in docs/ are the source.) Building with an AI coding agent? Start with Getting started with AI.

Key Features of LIP ⭐

  • πŸš€ Effortless Setup: One command to a seeded local sandbox (npm start), or self-host with Docker Compose. The startup screen prints your Admin URL and API key.

  • πŸ” Complete Loyalty Lifecycle: Member lookup, enrollment, balances, and ledger history. Evaluate orders before checkout, post accrual after payment, and run redemption reserve, capture, reverse, and refund-safe adjustment flows.

  • πŸ” Foodservice-First Order Model: Restaurant orders with items, modifiers, discounts, fees, taxes, tips, tenders, and totals. Channel-aware rules for counter, drive-thru, kiosk, web, mobile, pickup, delivery, and catering.

  • πŸͺ Franchise-Aware Scope: Brand, merchant, location, and franchisee identifiers, plus product, category, tag, and line-kind earning exclusions.

  • 🎯 Multiple Program Models: executable points, visits/stamps, wallet credit, paid membership, and hybrid multi-account programs with independent earning, balances, expiration, reward costs, and reservations.

  • πŸ“£ Engagement Platform: persisted static or dynamic segments, scheduled reward campaigns, idempotent wallet issuance, reward draft CRUD, and membership lifecycle controls in Admin. Ledger analytics, consent-filtered CRM exports, and signed messaging connector jobs include retries and audit.

  • πŸ›‘οΈ Retry-Safe by Design: Idempotency keys, request context, RFC 9457 problem details, and partial refund, void, reversal, duplicate-check, and settlement semantics.

  • 🧰 TypeScript SDK: Idiomatic domain client with request ids, timestamps, idempotency keys, exact-money helpers, a foodservice order builder, and a generated low-level OpenAPI client.

  • πŸ–₯️ Local Admin Dashboard: Authenticated dashboard at http://127.0.0.1:3210/admin/ for inspecting members and ledger activity, plus versioned program drafts, validation, live publish, and rollback.

  • πŸ—„οΈ Durable Storage: SQLite-backed local state by default plus normalized, tenant-scoped Postgres tables, migrations, optimistic revisions, advisory transaction locks, and scheduler leases for multi-instance protocol serving.

  • ☁️ Cloud Control Plane: A separate Postgres-backed management service for organizations, projects, regional environments, plans, subscriptions, provisioning jobs, idempotent usage metering, and quotas. The open protocol and self-hosted runtime remain independent of this non-normative service.

  • πŸ” External Identity Bridge: Validate Clerk, Auth0, or generic OIDC access tokens in your BFF and map provider identities to stable customer and LIP member ids without moving credentials or sessions into the loyalty platform.

  • πŸ§ͺ Specs and Conformance: OpenAPI 3.1 contract, JSON Schema Draft 2020-12 payload schemas, normative lifecycle, account, webhook, and foodservice profile documents, and black-box HTTP conformance tests you can run against any implementation.

  • πŸ”§ Batteries-Included CLI: Validation, diagnostics (doctor), local serving, schema listing, baseline conformance checks, and checksummed full-state export/import for cloud migration.

  • πŸ€– AI-Ready: Installable agent Skills, an official MCP server, llms.txt, and curated prompts so Cursor, Claude Code, Codex, and similar tools implement LIP correctly.

Want the full picture? Check out the developer docs for a comprehensive overview.

How to Install πŸš€

Getting started with AI πŸ€–

LIP is set up for AI coding agents the same way platforms like Clerk are: Skills for specialized knowledge, an MCP server for accurate lookups, and a compact index for agent context.

# After cloning and installing (see below)
npx skills add .

That installs seven Skills (lip, lip-cli, lip-sdk, lip-checkout, lip-webhooks, lip-bff, lip-conformance) into your agent environment.

Then enable the MCP server. Cursor can use the repo root mcp.json (Settings β†’ MCP), or run it directly:

npm run mcp
Resource What it is
Using LIP with AI Full AI getting-started guide
AI prompts Copy/paste prompts for checkout, webhooks, refunds, and more
llms.txt Compact repo index β€” point your agent here first
skills/ Installable agent Skills
packages/mcp/ Official MCP server (spec lookups, validation, SDK snippets)

Quick Start with Docker 🐳

Requirements: Git and Docker.

git clone https://github.com/alvinjchoi/opensource-loyalty.git
cd opensource-loyalty
docker compose up --build

The startup log prints the Admin URL and the Admin/API key. With the default Compose environment, the key is:

lip-dev-key

Open the Admin dashboard at http://127.0.0.1:3210/admin/ and sign in with that key.

Tip

If the terminal is no longer visible, read the same key from Docker logs with docker compose logs lip.

Then verify the API in a second terminal:

curl http://127.0.0.1:3210/health
curl http://127.0.0.1:3210/lip/v1/capabilities \
  -H 'Authorization: Bearer lip-dev-key'

Installation from Source πŸ› οΈ

Requirements: Git, Node.js 20.19 or newer, and npm.

Note

This repo uses npm workspaces with package-lock.json. pnpm is not the supported install path. For a clean lockfile-only install, use npm ci instead of npm install.

git clone https://github.com/alvinjchoi/opensource-loyalty.git
cd opensource-loyalty
npm install
npm start

The CLI prints:

Admin: http://127.0.0.1:3210/admin/
Admin/API key: lip-dev-key

In a second terminal, check the server and run the baseline conformance suite:

npm run lip -- doctor http://127.0.0.1:3210 --api-key lip-dev-key
npm run lip -- test http://127.0.0.1:3210 --api-key lip-dev-key

Run the full SDK lifecycle β€” enroll a member, evaluate an order, post accrual, reserve and capture a reward, reverse it, and adjust a refunded order:

npm run example:sdk

What You Should See βœ…

The local server exposes:

  • Admin dashboard: http://127.0.0.1:3210/admin/
  • Protocol API: http://127.0.0.1:3210/lip/v1
  • Health: http://127.0.0.1:3210/health
  • Prometheus metrics: http://127.0.0.1:3210/metrics (Bearer auth required)
  • Discovery: http://127.0.0.1:3210/.well-known/lip

Running the API Separately

Use this when you only need the reference API and Admin app:

npm run lip -- serve

Useful options:

npm run lip -- serve --reset
npm run lip -- serve --reset --no-seed
npm run lip -- serve --database .lip/another.db
npm run lip -- serve --port 4010 --api-key local-dev-key
npm run lip -- serve --program ./my-program.json
npm run lip -- serve --rate-limit 300 --rate-window-ms 60000
npm run lip -- serve --no-structured-logs

--program bootstraps an empty database with your own JSON program definition (same shape as ProgramDefinition in packages/reference/src/config.ts). Afterward, use the Admin Configure view to edit, validate, publish, or roll back persisted revisions without restarting. Demo member seeding is skipped when a custom program is loaded.

Self-Hosting Configuration βš™οΈ

The default Compose service runs the reference server and Admin dashboard on port 3210 and stores SQLite state in the named lip-data volume. Configure runtime values with environment variables:

LIP_API_KEY="replace-with-a-long-local-key"
LIP_PORT=3210
LIP_SEED_DEMO=true
LIP_RATE_LIMIT_REQUESTS=120
LIP_RATE_LIMIT_WINDOW_MS=60000
LIP_STRUCTURED_LOGS=true
docker compose up --build

For the Postgres-backed profile, run docker compose --profile postgres up --build; its API defaults to port 3211. See PostgreSQL production storage.

To run the managed-service control-plane foundation on port 3220, set a LIP_CLOUD_API_KEY of at least 16 characters and run docker compose --profile cloud up --build. See Cloud control plane.

Moving a self-hosted program to another LIP host? Follow MIGRATION.md. The migration archive preserves members, balances, immutable ledger history, open reservations, and idempotency records.

Authenticated protocol requests are limited per remote client. Responses include RateLimit-* headers and return RFC 9457 problem details with HTTP 429 when exhausted. The CLI and container emit one JSON http_request record per response without logging API keys or request bodies. The authenticated /metrics endpoint exports request counts and duration summaries in Prometheus text format.

Note

The Postgres protocol runtime coordinates engine mutations across instances, and the full Admin service suite runs on tenant-scoped Postgres stores. Multi-location deployments get a per-tenant location registry, Admin users/API keys scoped with allowed_location_ids, and per-location reporting at /admin/api/v1/reports/locations. Location-scoped principals fail closed: tenant-wide admin reads (snapshot, analytics, member exports) return 403 for them β€” location-filtered variants of those views are follow-up work. Franchise funding-share settlement math is not implemented yet.

Install from npm πŸ“¦

All packages are published to npm with provenance under the @loyalty-interchange scope. Run the sandbox without cloning:

npx @loyalty-interchange/cli serve

Or add the SDK to your app:

npm install @loyalty-interchange/sdk

See the release guide for how releases are cut and verified.

Project Structure πŸ—‚οΈ

|-- apps/
|   |-- admin/              # Browser Admin dashboard
|   `-- cloud/              # Managed Cloud control plane and management API
|-- docs/                   # Developer guides and API documentation
|-- examples/
|   `-- typescript/         # Runnable SDK lifecycle examples
|-- packages/
|   |-- cli/                # CLI: serve, quickstart, validation, doctor, conformance
|   |-- identity/           # External OIDC validation and customer/member mapping
|   |-- protocol/           # TypeScript types, schemas, validation, protocol contracts
|   |-- reference/          # Deterministic loyalty engine and Admin snapshot model
|   |-- sdk/                # Domain SDK and generated low-level OpenAPI client
|   |-- server/             # Reference HTTP server and non-normative Admin API
|   |-- storage/            # Storage adapter interface
|   |-- storage-postgres/   # Normalized Postgres adapter, migrations, locks, leases
|   `-- storage-sqlite/     # Durable SQLite adapter for local and single-node use
|-- scripts/                # Spec, SDK, examples, and package verification scripts
|-- spec/                   # Normative prose, OpenAPI, generated schemas, and examples
`-- tests/                  # Unit, integration, and black-box conformance tests

Tech Stack 🧱

  • Language: TypeScript on Node.js 20.19+
  • Frontend: React, Vite, Tailwind CSS, lucide-react
  • API: Node HTTP server with OpenAPI 3.1 contract
  • Cloud: Separate Node management API with PostgreSQL control-plane state
  • Validation: JSON Schema Draft 2020-12 via TypeBox
  • SDK: Handwritten domain client plus generated low-level OpenAPI client
  • Storage: SQLite sandbox or normalized, tenant-scoped PostgreSQL
  • Testing: Vitest and black-box HTTP conformance tests
  • Packaging: npm (@loyalty-interchange/*, published with provenance) and Docker

Common Commands πŸ§‘β€πŸ’»

npm start             # Start the local sandbox and Admin dashboard
npm run serve         # Same sandbox path with the public command name
npm run lip -- doctor # Check discovery, health, auth, and capabilities
npm run lip -- test   # Run baseline HTTP conformance checks
npm run lip -- schemas                 # List supported JSON schemas
npm run lip -- validate spec/examples/paid-order.json --schema FoodserviceOrder
npm run example:sdk   # Run the full TypeScript SDK lifecycle
npm run typecheck     # Type-check all packages and Admin app
npm test              # Run the full test suite
npm run build         # Build TypeScript packages and Admin assets
npm run generate      # Regenerate schemas, OpenAPI, and SDK client
npm run verify        # Full local verification pipeline

Documentation πŸ“š

Full docs site: loyalty-interchange.mintlify.app

Developer guides (rendered on the docs site; sources live in docs/):

  • Quickstart β€” validation, Docker, reset, seed, and conformance details
  • Essentials β€” the six things every new integrator needs to know
  • TypeScript SDK β€” SDK operations, errors, money helpers, and order builder
  • Webhooks β€” signed CloudEvents after every successful mutation, with a durable retry outbox
  • Customer identity β€” connect an already-authenticated customer to a program-scoped LIP member
  • Reference platform β€” server, Admin, storage, and implementation boundaries
  • PostgreSQL storage β€” multi-instance engine store, location scoping, and the lock-free report path
  • Cloud control plane β€” organizations, projects, environments, provisioning, operator auth, and metering
  • Punchh migration β€” mapping restaurant loyalty capabilities to vendor-neutral LIP contracts

Repo-only docs (no published page):

  • Getting started β€” shortest path from clone to working request
  • API endpoints β€” routes, auth, examples, errors, retries, and webhooks
  • Engagement β€” segments, campaigns, exports, and messaging jobs
  • Releasing β€” release process for maintainers

Normative specification (canonical when docs and generated artifacts disagree):

What's Next? 🌟

Current priorities are tracked in PLAN.md. Near-term focus:

  • Minimal developer onboarding
  • Program-as-code configuration drafts with validation, preview, publish, and rollback
  • Reward wallet and reward management APIs
  • Webhook subscription management
  • Cloud provisioning worker, direct OIDC validation, and Stripe billing adapter
  • More SDK examples and machine-readable docs

Contributing 🀝

Contributions are welcome! Start with CONTRIBUTING.md, run npm run verify before opening a pull request, and keep protocol changes backed by schemas, examples, and conformance tests.

Security πŸ›‘οΈ

If you believe you've found a security vulnerability, please follow the responsible disclosure process in SECURITY.md rather than opening a public issue.

License πŸ“œ

This project is licensed under Apache-2.0.

Support πŸ’¬

If you have any questions, suggestions, or need assistance, please open an issue β€” let's build open loyalty infrastructure together! πŸ’ͺ

About

Open, vendor-neutral loyalty protocol and reference platform for restaurant, QSR, coffee, and franchise ordering systems. Protocol spec, reference engine, HTTP API, TypeScript SDK, Admin dashboard, and conformance tests.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages