Skip to main content
Glama
Jayvy2002

prometheus-potential

by Jayvy2002
README.md
# Prometheus Potential

Agent efficiency API — facts, citations, cache, project memory, MCP.

| Surface | URL |
| --- | --- |
| Marketing (Netlify target) | https://prometheuspotential.com |
| API (Cloudflare Worker `distill`) | https://distill.prometheus-potential.workers.dev |
| Source | https://github.com/Jayvy2002/prometheus-potential |

The Worker script id stays `distill` for Cloudflare continuity. User-facing brand is **Prometheus Potential**.

This repository is the production MVP specified in `docs/MVP.md`.

## Clone and connect Netlify

```bash
git clone https://github.com/Jayvy2002/prometheus-potential.git
cd prometheus-potential
```

In Netlify: **Add new site → Import an existing project → GitHub → `Jayvy2002/prometheus-potential`**.

| Setting | Value |
| --- | --- |
| Branch | `main` |
| Build command | `npm run build:site` |
| Publish directory | `site/dist` |
| Node | 22 (`netlify.toml` sets `NODE_VERSION` and `NPM_FLAGS=--include=dev`) |

`netlify.toml` is already in the repo. Marketing HTML is generated from `src/site` at build time. `/v1/*`, `/health`, `/signup`, `/billing/*`, `/webhooks/*`, and `/openapi.json` proxy to the Worker so `/start` forms work on the marketing host.

Do **not** put `KEY_PEPPER`, `ADMIN_TOKEN`, or Stripe secrets in Netlify env — those belong on the Worker.

Custom domain: add `prometheuspotential.com` in the Netlify UI (DNS). The API can stay on `workers.dev` until a Worker custom domain is wired.

## What you get

| Method | Path | Auth |
| --- | --- | --- |
| GET | `/health` | no |
| POST | `/v1/signup` | no (IP rate-limited) |
| POST | `/v1/distill` | Bearer API key |
| POST | `/v1/remember` | Bearer API key |
| GET | `/v1/recall?project_id=&q=` | Bearer API key |
| GET | `/v1/usage` | Bearer API key |
| POST | `/v1/keys` | `ADMIN_TOKEN` |
| POST | `/v1/billing/checkout` | Bearer API key |
| POST | `/billing/go` | form `api_key` |
| POST | `/v1/billing/portal` | Bearer API key |
| POST | `/webhooks/stripe` | Stripe-Signature |

Marketing and legal (footer on every page; listed in `/sitemap.xml` and `/robots.txt`): `/` `/pricing` `/docs` `/docs/api` `/docs/agents` `/start` `/privacy` `/terms` `/aup` `/security` `/cookies` `/refunds` `/subprocessors` `/contact` `/status` `/mcp`.

## Quickstart

Create a free live key (self-serve, no operator):

1. Open https://distill.prometheus-potential.workers.dev/start (or `/start` on the marketing host once Netlify is connected)
2. Submit the form (or `POST /v1/signup`)
3. Copy the `dk_live_…` secret — Prometheus Potential stores an HMAC only

```bash
export DISTILL_API_URL=https://distill.prometheus-potential.workers.dev
export DISTILL_API_KEY='dk_live_your_key'

curl -sS "$DISTILL_API_URL/v1/distill" \
  -H "Authorization: Bearer $DISTILL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/","budget":"fast"}'
```

`budget=fast` = 1 unit. `budget=deep` = 3 units (stronger model, longer extract). Cache hits cost 0.

## Local development

Requires Node 20+. `npm run dev` is fully local (D1/KV simulators, heuristic distill if Workers AI is unavailable). `npm run dev:edge` needs `wrangler login` for the AI binding.

```bash
cp .dev.vars.example .dev.vars
# set KEY_PEPPER and ADMIN_TOKEN to long random strings — never commit .dev.vars
npm install
npx wrangler d1 migrations apply distill-db --local
KEY_PEPPER=$(grep KEY_PEPPER .dev.vars | cut -d= -f2) node scripts/seed-demo.mjs
# apply the printed SQL:
npx wrangler d1 execute distill-db --local --command "<SQL from seed>"
npm run dev
# default: http://127.0.0.1:43123  (no Workers AI; heuristic fallback)
# npm run dev:edge  — requires `wrangler login` for the AI binding
bash scripts/smoke.sh
npm run dogfood   # two URLs, remember+recall, asserts cache HIT
npm run build:site   # static marketing → site/dist (Netlify publish dir)
```

Internal dogfood (live by default, or set `DISTILL_API_URL` / `DISTILL_API_KEY`):

```bash
DISTILL_API_URL=https://distill.prometheus-potential.workers.dev npm run dogfood
```

Unit tests (SSRF, rate limit, HMAC keys, Stripe signatures):

```bash
npm test
```

## Deploy (Cloudflare Worker)

