Skip to content

Credit codes + invites: spend-only ad credit through crawlproof grants - #18

Merged
ralyodio merged 1 commit into
mainfrom
feat/credit-codes-invites
Oct 27, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/credit-codes-invites

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

  • Credit codes (@profullstack/redeem-credits 0.2.0, unit usd_cents = ad credit, prefix AD-). Redeem on /me ("Have a code?"), POST /api/v1/credits/redeem, adnetwork redeem <code>, MCP redeem_credit_code. Mint on dev2 with the module CLI against the app DB (README).
  • Invites (@profullstack/affiliates 0.3.0): 3 per account, /invites, /i/<code> (cookie an_invite, accepted at the CoinPay sign-in; or paste the code on /invites from another device), API GET/POST /api/v1/invites, POST /api/v1/invites/accept, CLI invites|invite|accept, MCP list_invites|create_invite. One accepted invite per account (already_invited, the other invite stays unused); bonus decided only after redeemInvite().ok. Accounts under 7 days old accept; senders must be 24 h old. Both get ADNETWORK_INVITE_BONUS_CENTS (default $5) of ad credit, except throwaway addresses (mailchecker), the inviter's own mailbox (+tag / Gmail dots), house accounts, accounts with no email; inviter half capped at ADNETWORK_INVITE_MONTHLY_CAP (5) per 30 days.

Money: how ad credit meets crawlproof

A deposit lands on two books: crawlproof's shared advertiser account (credit_purchases -> credits_balance, cash) and our deposits table (the person's share). A grant goes the same way, in this order:

  1. crawlproof POST /api/ads/v1/grants (Spend-only partner ad credit grants; code credits count as promo, not cash profullstack/crawlproof.com#394): ad_bonus_credits on the advertiser account, once per reference. ad_charge_click spends bonus first and pays publishers only from cash, so ad credit is spend-only: it runs ads, it can never be withdrawn as crypto, and clicks bought with it pay publishers nothing.
  2. here: a deposits row (coin credit, status complete, id credit:<source>) so the person's balance and the run/pause sweep see it.
    Both writes are idempotent on the source; if crawlproof is down the redemption stands and the grant is finished on the next try (already_redeemed -> repair; /invites repairs invite bonuses).

Security sweep

Sign-in is CoinPay OAuth, identity by sub (not email); /auth/start?next= only takes /[a-z]{1,20}; no client-supplied ids; admin-like powers (ADNETWORK_HOUSE_SUBS) are by sub. Nothing to fix found.

Tests

bun test: 23 pass (6 new: code once + spend-only grant, crawlproof-down repair, concurrent double-accept, /i/ -> CoinPay sign-in, invite rules, API). tsc --noEmit clean.

🤖 Generated with Claude Code

…f grants)

Credit codes (@profullstack/redeem-credits 0.2.0, unit usd_cents) and scarce
invites (@profullstack/affiliates 0.3.0, 3 each, one accepted per account).
Every grant goes to crawlproof first (POST /api/ads/v1/grants: ad_bonus_credits
on the shared advertiser account, runs ads, pays no publisher), then a
deposits row (coin 'credit') adds it to the person's balance. Both idempotent
on the source. /me "Have a code?", /invites, /i/<code> (accepted at CoinPay
sign-in), API, CLI (redeem, invites, invite, accept), MCP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​profullstack/​redeem-credits@​0.2.07610010090100
Added@​profullstack/​affiliates@​0.3.07610010092100
Addedmailchecker@​6.0.2110010010088100

View full report

@ralyodio
ralyodio merged commit 0ac53d5 into main Oct 27, 2026
3 checks passed
@ralyodio
ralyodio deleted the feat/credit-codes-invites branch October 27, 2026 03:24
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.

1 participant