Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "indie-payment-kit",
"version": "0.2.0",
"description": "One orchestrator that selects, installs, integrates, and sandbox-verifies payment providers for indie products.",
"version": "0.3.0",
"description": "One orchestrator that integrates official payment Skills into real projects and reports sandbox evidence.",
"author": {
"name": "BeatAPI",
"email": "support@beatapi.io",
Expand Down
127 changes: 80 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,85 @@
# Indie Payment Kit

One Skill that selects, installs, integrates, and sandbox-verifies payments without sending the
developer to a second provider Skill.
One Skill that takes a developer from an existing repository to a payment integration plan, code
changes, and sandbox evidence without handing the conversation to a second provider Skill.

```text
one install -> inspect project -> choose provider -> load official pack internally
-> write checkout/webhook/entitlement -> verify sandbox evidence
install once -> inspect the real project -> choose a provider -> load its official Skill internally
-> extend the existing payment domain or add a framework-native adapter
-> validate locally -> verify the sandbox flow -> report the evidence state
```

Built by [BeatAPI](https://beatapi.io) for independent developers using coding agents.
Built by [BeatAPI](https://beatapi.io) for developers using coding agents.

## What changed in v0.2
## v0.3 public beta

- The primary path is orchestration, not official-source handoff.
- Official Provider Skills remain upstream and are installed only when selected.
- The user continues talking to `indie-payment-kit`; provider packs are internal dependencies.
- Project inspection distinguishes Next.js, TanStack Start, Hono, generic Node, HTML with a
backend, and static HTML.
- Static HTML receives a safe Payment Link plan; a trusted backend unlocks verified webhooks and
entitlements.
- Every run ends with evidence states rather than a generic “integrated” claim.
- Seven provider packs are discovered and installed from provider-maintained Agent Skills: Stripe,
Dodo Payments, PayPal, Paddle, Polar, Alipay, and WeChat Pay.
- Creem is loaded from its official AI-agent Skill documentation until its published Skill exposes
a standard Skills CLI entry point.
- Provider packs install in a temporary directory and are copied to
`.indie-payment-kit/packs/`; existing user Skills are never removed.
- Existing payment modules, routes, SDKs, data layers, and environment-key names are detected before
any write plan is created.
- Mature projects use `extend-existing`; the kit does not generate a second payment domain.
- New Next.js App Router projects can materialize a one-time-payment sandbox starter for Stripe or
Dodo. Subscriptions and other frameworks use agent-guided implementation from the selected
official provider pack.

This beta does **not** claim that any provider is `sandbox-verified` or production-ready by default.
Generated files and successful builds are lower evidence states than a completed sandbox payment.

## Install

```bash
npx skills add https://github.com/BeatAPI/indie-payment-kit
```

Then ask:
Then ask one question, for example:

- “Use Indie Payment Kit to add Stripe subscriptions to this TanStack project and test them.”
- “Use Indie Payment Kit to add Stripe credit-pack payments to this TanStack project.”
- “Connect this Next.js app to Dodo Payments and verify the sandbox webhook.”
- “Add a safe payment option to this static HTML site.”
- “Choose and connect both a global and mainland-China payment route.”
- “Choose a global and mainland-China payment route for this SaaS.”
- “Review the existing payment module and migrate it without creating a second billing system.”

## Supported project targets
## Current execution modes

| Target | Integration mode |
| Project target | Current behavior |
|---|---|
| Next.js App Router | Full lifecycle |
| TanStack Start | Full lifecycle |
| Hono / Express / Fastify / Node | Full lifecycle |
| HTML or SPA with an API | Full lifecycle |
| Static HTML only | Hosted Payment Link; backend required for verified fulfillment |

## Provider coverage

Stripe, PayPal, Dodo Payments, Paddle, Polar, Creem, Alipay, and WeChat Pay remain selectable.
Stripe and Dodo are the first deep-orchestration targets; support labels remain conservative until
reproducible sandbox evidence exists.
| Existing payment implementation | Inspect and extend the existing domain with the selected official provider Skill |
| Next.js App Router, new project | Stripe/Dodo one-time sandbox starter; other flows are agent-guided |
| Next.js Pages Router | Agent-guided adaptation into the detected `pages` or `src/pages` tree |
| TanStack Start | Agent-guided native routes using the official provider pack and existing project conventions |
| Hono / Express / Fastify / Node | Agent-guided adapter inside the existing server/router structure |
| HTML or SPA with an API | Frontend checkout entry plus agent-guided server integration |
| Static HTML only | Hosted Payment Link; no automated entitlement without a trusted server |

“Agent-guided” still means the root Skill owns the task and writes the project changes. It means the
implementation is derived from the current official provider Skill rather than a maintained canned
template.

## Provider source policy

Indie Payment Kit does not invent provider APIs. Every route starts from an allowlisted,
provider-maintained Skill, toolkit, or official AI-agent source recorded in
`provider-packs.json`. The selected material is loaded internally and remains subject to the
project's architecture, authorization, secret, and production-mutation rules.

Seven current official sources and their selected entry Skill names were checked on 2026-08-31.
Installer isolation, integrity matching, and selective copying are covered by local tests; this is
not a claim that every upstream download was re-executed for this release. Creem remains a manual
official-Skill source because its current repository is not discoverable through the standard
Skills CLI.

## Deterministic tools

Inspect a project without reading secrets:
Inspect without reading secret values:

```bash
npm run inspect -- /path/to/project
```

Choose a route:
Recommend a route and build a framework-aware plan:

```bash
npm run recommend -- \
Expand All @@ -68,34 +89,46 @@ npm run recommend -- \
--billing subscription \
--tax managed \
--stack tanstack
```

Build a framework-aware execution plan:

```bash
npm run plan -- \
--project /path/to/project \
--provider dodo \
--billing subscription
```

Inspect a Provider Pack before installation:
Inspect a provider pack before the approved download:

```bash
npm run provider-pack -- --provider stripe --billing one-time
```

Materialization is intentionally narrow:

```bash
npm run provider-pack -- --provider stripe --billing subscription
npm run materialize -- \
--project /path/to/new-nextjs-project \
--provider stripe \
--billing one-time
```

The provider-pack command is dry-run by default. The root Skill runs `--install --yes` only after
the user approves the official source, external download, and repository changes.
It writes only new Next.js App Router Stripe/Dodo one-time sandbox starters. Existing payment
domains, subscriptions, TanStack, Hono, Node, and other providers stay in the official-pack-driven
agent path.

## Safety boundary
## Safety and evidence boundary

- No default telemetry or credential collection.
- No `.env` value reads.
- No browser-side secret keys.
- No shell interpolation from user-controlled provider names.
- Sandbox first; live external mutations require fresh confirmation.
- No claim of merchant approval or successful payment without direct evidence.
- No `.env` value reads and no browser-side secret keys.
- External pack downloads and repository writes require an explicit plan confirmation.
- Product and price identifiers are selected on the trusted server in checked-in starters.
- The included JSON store is a local sandbox seam, not a production or multi-instance database.
- Generated checkout routes require `INDIE_PAYMENT_KIT_ENABLE_SANDBOX_CHECKOUT=true` locally and
remain disabled when `NODE_ENV=production`; production integrations must add project-native
authentication and rate limiting.
- Live products, webhooks, refunds, subscriptions, and other account mutations require fresh
confirmation.
- Merchant approval, sandbox payment success, and production collection are never inferred from
generated code.

## Verify

Expand Down
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ payloads in issues, pull requests, fixtures, or examples.
Report suspected vulnerabilities privately to `support@beatapi.io`. Include a
minimal reproduction with secrets and personal data removed.

Official provider packs are isolated under `.indie-payment-kit/packs/` and must
not remain in agent skill discovery directories. Installer npm packages are
integrity-checked before execution. Project writes reject broad filesystem
targets and symbolic-link destinations.

This project provides integration guidance and local decision tooling. It does
not custody funds or provide a hosted payment service.
25 changes: 19 additions & 6 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ a handoff destination.
| Official pack source and installer | `provider-packs.json` + `provider-pack.mjs` |
| Project shape and trusted server | `inspect-project.mjs` |
| Planned files and evidence target | `plan-integration.mjs` |
| Current API details | Selected official provider pack |
| Checked-in write templates | `templates/` + `materialize-integration.mjs` |
| Current API details | Isolated official provider pack |
| Product-domain invariants | `lifecycle-contract.md` |
| Completion claims | `go-live-checklist.md` |

Expand All @@ -47,12 +48,23 @@ Payment-domain behavior is shared. Framework adapters own only:
The first adapter families are Next.js App Router, TanStack Start, Hono, generic Node, HTML with a
backend, and static HTML Payment Links.

Checked-in templates and framework support are separate concepts. Templates are optional sandbox
accelerators. The root Skill can use a current official provider pack to write a native TanStack,
Hono, Node, Pages Router, or other adapter without maintaining a provider-by-framework template
matrix. Plans expose `checked-in-sandbox-template`, `agent-guided`, or `payment-link` truthfully.

Before choosing either path, inspection searches for existing payment modules, routes, SDKs, data
layers, and environment-key names. An existing domain selects `extend-existing` and suppresses
generic template writes.

## Provider-pack seam

Provider packs are selected-provider-only and project-local where the official installer supports
it. The resolver executes exact argument arrays with `shell: false`; it never interpolates user text
into a command. Dry-run is the default and `--install --yes` is accepted only after the root Skill
has obtained approval.
Provider packs are selected-provider-only. The allowlisted installer runs in a temporary project,
then only the confirmed Skills are copied to `.indie-payment-kit/packs/`. User-owned discovery
directories are never removed or rewritten. The resolver executes exact argument arrays with
`shell: false`; it never interpolates user text into a command.
Pinned npm installer packages are integrity-checked before spawn. Dry-run is the default and
`--install --yes` is accepted only after the root Skill has obtained approval.

Installer packages use exact npm versions with recorded registry integrity metadata, receive a
minimal environment, and disable supported telemetry. Provider content remains an explicitly
Expand All @@ -68,7 +80,8 @@ MCP login or host restart is an optional acceleration path, not a prerequisite f
- Recommendation and planning are local and deterministic.
- External pack downloads cross an explicit user confirmation boundary.
- Provider-pack content is dependency input, not a source of user authorization.
- Project writes remain inside the user-approved repository.
- Project writes canonicalize the approved repository and reject broad targets or symbolic-link
destinations before materializing templates or copying provider packs.
- Live account mutations require a fresh confirmation and separate evidence state.

## Static web boundary
Expand Down
31 changes: 17 additions & 14 deletions docs/PRD.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Indie Payment Kit PRD

- 产品版本:v0.2 单入口编排器
- 产品版本:v0.3 public beta
- 项目归属:BeatAPI
- 开源仓库:`BeatAPI/indie-payment-kit`
- 核心形态:一个用户入口 Skill + 按需加载的官方 Provider Pack
Expand Down Expand Up @@ -60,27 +60,30 @@ Indie Payment Kit 让独立开发者只安装一个 Skill、只描述一次需

框架不是支付产品差异,而是安全代码落点差异。

| 项目形态 | v0.2 行为 |
| 项目形态 | v0.3 beta 行为 |
|---|---|
| Next.js App Router | 原生 Route Handler 接入 |
| TanStack Start | 原生 Server Route 接入 |
| Hono/Express/Fastify/Node | 复用已有后端路由和服务层 |
| HTML/SPA + API | 前端按钮 + 通用后端完整闭环 |
| 已有支付实现 | 识别并扩展现有支付域,禁止生成第二套订单/权益模型 |
| Next.js App Router | Stripe/Dodo 一次性支付沙箱脚手架;其他能力由官方 Pack 驱动适配 |
| TanStack Start | 官方 Provider Skill 驱动,写入原生 Server Route 并复用现有架构 |
| Hono/Express/Fastify/Node | 官方 Provider Skill 驱动,复用已有后端路由和服务层 |
| HTML/SPA + API | 前端入口 + 官方 Provider Skill 驱动的后端接入 |
| 纯静态 HTML | Payment Link;明确提示无法自动验签和开权益 |

完整支付闭环必须有可信服务端。浏览器不得保存 Secret Key、验证 webhook 或直接授予权益。

## 6. 支付商范围与能力等级

| 支付商 | 选型 | 内部加载官方源 | 框架编排目标 |
| 支付商 | 选型 | 内部官方源 | 当前执行方式 |
|---|---:|---:|---:|
| Stripe | 是 | 是 | P0 |
| Dodo Payments | 是 | 是 | P0 |
| 支付宝 | 是 | 是 | P1 |
| 微信支付 | 是 | 是 | P1 |
| PayPal、Paddle、Polar、Creem | 是 | 是 | P2 |

八家可以被推荐,不代表八家已具备同等级沙箱证据。所有输出必须显示能力等级。
| Stripe | 是 | 可安装官方 Skill | Next.js 一次性脚手架 + Agent 自主适配 |
| Dodo Payments | 是 | 可安装官方 Skills | Next.js 一次性脚手架 + Agent 自主适配 |
| 支付宝 | 是 | 可安装官方 Skill | Agent 自主适配 |
| 微信支付 | 是 | 可安装官方 Skill | Agent 自主适配 |
| PayPal、Paddle、Polar | 是 | 可安装官方 Skills | Agent 自主适配 |
| Creem | 是 | 官方 Skill 文档 | Agent 直接读取官方源后适配 |

八家可以被推荐,不代表八家已具备同等级沙箱证据。v0.3 没有任何支付商声明为
`sandbox-verified`,所有输出必须显示能力等级。

## 7. P0 需求

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "indie-payment-kit",
"version": "0.2.0",
"version": "0.3.0",
"private": true,
"description": "One orchestrator that selects, installs, integrates, and sandbox-verifies payment providers for indie products.",
"description": "One payment-integration Skill that extends real projects from official provider packs and reports sandbox evidence.",
"type": "module",
"scripts": {
"recommend": "node skills/indie-payment-kit/scripts/recommend.mjs",
"inspect": "node skills/indie-payment-kit/scripts/inspect-project.mjs",
"plan": "node skills/indie-payment-kit/scripts/plan-integration.mjs",
"materialize": "node skills/indie-payment-kit/scripts/materialize-integration.mjs",
"provider-pack": "node skills/indie-payment-kit/scripts/provider-pack.mjs",
"test": "node --test test/*.test.mjs",
"validate": "node scripts/validate-repo.mjs",
Expand Down
13 changes: 12 additions & 1 deletion scripts/validate-repo.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ async function main() {

const packageJson = await readJson('package.json');
assert(packageJson.version === manifest.version, 'package.json and plugin versions must match.');
const packageLock = await readJson('package-lock.json');
assert(packageLock.version === packageJson.version, 'package-lock.json and package versions must match.');
assert(packageLock.packages?.['']?.version === packageJson.version, 'package-lock root package version must match.');

const skill = await readFile(path.join(skillRoot, 'SKILL.md'), 'utf8');
assert(skill.startsWith('---\nname: indie-payment-kit\n'), 'Skill frontmatter is missing or invalid.');
assert(!skill.includes('[TODO:'), 'Skill contains unfinished scaffold placeholders.');
assert(skill.includes('Never finish by telling the user to invoke'), 'Skill must preserve the single-entry invariant.');
assert(skill.includes('Never tell the user to continue in a provider Skill'), 'Skill must preserve the single-entry invariant.');

const openaiYaml = await readFile(path.join(skillRoot, 'agents', 'openai.yaml'), 'utf8');
assert(openaiYaml.includes('$indie-payment-kit'), 'Default prompt must mention $indie-payment-kit.');
Expand All @@ -66,6 +69,12 @@ async function main() {
for (const [providerId, pack] of Object.entries(providerPacks.providers)) {
assert(ids.has(providerId), `Unknown provider pack: ${providerId}`);
assert(pack.source.startsWith('https://'), `${providerId} provider-pack source must be HTTPS.`);
assert(pack.sourceAuthority === 'official-provider', `${providerId} must use a provider-maintained source.`);
assert(
['well-known-skills', 'repository-skills', 'official-skill-manual'].includes(pack.sourceType),
`${providerId} has an unsupported provider source type.`,
);
assert(/^\d{4}-\d{2}-\d{2}$/.test(pack.verifiedAt), `${providerId} source verification date is missing.`);
assert(
Array.isArray(pack.entrySkills) && pack.entrySkills.every((skill) => /^[a-z0-9][a-z0-9-]*$/.test(skill)),
`${providerId} contains an unsafe internal Skill name.`,
Expand All @@ -75,6 +84,8 @@ async function main() {
assert(pack.install[0] === 'npx', `${providerId} installer must use the allowlisted npx executable.`);
assert(!pack.install.some((token) => /[;&|`$\n\r]/.test(token)), `${providerId} installer contains shell control characters.`);
assert(!pack.install.some((token) => token.includes('@latest')), `${providerId} installer must not use a floating npm latest tag.`);
const agentIndex = pack.install.indexOf('--agent');
assert(pack.install[agentIndex + 1] === 'codex', `${providerId} staging install must target only the Codex discovery path.`);
assert(/^sha512-[A-Za-z0-9+/]+=*$/.test(pack.installerIntegrity), `${providerId} installer integrity metadata is missing.`);
}
}
Expand Down
Loading
Loading