```bash
npx wrangler d1 migrations apply distill-db --remote
node scripts/seed-demo.mjs   # copy SQL
npx wrangler d1 execute distill-db --remote --command "<SQL>"
printf '%s' "$KEY_PEPPER" | npx wrangler secret put KEY_PEPPER
printf '%s' "$ADMIN_TOKEN" | npx wrangler secret put ADMIN_TOKEN
printf '%s' "$DISTILL_PRO_PAYMENT_LINK" | npx wrangler secret put DISTILL_PRO_PAYMENT_LINK
# optional
# printf '%s' "$OPENAI_API_KEY" | npx wrangler secret put OPENAI_API_KEY
# printf '%s' "$STRIPE_SECRET_KEY" | npx wrangler secret put STRIPE_SECRET_KEY
# printf '%s' "$STRIPE_WEBHOOK_SECRET" | npx wrangler secret put STRIPE_WEBHOOK_SECRET
npx wrangler deploy
DISTILL_API_URL=https://distill.prometheus-potential.workers.dev bash scripts/smoke.sh
```

Mint a private key (anyone):

```bash
curl -sS https://distill.prometheus-potential.workers.dev/v1/signup \
  -H "Content-Type: application/json" \
  -d '{"label":"prod"}'
```

Admin-only mint (plan override):

```bash
curl -sS https://distill.prometheus-potential.workers.dev/v1/keys \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"live","plan":"free","label":"ops"}'
```

The raw key is returned **once**. Prometheus Potential stores HMAC-SHA256(`KEY_PEPPER`, key) only.

## Stripe

- Product: `prod_VI8P43PELzxbFv` Distill Pro (Stripe product id; UI says Prometheus Potential Pro)
- Price: `price_1UHY8O6mDl8tBguf5Y9jg6vK` ($29/mo = 5,000 fast units / UTC day; deep = 3 units)
- Overage (documented, **not auto-billed in v1**): $0.01 / fast, $0.03 / deep. Over the included units → HTTP 429 + upgrade CTA.
- **Payment Link (Worker secret `DISTILL_PRO_PAYMENT_LINK`):** `https://buy.stripe.com/fZueV659Yeq25pw11rgIo03`. `/pricing` CTA opens this URL. `POST /billing/go` (and `POST /v1/billing/checkout` when Checkout is not configured) redirects with `client_reference_id=<key id>`.
  ```bash
  printf '%s' 'https://buy.stripe.com/fZueV659Yeq25pw11rgIo03' | npx wrangler secret put DISTILL_PRO_PAYMENT_LINK
  ```
- **Checkout Sessions:** `POST /v1/billing/checkout` with a Bearer key when `STRIPE_SECRET_KEY` is set.
- **Webhook (required to flip the key to Pro after payment — does not block the Payment Link):**
  - URL: `https://distill.prometheus-potential.workers.dev/webhooks/stripe`
  - Secret: `STRIPE_WEBHOOK_SECRET` (`whsec_…`)
  - Events: `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted`
  - `checkout.session.completed` upgrades the key with `setKeyPlan(..., "pro")`. The key id is resolved from (in order) `metadata.key_id`, `metadata.keyId`, **`client_reference_id`** (Payment Link), then `subscription_details.metadata.key_id`. Empty metadata does not block `client_reference_id`.

Until `STRIPE_WEBHOOK_SECRET` is set, successful Stripe payments will not automatically change the key’s plan.

Optional secret: `OPENAI_API_KEY` — if Workers AI fails or is unavailable, the API falls back to OpenAI (`gpt-4o-mini`), then to extractive heuristics so it still returns facts JSON.

## MCP

See [`mcp/README.md`](mcp/README.md) and the public guide [`/docs/agents`](https://distill.prometheus-potential.workers.dev/docs/agents). Tools: `distill`, `remember`, `recall`.

## Security

See [`SECURITY.md`](SECURITY.md). Do not commit `.dev.vars`, Stripe secrets, or `KEY_PEPPER`.

## Limits

| Plan | Fast units / UTC day | Deep | Remember / day | Req / min (key) | Req / min (IP) |
| --- | --- | --- | --- | --- | --- |
| Free | 50 | 3 units each | 200 | 60 | 120 |
| Pro ($29/mo) | 5,000 | 3 units each | 5,000 | 600 | 120 |

Over-limit → `429` + `Retry-After` + upgrade CTA. Overage list prices: $0.01 fast / $0.03 deep (soft cap in v1).

## Operator config

Non-secret vars in `wrangler.jsonc`:

- `LEGAL_ENTITY` (default Prometheus Potential)
- `CONTACT_EMAIL`
- `PUBLIC_ORIGIN` (API)
- `MARKETING_ORIGIN` (canonical HTML / sitemap; `https://prometheuspotential.com`)
- `CORS_ORIGINS` (comma-separated; empty = no `*` credentialed CORS)
- `STRIPE_PRICE_ID` / `STRIPE_PRODUCT_ID`

Worker **secret** (not in `wrangler.jsonc`):

- `DISTILL_PRO_PAYMENT_LINK`
- `KEY_PEPPER`, `ADMIN_TOKEN`
- optional `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `OPENAI_API_KEY`

No company registration numbers are invented on the legal pages.