identity.verify: bridge Turtini visitors into your external app as users

External-app blocks that declare the identity.verify capability get a short-lived signed token attesting the current visitor's Turtini identity. Your backend verifies the token against Turtini's public endpoint and upserts the user into your own data store — the visitor's Turtini account just became a user of your app, with no extra signup, no password copy, no OAuth dance.

When the token is issued:
• Visitor is signed in to Turtini (cookie or active session)
• Block declared identity.verify in its capability list AND the published version was approved by review
• Listing is in 'approved' state (not draft / pending / suspended)

If any condition fails, the host doesn't issue a token; your block sees identityToken === undefined and falls through to whatever flow you offer anonymous visitors (likely a sign-up form, or just the public view).

Token shape (HS256 JWT):
header.payload.signature — compact JWS
payload: { sub: uid, email, blockId, iat, exp, aud: 'marketplace-block' }
Signed with a platform secret. TTL is 5 minutes — short on purpose. Refresh by re-requesting via the issueBlockIdentityToken callable when needed (the host SDK does this automatically when the viewer transitions to signed-in mid-session).

How to verify from your backend:
POST https://us-central1-turtini.cloudfunctions.net/verifyBlockIdentity
Content-Type: application/json
{ "token": "<token-from-iframe>" }

Response (200):
{
"ok": true,
"uid": "abc123...",
"email": "[email protected]",
"blockId": "pixel-studios.testimonial",
"issuedAt": 1717000000,
"expiresAt": 1717000300
}

Response (401):
{ "ok": false, "error": "expired" | "bad_signature" | "malformed" }

Always verify on the backend, never on the frontend (don't ship the platform secret to browsers). Your frontend trusts what your backend tells it.

Upserting the user:
Once verified, the Turtini uid is the canonical identifier for the visitor. Match it to your own user table:
• First time you see a uid → create a new user record, store the Turtini uid + email
• Subsequent visits → look up by Turtini uid + return the existing record

Now the visitor is YOUR user too. Anything your app gives signed-in users — saved state, history, preferences, paid features — works transparently. The visitor never knew they "signed up" for your app; they just clicked install on the host org's Turtini Marketplace.

What this enables (the strategic frame):
The Marketplace isn't just "install a block." It's distribution + monetization + identity, in one substrate. People who built apps on their own first don't have to choose between staying solo and rewriting for Turtini — they can fold in later and treat Turtini both as a distribution channel for their app AND as an authentication provider that lets every Turtini account become a one-click user of their app.

For Turtini visitors: it feels like "every block on every site I visit just knows me." No 50 different sign-ups.
For external-app creators: it feels like "every Turtini account is a potential user of my app, and they sign up by clicking install."