Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Agents
openreceive/laravel
claude-code
cursor
checkout
payments
laravel
bitcoin
Lightning
payment-gateway
self-hosted
USDT
stablecoin
USDC
nostr
nwc
bitcoin-payments

Optimize for a small, honest API and a good developer experience.

Install
php artisan boost:add-skill openreceive/laravel

Save this content to: AGENTS.md

# OpenReceive Agent Rules

Optimize for a
small, honest API and a good developer experience.

## Product overviews

Every README that provides a basic OpenReceive, package, integration, or demo
overview must mention optional swaps and name USDT, USDC, SOL, and ETH. Explain
that a configured swap provider converts these payments to BTC over Lightning
in the merchant's connected wallet, with asset and network availability depending
on the provider. Keep package descriptions consistent with this positioning;
describe supporting libraries in the context of the full integration.
Lead public package READMEs with what the developer can build and the package's
specific role. Include installation requirements and a working quickstart link
before detailed internals. Use links that resolve from published packages and
split repositories. Keep registry descriptions aligned with the README; avoid
blanket security guarantees or implying that a helper package is a full backend.

## Non-negotiables

- OpenReceive never owns orders, users, prices, or fulfillment, and never requires a separate
  database, Redis, or migration runner. It MAY own payment-attempt rows (`openreceive_payments`)
  inside the host application's existing database: the host passes its database handle and runs
  the migration through its own workflow; the library owns the schema, locking, settlement
  write-once, and reconciliation state machine. Implementing a custom
  `PaymentRepository` is the documented escape hatch, never the quickstart.
- The host owns orders and prices. Direct server code passes `{ reference, amount }`; mounted
  HTTP handlers resolve the amount from host-owned data and reject payer-supplied amounts.
- One `openreceive_payments` row per attempt is committed before payer instructions are
  exposed. A reference may have multiple historical attempts; `payment_hash` is globally unique,
  settlement is write-once per attempt, and fulfillment runs only for the reference's first settled
  attempt.
- Attempts carry an explicit status (`pending`, `settled`, `expired`, `failed`, `attention`).
  Only `pending` attempts are reconciled; closure of an unpaid attempt requires a successful
  wallet scan at or after expiry plus `OPENRECEIVE_ATTEMPT_EXPIRY_GRACE_SECONDS` (an exported
  constant, 900 seconds — not an environment variable) — a local clock alone never closes a
  row. A settled row is never overwritten.
- Settlement discovery is opportunistic by default: every mounted OpenReceive route first runs
  one reconcile pass through the durable `openreceive_meta` gate (CAS in the host database,
  minimum 3 seconds between real wallet scans, stretched by invoice age), shared by every
  worker/process — the gate IS the NWC scan budget, and `payments/check` serves the requested
  hash from that pass (or the host row on `gate_busy`), never a second per-invoice wallet
  walk. No web process starts a settlement timer; the optional notifications worker
  (NWC-02 listener + periodic pass) is a separate process. A custom repository without
  `claimReconcileGate` must disable `opportunisticReconcile` explicitly — the default
  settlement path never degrades silently, and process-local memory never backs the gate.
- A retry or concurrent create serializes per reference inside the library repository. A reference has
  one live payment session; within it, at most one live attempt per rail/asset so a payer can
  switch methods. The host never sees the live/supersede/conflict vocabulary — it sees an order
  as unpaid or paid. Do not add a separately configured OpenReceive idempotency store.
- Receive-only NWC codes must never reach browser/mobile code, logs, tests, screenshots,
  docs, source maps, or demo assets. Receive APIs never expose send-payment methods. Wallet
  preflight fails closed when the connection advertises spend methods; booting anyway requires
  the explicit `allowSpendCapableWallet` / `OPENRECEIVE_ALLOW_SPEND_CAPABLE_NWC` override.
- NWC notifications are authenticated wallet data: a conforming client decrypts them with the
  same key material that authenticates RPC responses. A `payment_received` payload that
  satisfies the settlement rule (`settled_at` or `transaction_state/state == "settled"`; a
  preimage alone is corroborating evidence) settles the matching pending attempt directly,
  with no redundant wallet scan for that invoice. Anything less — a payload without a finality
  signal, or an unknown payment hash — only triggers a bounded reconciliation scan. The
  notifications worker's own periodic pass (plus request-path opportunistic reconcile) remains
  the safety net for notifications missed while offline. Direct settlement
  assumes the NWC client binds notification decryption to the connection's wallet pubkey (the
  bundled SDK does); a custom client that skips author verification must not be granted it.
- Use `amount_msats` for millisatoshi values in public results and exact integer/decimal money
  math. Never use binary floats for fiat math.
- Swap provider credentials live only in the host payment attempt's optional server-only
  `swap_data` field.
  They never appear in browser responses or logs. Provider completion is not wallet
  settlement; refund decisions refresh provider state.
