```
 ██████╗ ██╗██████╗      ██████╗ ██████╗ ███╗   ██╗███╗   ██╗███████╗ ██████╗████████╗
██╔═══██╗██║██╔══██╗    ██╔════╝██╔═══██╗████╗  ██║████╗  ██║██╔════╝██╔════╝╚══██╔══╝
██║   ██║██║██║  ██║    ██║     ██║   ██║██╔██╗ ██║██╔██╗ ██║█████╗  ██║        ██║
██║▄▄ ██║██║██║  ██║    ██║     ██║   ██║██║╚██╗██║██║╚██╗██║██╔══╝  ██║        ██║
╚██████╔╝██║██████╔╝    ╚██████╗╚██████╔╝██║ ╚████║██║ ╚████║███████╗╚██████╗   ██║
 ╚══▀▀═╝ ╚═╝╚═════╝      ╚═════╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝  ╚═══╝╚══════╝ ╚═════╝   ╚═╝
        s i g n   i n   w i t h   q I D  ·  the address is the account
```

# qID Connect

Sign in with qID: post-quantum wallet login for BTX apps. A user proves
control of a BTX address with a post-quantum signature and that address IS
their account. No email, no password, no hybrid login. This is to BTX what
WalletConnect and Sign-In With Ethereum are to EVM, in one package.

This repo is the official integration surface of qID Connect, Phase 1:
connect, prove, sign in. It contains everything a website needs to add
"Sign in with qID" today, against the shipped PQ Wallet for BTX.

**Start here:**
- Try it live, no wallet needed: https://qid.dev/connect
- Integration guide: https://qid.dev/connect/integrate
- What changed: [`CHANGELOG.md`](CHANGELOG.md) · Report a vulnerability:
  [`SECURITY.md`](SECURITY.md)

## What is in the box

```
packages/server    @qid/connect-server   challenge, verify, account by address,
                                         session, QR rendezvous (proof + poll),
                                         durable SQLite stores + conformance tests
packages/widget    @qid/connect-widget   the "Sign in with qID" button, the
                                         dialog (QR, deep link, copy-paste), and
                                         the signed-in account chip + dropdown
examples/express-demo   a complete wallet-only site (register AND login, no email)
examples/next-demo      the same integration as Next.js drop-in files
examples/static-rewrite-demo   CDN page + standalone server + same-origin rewrite
docs/INTEGRATION.md     start here
docs/MIGRATION-from-email.md   for apps that bolted qID onto email accounts
docs/DESIGN.md          the design contract: mark, button, dialog, theming
assets/                 qid-mark.svg and the hero banner
tools/signer            the frozen v1 test signer CLI (generate proofs without a wallet)
```

## Try it in two minutes

```
bun install
bun test packages                 # frozen v1 vectors, e2e, QR + rotation flows
bun examples/express-demo/server.js
open http://localhost:8788
```

Sign in with a real PQ Wallet for BTX (v0.21+, Settings, qID Sign-In), or fake a
wallet for testing: click the button, copy the nonce and ts from the shown
request, then

```
bun tools/signer/btx-sign-ownership.mjs --random \
  --origin http://localhost:8788 --nonce <nonce> --ts <ts>
```

and paste the printed proof back into the dialog. To simulate the phone on
the "Scan with phone" tab instead, POST that same printed proof to
`http://localhost:8788/qid/proof`; the open dialog signs itself in within a
second or two.

## How it works

1. Your server issues a one-time challenge `{nonce, rp_origin, ts}` bound to
   your origin.
2. The user's wallet shows them your site and signs the challenge with their
   post-quantum login key (ML-DSA-44).
3. Your server verifies the proof with the frozen v1 verifier, rebuilds the
   address from the proof, and the verified address becomes (or finds) the
   account.
4. A signed HttpOnly session cookie keeps them signed in.

The dialog offers three transports: copy and paste against the desktop BTX
PQ Wallet, a QR for phone wallets, and a `btxqid://` deep link that opens
the installed PQ Wallet for BTX (v0.27+) directly. The QR carries the same
request plus a proof URL on your own server; the phone signs and posts the
proof there, and the browser that showed the QR claims the session with a
secret only it holds. There is no relay server anywhere: your backend is the
rendezvous, so login keeps working even if every piece of third-party
infrastructure on earth is down.

The connector is dynamic: every request shows a countdown, rotates itself
before it goes stale, and the server burns the superseded nonce, so a
screenshotted or stale request cannot be replayed.

After sign-in, `mountQidAccount` renders the signed-in account chip — the
address in a dropdown with click-to-copy, extensible menu items, and a
two-step Log out — so the signed-in state looks the same on every BTX app.

## The safety property

A qID sign-in proof can never move funds. Login proofs are signed under the
`BTX-qID/login-v1` domain tag; transactions sign under `TapSighash`. The
domains cannot collide, so the worst a fully malicious site can obtain is a
single-use login proof for its own origin. This is structural, not policy.

Claims we make and none we do not: resistant to quantum attacks, built on
NIST-standardized post-quantum cryptography (FIPS 204 ML-DSA-44), pending
independent audit. Nothing here is "unhackable" and we never say so.

## Frozen v1, forward compatible

The v1 proof format and verifier behavior are frozen. The verifier ships as
a byte-identical, hash-pinned copy and the full v1 test vector set runs in
the tests. New capability arrives as new versions, never as a mutation of
v1, and proofs carry explicit version and algorithm fields.

## Building a wallet?

The wallet-side signer SDK (request parsing, the normative signer rules, a
reference mobile approval screen) is available to wallet builders. Reach out
through qid.dev and we will get you access. The protocol layer underneath is
qID, the post-quantum identity core: https://qid.dev

## Names

The code is MIT licensed. The qID and qID Connect names and the qID mark are
not part of the license; see `TRADEMARKS.md`. Forks must use their own name.

## License

MIT
