Flip-Pay subscription linking

If you already use Flip-Pay as your paywall vendor
(Press Gazette does — it's the fp.user cookie scoped to .your-domain),
we can verify subscription status without a single line of code on your side.

Setup

  1. DNS — you've already done this during verification: the CNAME
    oasy.your-domain → cname.oasy.ai.

  2. Vercel custom domain — already done by us when you verified.

  3. Tell us your Flip-Pay audience claim. We need the aud value in
    the JWT Flip-Pay issues for your publication. Ping support; it's a one-
    line config update on our side:

    UPDATE "Publisher"
    SET "subscriptionConnectUrl" = 'https://oasy.your-domain/api/oauth/connect-mcp',
        "flipPayAudience"        = '<your flip-pay aud claim, e.g. "pressgazette">'
    WHERE id = '<your orgId>';

That's the whole integration. No endpoint to build, no webhook to fire,
no shared secret to coordinate.

How it works

When a reader lands on oasy.your-domain/api/oauth/connect-mcp (via our
redirect from the consent screen), their browser automatically attaches
the fp.user cookie because we're on a subdomain of your domain. We:

  1. Parse the cookie's JSON value.
  2. Extract the embedded id_token JWT.
  3. Verify it against Flip-Pay's JWKS
    (https://accounts.flip-pay.com/...) with the configured audience.
  4. Trust the subscriber / email / name claims.
  5. Flip the SubscriptionLink row to confirmed, propagate
    tier=subscriber to tokens, redirect the reader back into the OAuth
    flow.

If the reader is signed in but not subscribed, we render "We see you're
signed in as X but you're not subscribed yet" with a link to your
checkout. If they're not signed in at all, we ask them to sign in to
your site first and reload.

What the reader sees

A 2-3 second redirect chain to your site, an automatic cookie read, and
then they're back in the agent's chat with a tier=subscriber token.
PAYWALL articles serve normally from that point on.

Cancellation

The next time the reader makes an MCP call after their Flip-Pay JWT
flips to non-subscriber, we downgrade their token to tier=free. The
meter starts counting again.