- Do not duplicate provider data, supported currencies, settlement rules, polling cadence, or
  demo product data.
- Schema or route changes update their vectors in the same change. Invoice behavior needs
  host-row retry/concurrency tests; settlement behavior needs replay-safe tests.
- We should not worry about validating the NWC's responses or behavior: a user of OpenReceive implicitly
  trusts their backing NWC service, because they will need to use that NWC service anyway to withdraw any funds.
  OpenReceive users can also build their own NWC service, or run one on their own
  hardware, like an Alby Hub instance.

## Shipped routes and hooks

- `@openreceive/http` adapters and the Rails engine ship the route set in
  `spec/openapi/openreceive-http.v1.yaml`.
- The host keeps authentication. The quickstart host contract is `authorize`, `amountFor`,
  and `onPaid` plus a database handle; the library derives
  `resolveCheckout` / `onCheckoutCreated` and the reconciliation transitions from its own
  repository. The advanced hook surface remains for custom-repository hosts.
- OpenReceive mints no authentication, recovery, or refund tokens. The host authorizes every
  request and verifies the requested `payment_hash` belongs to the reference before resolving
  server-only `swap_data`.
- `onCheckoutCreated` runs before a create response. Failure returns 409 and withholds the
  invoice or swap instructions.

## Releases

General package releases do not publish the BTCPay Server plugin. Its source
version is independent of the npm/gem release version. A source version bump
does not authorize submitting a Plugin Builder build or publishing the plugin;
do either only when the user explicitly requests a BTCPay release.

ALWAYS GIVE THE MAINTAINER THE APPROVAL LINKS. Pushing a release tag starts
`Publish Gems`, `Publish PyPI` and `Publish Composer`, and each waits for a
maintainer's click in the browser. Gems, PyPI, Packagist and the GitHub
release all stall until then. As soon as the runs exist, list all three
labelled run URLs (`https://github.com/OpenReceive/openreceive/actions/runs/<id>`)
from:

```sh
gh run list --repo OpenReceive/openreceive --branch v<x.y.z> --json workflowName,status,url
```

Put them in the LAST message of the turn that pushed the tag. Text between tool
calls does not count, because the maintainer may never see it. Repeat them at
the end of every later release message until each run is approved, and name
any stale run from an older tag that must not be approved. This step has been
missed before; it is part of the release, not a courtesy.

Publishing the GitHub release starts a fourth gated run, `Publish WordPress.org`,
which commits the release's WordPress ZIP to the plugin directory. Give its URL
the same way, in the last message of the turn that published the release:

```sh
gh run list --repo OpenReceive/openreceive --workflow publish-wordpress.yml --limit 1 --json status,headBranch,url
```

## Testing

Run demo application servers and their backing services in Docker. Builds,
tests, lint/type checks, browser automation, and release verification may run
on the host or in Docker. The Docker requirement applies to running the demo
applications, not to the verification tools or test runners.

Use the smallest relevant test while iterating. `npm test` is the JS suite; the contract and
secret check is:

```sh
npm run check
```

For JS/TS changes, run a focused test first and then at minimum:

```sh
npm run typecheck && npm test
```

For broad route, package, contract, schema, release, or deployment changes, run:

```sh
npm run test:ci
```

Wallet behavior also requires `npm run test:live:nwc`; it must skip clearly when `nwc` is not
configured. Ruby is a second settlement engine and must match the shared money, settlement,
swap-data, and HTTP vectors:

```sh
npm run test:ruby
```

Before declaring work done, report the exact checks run and any intentional skip.

## Trust model

Our own server, the configured NWC wallet, and the configured swap provider are trusted. The
frontend formats what the server sent: a throw in a checkout panel is a bug in our own API
surfacing, not a display-boundary bug class to defend against. Do not reintroduce
"untrusted-wire" readers or blanking display wrappers for our own JSON, NWC replies, or
FixedFloat deposit addresses; adapter work (field aliases, string-to-number coercion) is fine.

Keep validating what is genuinely untrusted: the payer and browser client (payment_hash shape,
refund-address checksums, request bodies hitting HTTP handlers), the host amount callback
(`amount_for` / `amountFor` — the host owns prices), and public price feeds (fail closed on
missing or stale rates). Invoice expiry keeps its rule: local clock alone never closes a row — a
successful wallet scan at/after expiry plus the grace window is the close rule, and an
unrecognized `list_transactions` shape must fail the scan rather than look empty, because an
empty-looking scan at expiry+grace closes unpaid attempts.

## Private boundary

Do not add private openreceive.org application code, infrastructure inventory, host IPs,
deployment credentials, analytics, landing pages, or business logic to this public repo.

