Kino.Qx.CredentialsCell (Kino.Qx v0.3.0)

Copy Markdown View Source

Livebook Smart Cell that emits a %Qx.Hardware.Config{} binding (qx) for downstream cells to pipe circuits through.

Registered automatically when :kino_qx is loaded — appears in Livebook's "+ Smart" menu as "Qx Credentials" alongside the existing "Qx Snippet" cell.

Usage

In a notebook:

# Cell 1: this Smart Cell — fill in URL/region/backend, click Connect.
# It emits:
qx = %Qx.Hardware.Config{
  portal_url: "https://test.qxquantum.com",
  portal_token: System.fetch_env!("LB_PORTAL_TOKEN"),
  ibm_api_key: System.fetch_env!("LB_IBM_API_KEY"),
  ibm_crn: System.fetch_env!("LB_IBM_CRN"),
  ibm_region: "us-south",
  backend: "ibm_brisbane",
  optimization_level: 1,
  shots: 4096
}

# Cell 2: regular Elixir
circuit
|> Kino.Qx.run!(qx)
|> Qx.Draw.plot_counts(title: "Bell state")

Privacy invariant

This cell never accepts tokens into its UI. The three secrets live in Livebook secrets under these fixed names:

  • LB_PORTAL_TOKEN — qxportal qx_live_… bearer
  • LB_IBM_API_KEY — IBM Cloud API key
  • LB_IBM_CRN — IBM Service-CRN

Connect reads them via System.fetch_env!/1; to_source/1 emits code that does the same. Tokens never appear in cell state, never enter the .livemd file. Sharing a notebook does not leak any credential — the recipient must define their own secrets.

See the Livebook docs for how to add session/hub secrets: https://hexdocs.pm/livebook/secrets.html

Persisted attrs

Written into the .livemd file (none are secret):

  • portal_base_url — qxportal URL (default https://test.qxquantum.com)
  • ibm_region"us-south" or "eu-de"
  • last_backend_name — IBM backend chosen
  • optimization_level — 0..3, default 1
  • shots — 1..100_000, default 4096

Iron Law compliance

  • #7 — IBM job statuses come off the wire upstream in Qx.Hardware.Ibm and are matched against an allowlist there; this cell never coins atoms from network responses.
  • #8 — every handle_event/3 clause validates input shape: region in ["us-south", "eu-de"]; optimization_level integer in 0..3; shots integer in 1..100_000; backend name appears in the cached backends_list; portal_base_url matches the host allowlist.
  • #11 — no long-lived processes. The Connect task is short-lived (auth + list backends, then send/2 the result and exit). It is unlinked (Task.start/1) so a do_connect/1 raise can't wipe cell state; orphan risk is nil because the task self-terminates after one send/2.

Summary

Functions

child_spec(map)