# BitLogin

> A static, relay-backed portable Nostr account protocol. A familiar login
> name and password (or an existing `nsec`) unlocks a portable Nostr identity
> stored as encrypted "capsules" on public Nostr relays — no account server,
> no password-reset email, no database. Ships as an embeddable custom element
> plus a NIP-07-compatible `window.nostr` provider that any static site can
> drop in with one script tag.

## Integrate in one snippet

```html
<script type="module" src="/vendor/bitlogin/bitlogin.js"></script>
<bitlogin-auth
  vault-relays="wss://relay-one.example,wss://relay-two.example,wss://relay-three.example"
  discovery-relays="wss://discovery-one.example,wss://discovery-two.example">
</bitlogin-auth>
```

`bitlogin.js` and `cryptoWorker.js` (plus the shared chunk they both import)
must be deployed side by side — the main script resolves the worker's URL at
runtime relative to its own location, so this works from any path. For
production, self-host these files rather than depending on the demo
deployment above.

## What it gives your app

- A `<bitlogin-auth>` custom element (Shadow DOM, no CSS collisions) handling
  create account, sign in, forgot-password recovery via a 12-word phrase, and
  password rotation.
- A `window.nostr` provider shaped like the de facto NIP-07 interface
  (`getPublicKey`, `signEvent`, `getRelays`, `nip44.encrypt`/`decrypt`) —
  existing Nostr app code that already calls `window.nostr` works unmodified,
  same as it would against a browser extension (Alby, nos2x, …).
- `window.bitlogin` — installed as soon as the script loads, independent of
  login state: `{ version, isActiveSigner(), releaseSigner() }`. Use
  `window.bitlogin.isActiveSigner()` to tell whether BitLogin specifically
  (not another extension) currently backs `window.nostr`, and
  `releaseSigner()` to hand `window.nostr` back (a safe no-op if BitLogin
  doesn't hold it) when a user switches to a different signing method in
  your own UI.
- The `<bitlogin-auth>` element also exposes instance-scoped
  `claimSigner()` / `releaseSigner()` methods for the same purpose;
  `claimSigner()` is called automatically on every successful sign-in,
  sign-up, or recovery, and `releaseSigner()` on logout and on removal
  from the DOM — so by default a page with a single widget never needs to
  call either manually. Without this, `window.nostr` would stay pointed at
  a signed-out BitLogin provider forever, blocking a switch to another
  method without a page reload.
- `requestNwcConnection({ appName, reason })` on the element — asks the user
  to share an NWC wallet connection with the page's origin and resolves the
  full `nostr+walletconnect://` URI (or null if declined). Handles sign-in,
  one-tap approval for an origin-bound stored connection (connections are
  encrypted Connection Vault records that follow the user across devices),
  or first-time import via Bitcoin Connect's chooser / a pasted URI. REVEAL
  mode: the origin receives the full bearer credential — wallet-side budgets
  are the real security boundary. Requires `style-src-attr 'unsafe-inline'`
  in the host CSP. Fires `bitlogin-connection-granted` after each share.
- `offerNwcConnection(uri, { appName, label })` on the element — the inverse:
  the app obtained an NWC URI by its own means and offers the user a portable
  copy. Consent screen in the widget's own UI, never a silent save; resolves
  'saved' | 'declined' | 'already-saved' (same wallet+secret exists; origin
  binding refreshed, no UI) | 'unavailable' (no session/vault — treat as
  no-op). Safe to fire after every successful connect.
- Events on the element: `bitlogin-login` (`detail.publicKey`),
  `bitlogin-logout`, `bitlogin-signer-claimed`, `bitlogin-signer-released`
  (the last also fires on `window` when triggered via
  `window.bitlogin.releaseSigner()`), `bitlogin-connection-granted`
  (`detail.origin`).
- Private keys live in a dedicated Web Worker and the signing APIs return only
  public keys, signed events, and ciphertext. LIMIT: an embedded widget is
  same-origin with its host page, so a malicious or XSS-compromised host can
  reach the worker directly (including exportIdentity) and can overlay the
  consent UI. Treat the host page as trusted; embed only in sites you control.
- Removing a wallet connection from BitLogin deletes the stored copy only. It
  is NOT revocation -- spending authority is revoked at the wallet.
- Losing BOTH the password and the recovery phrase is permanent: there is no
  custodial recovery, by design. An account also depends on relays retaining
  its encrypted capsule; download the recovery export as an offline fallback.

## Key facts for integration

- Build or obtain a reviewed release, then self-host its complete module graph
  on the application's own origin and load it with `<script type="module">`.
- Don't give the element `id="bitlogin"` — browsers auto-expose elements with
  a matching `id`/`name` as a same-named global, which shadows
  `window.bitlogin`. Use `id="bitlogin-widget"` or similar.
- Configure relays via the `vault-relays` and `discovery-relays` attributes
  (comma-separated `wss://` URLs); omit to use BitLogin's small built-in
  bootstrap list.
- Human-chosen passwords are disabled. The widget always generates a
  high-entropy passphrase because a downloadable encrypted capsule can be
  guessed against offline forever.
- Recovery is a 12-word BIP-39-style phrase, independent of the password;
  losing the password never locks the user out if they still have the
  phrase.

## Reference docs

- [Integration guide](/docs.html) — full walkthrough with code samples.
- [Live account manager demo](/account.html) — create/login/recover, sign a
  test event, rotate password, export identity.
- [Protocol specification](https://github.com/PR0M3TH3AN/bitlogin/blob/main/docs/spec.md) —
  the full BitLogin protocol (crypto construction, capsule formats,
  relay architecture, threat model).
- [Second-factor / recovery options design notes](https://github.com/PR0M3TH3AN/bitlogin/blob/main/docs/second-factor.md)
  and [future recovery-path options](https://github.com/PR0M3TH3AN/bitlogin/blob/main/docs/future-recovery-options.md) —
  proposals, not all implemented; each notes its own status.
- [Source repository](https://github.com/PR0M3TH3AN/bitlogin) — monorepo:
  `packages/core` (protocol implementation), `packages/widget` (the embeddable
  element + provider), `packages/demo` (this site).

## Status

Experimental alpha, NOT independently audited. Verified with an in-memory
mock-relay test suite, real-browser end-to-end runs, and an internal
adversarial audit (2026-07-31) whose findings are recorded in
docs/connection-vault.md §19 and the CHANGELOG. See the README
in the source repository for the full implemented/deferred feature list.