Never commit an absolute path into a contributor's home folder (`/Users/<name>/…`,
`/home/<name>/…`); it publishes their account name. Write repo-relative paths, or `~/`
for tool locations. `npm run scan:secrets` fails on them.

Specify openreceive.org changes here through the generated `docs/site-contract.json`
and `docs/internal/site-build.md`. Update the canonical docs, agent directions, or
contract generator, then regenerate the docs bundle. The private Rails app consumes
that revision through its docs sync and applies the requirements. Use this one-way
workflow for site routes and redirects too; a specification change here does not
require locating or editing the private site repository.

OpenReceive Agent Rules

Optimize for a small, honest API and a good developer experience.

Product overviews

Every README that provides a basic OpenReceive, package, integration, or demo overview must mention optional swaps and name USDT, USDC, SOL, and ETH. Explain that a configured swap provider converts these payments to BTC over Lightning in the merchant's connected wallet, with asset and network availability depending on the provider. Keep package descriptions consistent with this positioning; describe supporting libraries in the context of the full integration. Lead public package READMEs with what the developer can build and the package's specific role. Include installation requirements and a working quickstart link before detailed internals. Use links that resolve from published packages and split repositories. Keep registry descriptions aligned with the README; avoid blanket security guarantees or implying that a helper package is a full backend.

Non-negotiables

  • OpenReceive never owns orders, users, prices, or fulfillment, and never requires a separate database, Redis, or migration runner. It MAY own payment-attempt rows (openreceive_payments) inside the host application's existing database: the host passes its database handle and runs the migration through its own workflow; the library owns the schema, locking, settlement write-once, and reconciliation state machine. Implementing a custom PaymentRepository is the documented escape hatch, never the quickstart.
  • The host owns orders and prices. Direct server code passes { reference, amount }; mounted HTTP handlers resolve the amount from host-owned data and reject payer-supplied amounts.
  • One openreceive_payments row per attempt is committed before payer instructions are exposed. A reference may have multiple historical attempts; payment_hash is globally unique, settlement is write-once per attempt, and fulfillment runs only for the reference's first settled attempt.
  • Attempts carry an explicit status (pending, settled, expired, failed, attention). Only pending attempts are reconciled; closure of an unpaid attempt requires a successful wallet scan at or after expiry plus OPENRECEIVE_ATTEMPT_EXPIRY_GRACE_SECONDS (an exported constant, 900 seconds — not an environment variable) — a local clock alone never closes a row. A settled row is never overwritten.
  • Settlement discovery is opportunistic by default: every mounted OpenReceive route first runs one reconcile pass through the durable openreceive_meta gate (CAS in the host database, minimum 3 seconds between real wallet scans, stretched by invoice age), shared by every worker/process — the gate IS the NWC scan budget, and payments/check serves the requested hash from that pass (or the host row on gate_busy), never a second per-invoice wallet walk. No web process starts a settlement timer; the optional notifications worker (NWC-02 listener + periodic pass) is a separate process. A custom repository without claimReconcileGate must disable opportunisticReconcile explicitly — the default settlement path never degrades silently, and process-local memory never backs the gate.
  • A retry or concurrent create serializes per reference inside the library repository. A reference has one live payment session; within it, at most one live attempt per rail/asset so a payer can switch methods. The host never sees the live/supersede/conflict vocabulary — it sees an order as unpaid or paid. Do not add a separately configured OpenReceive idempotency store.
  • Receive-only NWC codes must never reach browser/mobile code, logs, tests, screenshots, docs, source maps, or demo assets. Receive APIs never expose send-payment methods. Wallet preflight fails closed when the connection advertises spend methods; booting anyway requires the explicit allowSpendCapableWallet / OPENRECEIVE_ALLOW_SPEND_CAPABLE_NWC override.
  • NWC notifications are authenticated wallet data: a conforming client decrypts them with the same key material that authenticates RPC responses. A payment_received payload that satisfies the settlement rule (settled_at or transaction_state/state == "settled"; a preimage alone is corroborating evidence) settles the matching pending attempt directly, with no redundant wallet scan for that invoice. Anything less — a payload without a finality signal, or an unknown payment hash — only triggers a bounded reconciliation scan. The notifications worker's own periodic pass (plus request-path opportunistic reconcile) remains the safety net for notifications missed while offline. Direct settlement assumes the NWC client binds notification decryption to the connection's wallet pubkey (the bundled SDK does); a custom client that skips author verification must not be granted it.
  • Use amount_msats for millisatoshi values in public results and exact integer/decimal money math. Never use binary floats for fiat math.
  • Swap provider credentials live only in the host payment attempt's optional server-only swap_data field. They never appear in browser responses or logs. Provider completion is not wallet settlement; refund decisions refresh provider state.
  • Do not duplicate provider data, supported currencies, settlement rules, polling cadence, or demo product data.
  • Schema or route changes update their vectors in the same change. Invoice behavior needs host-row retry/concurrency tests; settlement behavior needs replay-safe tests.
  • We should not worry about validating the NWC's responses or behavior: a user of OpenReceive implicitly trusts their backing NWC service, because they will need to use that NWC service anyway to withdraw any funds. OpenReceive users can also build their own NWC service, or run one on their own hardware, like an Alby Hub instance.

Shipped routes and hooks

  • @openreceive/http adapters and the Rails engine ship the route set in spec/openapi/openreceive-http.v1.yaml.
  • The host keeps authentication. The quickstart host contract is authorize, amountFor, and onPaid plus a database handle; the library derives resolveCheckout / onCheckoutCreated and the reconciliation transitions from its own repository. The advanced hook surface remains for custom-repository hosts.
  • OpenReceive mints no authentication, recovery, or refund tokens. The host authorizes every request and verifies the requested payment_hash belongs to the reference before resolving server-only swap_data.
  • onCheckoutCreated runs before a create response. Failure returns 409 and withholds the invoice or swap instructions.

Releases

General package releases do not publish the BTCPay Server plugin. Its source version is independent of the npm/gem release version. A source version bump does not authorize submitting a Plugin Builder build or publishing the plugin; do either only when the user explicitly requests a BTCPay release.

ALWAYS GIVE THE MAINTAINER THE APPROVAL LINKS. Pushing a release tag starts Publish Gems, Publish PyPI and Publish Composer, and each waits for a maintainer's click in the browser. Gems, PyPI, Packagist and the GitHub release all stall until then. As soon as the runs exist, list all three labelled run URLs (https://github.com/OpenReceive/openreceive/actions/runs/<id>) from:

gh run list --repo OpenReceive/openreceive --branch v<x.y.z> --json workflowName,status,url

Put them in the LAST message of the turn that pushed the tag. Text between tool calls does not count, because the maintainer may never see it. Repeat them at the end of every later release message until each run is approved, and name any stale run from an older tag that must not be approved. This step has been missed before; it is part of the release, not a courtesy.

Publishing the GitHub release starts a fourth gated run, Publish WordPress.org, which commits the release's WordPress ZIP to the plugin directory. Give its URL the same way, in the last message of the turn that published the release:

gh run list --repo OpenReceive/openreceive --workflow publish-wordpress.yml --limit 1 --json status,headBranch,url

Testing

Run demo application servers and their backing services in Docker. Builds, tests, lint/type checks, browser automation, and release verification may run on the host or in Docker. The Docker requirement applies to running the demo applications, not to the verification tools or test runners.

Use the smallest relevant test while iterating. npm test is the JS suite; the contract and secret check is:

npm run check

For JS/TS changes, run a focused test first and then at minimum:

npm run typecheck && npm test

For broad route, package, contract, schema, release, or deployment changes, run:

npm run test:ci

Wallet behavior also requires npm run test:live:nwc; it must skip clearly when nwc is not configured. Ruby is a second settlement engine and must match the shared money, settlement, swap-data, and HTTP vectors:

npm run test:ruby

Before declaring work done, report the exact checks run and any intentional skip.

Trust model

Our own server, the configured NWC wallet, and the configured swap provider are trusted. The frontend formats what the server sent: a throw in a checkout panel is a bug in our own API surfacing, not a display-boundary bug class to defend against. Do not reintroduce "untrusted-wire" readers or blanking display wrappers for our own JSON, NWC replies, or FixedFloat deposit addresses; adapter work (field aliases, string-to-number coercion) is fine.

Keep validating what is genuinely untrusted: the payer and browser client (payment_hash shape, refund-address checksums, request bodies hitting HTTP handlers), the host amount callback (amount_for / amountFor — the host owns prices), and public price feeds (fail closed on missing or stale rates). Invoice expiry keeps its rule: local clock alone never closes a row — a successful wallet scan at/after expiry plus the grace window is the close rule, and an unrecognized list_transactions shape must fail the scan rather than look empty, because an empty-looking scan at expiry+grace closes unpaid attempts.

Private boundary

Do not add private openreceive.org application code, infrastructure inventory, host IPs, deployment credentials, analytics, landing pages, or business logic to this public repo.

Never commit an absolute path into a contributor's home folder (/Users/<name>/…, /home/<name>/…); it publishes their account name. Write repo-relative paths, or ~/ for tool locations. npm run scan:secrets fails on them.

Specify openreceive.org changes here through the generated docs/site-contract.json and docs/internal/site-build.md. Update the canonical docs, agent directions, or contract generator, then regenerate the docs bundle. The private Rails app consumes that revision through its docs sync and applies the requirements. Use this one-way workflow for site routes and redirects too; a specification change here does not require locating or editing the private site repository.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment